<?php
/*
* BuilderFormElement
*
* Copyright(c) 2010, Thomas Shone
* Licensed under the Creative Commons Attribution 3.0 Unported License.
* http://www.shone.co.za
*
* Constructs forms elements from meta data
*/
class BuilderFormElement
{
private $aMeta;
private $aData;
private $aClasses;
private $aExtras;
private $aAttributes;
public function Build($aMeta, $aData = array())
{
$this->aMeta = $aMeta;
$this->aData = $aData;
$this->aClasses = array();
$this->aExtras = array();
$this->aAttributes = array();
$aMethods = get_class_methods(__CLASS__);
$sRenderFunction = 'Render' . ucwords($aMeta['type']);
if (in_array($sRenderFunction, $aMethods))
{
$this->___CheckMeta();
$this->___ConstructAttributes();
$this->___ConstructExtras();
$this->___ConstructClasses();
return $this->$sRenderFunction();
}
}
private function ___GetData()
{
// Don't attempt to set data for the following elements
$aExcludeList = array('submit');
if (in_array($this->aMeta['type'], $aExcludeList))
{
return $this->aMeta['value'];
}
// Look up post specific input match
$mValue = Input::GetPost($this->aMeta['name']);
if ($mValue)
{
return $mValue;
}
// If nothing there, look up non-post specific input match
$mValue = Input::Get($this->aMeta['name']);
if ($mValue)
{
return $mValue;
}
// Look up data passed
if (!empty($this->aData[$this->aMeta['name']]))
{
return $this->aData[$this->aMeta['name']];
}
if (!empty($this->aMeta['value']))
{
return $this->aMeta['value'];
}
return '';
}
private function ___CheckMeta()
{
if (empty($this->aMeta['name']))
{
throw new Exception('Name Required.');
}
if (empty($this->aMeta['type']))
{
throw new Exception('Type Required.');
}
$this->aMeta['value'] = $this->___GetData();
}
private function ___ConstructAttributes()
{
if (empty($this->aMeta['id']))
{
$this->aMeta['id'] = $this->aMeta['name'];
}
// Check validation for attributes
!empty($this->aMeta['validation']['length']['max']) && $this->aAttributes['maxlength'] = $this->aMeta['validation']['length']['max'];
!empty($this->aMeta['validation']['length']['min']) && $this->aAttributes['size'] = $this->aMeta['validation']['length']['min'];
$aFields = array('type', 'name', 'id', 'value', 'cols', 'rows', 'class', 'size', 'maxlength', 'hint');
foreach ($aFields as $sField)
{
if (!empty($this->aMeta[$sField]))
{
switch ($sField)
{
case 'name':
$this->aAttributes[$sField] = 'input['. $this->aMeta[$sField] .']';
break;
case 'hint':
$this->aAttributes['rel'] = 'hint:'. $this->aMeta[$sField];
default:
$this->aAttributes[$sField] = $this->aMeta[$sField];
break;
}
}
}
}
private function ___ConstructExtras()
{
if (!empty($this->aMeta['image']))
{
$this->aExtras[] = '<img id="'. $this->aMeta['name'] .'-image" src="'. BuildUrl('html/images/'. $this->aMeta['image']) .'" />';
}
if (!empty($this->aMeta['description']))
{
$this->aExtras[] = '<span id="'. $this->aMeta['name'] .'-description" class="description">'. $this->aMeta['description'] .'</span>';
}
$aInlineErrors = Messages::GetInlineErrors($this->aMeta['name']);
if ($aInlineErrors && count($aInlineErrors))
{
$this->aExtras[] = '<span class="message-error message-error-inline">'. implode('<br/>', $aInlineErrors) .'</span>';
}
}
private function ___ConstructClasses()
{
if ($this->aMeta['type'] == 'submit')
{
$this->aClasses[] = 'submit';
}
if (!empty($this->aMeta['render']['class']))
{
$this->aClasses[] = $this->aMeta['render']['class'];
}
// Build Validation
if (!empty($this->aMeta['validation']))
{
$aFields = array();
$aFields[] = !empty($this->aMeta['validation']['required']) ? 'required' : 'optional';
if (!empty($this->aMeta['validation']['match']))
{
switch ($this->aMeta['validation']['match'])
{
case 'alphanumeric':
$aFields[] = 'custom[noSpecialCaracters]';
break;
case 'alpha':
$aFields[] = 'custom[onlyLetter]';
break;
case 'numeric':
$aFields[] = 'custom[onlyNumber]';
break;
case 'date':
$aFields[] = 'custom[date]';
break;
case 'email':
$aFields[] = 'custom[email]';
break;
case 'telephone':
$aFields[] = 'custom[telephone]';
break;
case 'url':
$aFields[] = 'custom[url]';
break;
case 'ajax':
$aFields[] = 'ajax[' . $this->aMeta['validation']['type'] . ']';
break;
default:
break;
}
}
if (!empty($this->aMeta['validation']['confirm']))
{
$aFields[] = 'confirm['. $this->aMeta['validation']['confirm'] .']';
}
if (
!empty($this->aMeta['validation']['length']['min']) &&
!empty($this->aMeta['validation']['length']['max'])
)
{
$aFields[] = 'length[' . $this->aMeta['validation']['length']['min'] . ',' . $this->aMeta['validation']['length']['max'] . ']';
}
$this->aClasses[] = 'validate[' . implode(',', $aFields) .']';
}
}
private function RenderAttributes()
{
$sResult = '';
foreach ($this->aAttributes as $sKey => $sValue)
{
$sResult .= ' ' . $sKey . '="' . $sValue . '"';
}
return $sResult;
}
private function RenderExtras()
{
return implode(' ', $this->aExtras);
}
private function RenderClasses()
{
return implode(' ', $this->aClasses);
}
private function RenderLabel()
{
return $this->aMeta['label'];
}
private function RenderBasic()
{
return "\n\t" . '<input' . $this->RenderAttributes() . ' class="' . $this->RenderClasses() . '" /> ' . $this->RenderExtras();
}
private function RenderText()
{
return $this->RenderBasic();
}
private function RenderTextarea()
{
$sValue = '';
if (!empty($this->aAttributes['value']))
{
$sValue = $this->aAttributes['value'];
unset($this->aAttributes['value']);
}
return "\n\t" . '<textarea' . $this->RenderAttributes() . ' class="' . $this->RenderClasses() . '" />' . $sValue . '</textarea> ' . $this->RenderExtras();
}
private function RenderPassword()
{
return $this->RenderBasic();
}
private function RenderSubmit()
{
return $this->RenderBasic();
}
private function RenderFile()
{
return $this->RenderBasic();
}
private function RenderCheckbox()
{
return $this->RenderBasic();
}
private function RenderHidden()
{
return $this->RenderBasic();
}
private function RenderRadioList()
{
$sResult = '';
$sId = $this->aAttributes['id'];
foreach ($this->aMeta['list'] as $aEntry)
{
$sName = !empty($aEntry['name'])
? $aEntry['name']
: $aEntry['value'];
unset($this->aAttributes['checked']);
$this->aAttributes['value'] = $aEntry['value'];
$this->aAttributes['id'] = $sId .'-'. $sName;
$sLabel = $sName;
if (!empty($aEntry['image']))
{
$sLabel = '<img src="'. BuildUrl('html/images/'. $aEntry['image']) .'" /> '. $sLabel;
}
if (!empty($this->aMeta['value']) && $aEntry['value'] == $this->aMeta['value'])
{
$this->aAttributes['checked'] = 'true';
}
$sResult .= '<input '. $this->RenderAttributes() .'><label for="'. $this->aAttributes['id'] .'">'. $sLabel .'</label><br/>' ."\n";
}
return $sResult;
}
private function RenderCheckList()
{
return $this->RenderRadioList();
}
private function RenderSelectList()
{
$sResult = '';
$sResult .= '<select '. $this->RenderAttributes() .'>' ."\n";
if (!empty($this->aMeta['list']))
{
foreach ($this->aMeta['list'] as $aEntry)
{
$sLabel = !empty($aEntry['name'])
? $aEntry['name']
: $aEntry['value'];
if (!empty($aEntry['image']))
{
$sLabel = '<img src="/html/images/'. $aEntry['image'] .'" /> '. $sLabel;
}
$sResult .= '<option value="'. $aEntry['value'] .'">'. $sLabel .'</option>' ."\n";
}
}
$sResult .= '</select>' ."\n";
return $sResult;
}
private function RenderList()
{
$sResult = '';
if (!empty($this->aMeta['script']))
{
$sResult .= "<script>
$(document).ready(function()
{
$.getJSON('" . BuildUrl($this->aMeta['script']) . "',
function(data)
{
$.each(data, function(i,item)
{
$('#" . $this->aMeta['id'] . "').append('<option value=\"' + item.value + '\" ' + (\"". $this->aMeta['value'] ."\" == item.value ? 'selected=\"true\"' : '') + '>' + item.name + '</option>');
});
});
});
</script>";
}
switch ($this->aMeta['render-mode'])
{
case 'radio':
$this->aAttributes['type'] = 'radio';
$sResult .= $this->RenderRadioList();
break;
case 'checkbox':
$this->aAttributes['type'] = 'checkbox';
$sResult .= $this->RenderCheckList();
break;
case 'select':
default:
$sResult .= $this->RenderSelectList();
break;
}
return $sResult . $this->RenderExtras();;
}
// TODO: Implement these
/* private function RenderTags()
{
$sResult = '<input '. $this->RenderAttributes() .'>' . $this->RenderExtras() ."\n";
$sResult .= "<script>
$(document).ready(function() {
$('#" . $this->aMeta['id'] . "').tokenInput('" . $this->aMeta['script'] . "', {});
});
</script>";
return $sResult;
}
private function RenderCaptcha()
{
$sResult = '<img src="' . BuildUrl('captcha/index') . '?sid=' . md5(uniqid(time())) . '"><br/>';
$sResult .= $this->RenderBasic();
return $sResult;
}*/
}