Viewing file: class.htmlform.php (48.61 KB) -rw-rw-r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/** * A HTML Form Processor PHP Class * * See the documentation for more info * * Read the LICENSE file, provided with the package, to find out how you can use this PHP script. * * If you don't find this file, please write an email to noname at nivelzero dot ro and you will be sent a copy of the license file * * For more resources visit {@link http://stefangabos.blogspot.com} * * @author Stefan Gabos <[email protected]> * @version 1.2 (last revision: September 04, 2008) * @copyright (c) 2006 - 2008 Stefan Gabos * @package HTMLForm * @example contactform.php * @example othercontrols.php * @example register.php * @example sendtoafriend.php * @example radio.php */
error_reporting(E_ALL);
class HTMLForm {
/** * Template folder to use * * Note that this refers to the general template of the form (the one that is in the /templates folder) * * Note that only the folder of the template you wish to use needs to be specified. Inside the folder * you <b>must</b> have the <b>template.xtpl</b> file which will be automatically used * * default is "default" * * @var string */ var $template;
/** * Path to Zebra Framework PHP Date Picker class * * This property has no default value * * @var string */ var $datePickerPath;
/** * The maximum allowed size for file uploads (in bytes) * * Default is 1024000 (1 MB) * * <i>Note that the actual limit in size of uploaded files is set in php.ini!. * * To find out what is the actual limit in size of uploaded files, use * * <code> * * ini_get('post_max_size'); * * </code> * * @var integer */ var $maxFileSize;
/** * This array contains all the elements added to the form * * @var array * * @access private */ var $controls;
/** * This array contains all the error messages generated by the form * * @var array * * @access private */ var $errors;
/** * Initializes the form * * @param string $formName Name of the form * * @param string $formMethod (optional) Submission method of the form * * Possible values are <b>POST</b> an <b>GET</b> * * Default is <b>POST</b> * * @param string $formAction (optional) Action of the form * * Default is an empty string (form will be submitted to itself) * * @param string $HTMLAttributes (optional) Extra HTML attributes for the form * * Default is an empty string * * @return void */ function HTMLForm($formName, $formMethod = 'POST', $formAction = '', $HTMLAttributes = '') {
// make these variables globals // the form's name global $HTMLForm_name;
// the form's submission method global $HTMLForm_method;
// default values for the form's properties // we do this so that the script will also work in PHP 4 $this->template = 'default';
$this->datePickerPath = '';
$this->maxFileSize = '1024000';
$this->custom = array();
$this->controls = array();
$this->user = array();
$this->blocks = array();
$this->errors = array();
// get the absolute path of the class. any further includes rely on this // and (on a windows machine) replace \ with / $this->absolutePath = preg_replace('/\\\/', '/', dirname(__FILE__));
// get the relative path of the class. ( by removing $_SERVER["DOCUMENT_ROOT"] from the it) // any HTML reference (to scripts, to stylesheets) in the template file should rely on this $this->relativePath = preg_replace('/' . preg_replace('/\//', '\/', $_SERVER['DOCUMENT_ROOT']) . '/i', '', $this->absolutePath);
// make the form name and submission method available to all the methods of the class $HTMLForm_name = $this->formName = $formName; $HTMLForm_method = $this->formMethod = strtoupper($formMethod); $this->formAction = $formAction == '' ? $_SERVER['REQUEST_URI'] : $formAction; $this->formHTMLAttributes = $HTMLAttributes;
// include the XSS filter class - the HTMLForm_control class extends this class require_once $this->absolutePath . '/includes/class.xssclean.php';
// include the class.htmlform_control.php file which contains the HTMLForm_control class which is // extended by all of the classes require_once $this->absolutePath . '/includes/class.htmlform_control.php'; }
/** * Adds controls to the form * * <i>The '&' symbol in the prefix of the method name is there to specifically instruct the method to return a reference!</i> * * <code> * /* * notice the use of the "&" symbol -> it's the way we can have a reference to the object in PHP4 * {@*} * * $obj = & $form->add('text', 'control_id', 'Default text'); * * </code> * * @param string $type Type of the control to add * * Controls that can be added to the form: * * - - button controls ({@link HTMLForm_button}) * - - CAPTCHA controls ({@link HTMLForm_captcha}) * - - checkbox controls ({@link HTMLForm_checkbox}) * - - date controls ({@link HTMLForm_date}) * - - file controls ({@link HTMLForm_file}) * - - hidden controls ({@link HTMLForm_hidden}) * - - html controls ({@link HTMLForm_html}) * - - image controls ({@link HTMLForm_image}) * - - label controls ({@link HTMLForm_label}) * - - password controls ({@link HTMLForm_password}) * - - radio button controls ({@link HTMLForm_radio}) * - - reset button controls ({@link HTMLForm_reset}) * - - select box controls ({@link HTMLForm_select}) * - - submit button controls ({@link HTMLForm_submit}) * - - text box controls ({@link HTMLForm_text}) * - - textarea controls ({@link HTMLForm_textarea}) * * @param mixed $arguments A list of arguments as required by the control you are adding. * * Click above on each available control/element to see what arguments it accepts * * @return reference Reference to the newly created object */ function &add($type) {
// class names have the "HTMLForm_" prefix $className = 'htmlform_' . strtolower($type);
// if control to add is the date control if ($className == 'htmlform_date') { // if file indicated by datePickerPath ecists if (file_exists($this->datePickerPath) && is_file($this->datePickerPath)) { // include the file containing the date picker class require_once $this->datePickerPath;
// if the included file does not contain the datePicker class if (!class_exists('datePicker')) {
trigger_error('<br>File <strong>class.datepicker.php</strong> at "' . $this->datePickerPath . '" does not contain the <strong>datePicker</strong> class!<br>Error', E_USER_ERROR);
}
} else {
trigger_error('<br>File <strong>class.datepicker.php</strong> was not found at "' . $this->datePickerPath . '". Make sure you correctly set the form\'s "datePickerPath" property!<br>Error', E_USER_ERROR); }
}
// include the file of class if not already included require_once $this->absolutePath . '/includes/class.' . $className . '.php';
// if included file contains such a class if (class_exists($className)) {
// convert arguments passed to the add() method to a string ready to be parsed by eval() // notice that first argument is ignored as it refers to the type of the control to add // and we don't have to pass that to the class $arguments = $this->getStrArgs(func_get_args(), 1); // creates the new object with the given arguments eval("\$obj = & new \$className(" . $arguments . ");");
// if the newly created object is a CAPTCHA control if ($className == 'htmlform_captcha') {
// set it's absolutePath property in order for the control // to be able to include the captcha.php file $obj->relativePath = $this->relativePath;
}
// add reference to the newly created object to the end of 'controls' array $this->controls[] = &$obj;
// return the identifier to the newly created object return $obj;
}
}
/** * Adds an user defined variable to be accessible in the form's template file * * <i>These variables are available in the form's template in the form {user.<variableName>}</i> * * <i>You can also add arrays and access them as {user.<variableName>.<key>}</i> * * @param mixed $variable Name of an user defined variable * * @param mixed $variableName Name through which the variable will be available in the template file * * @return void */ function addVar($variable, $variableName) {
$this->user[$variableName] = $variable;
}
/** * Parses an user defined block in the template * * @param string $blockName Name of the block to parse * * @param array $blockVars An associative array of name => value pairs of variables to be assigned to the parsed block * * @return void */ function parseBlock($blockName, $blockVars = '') {
$this->blocks[] = array('blockName' => $blockName, 'blockVars' => $blockVars);
}
/** * Returns a string with comma separated values generated from an array returned by func_get_args() function * * @param array $argumentsArray An array returned by func_get_args() function * * @param int $startFrom (optional) Starting from which item should the arguments be taken into consideration * * Default is '0', meaning all arguments are taken into consideration. If this should be '1', * then the first argument will be skipped, if '2' then the first two arguments will be * skipped and so on * * @return string a string with comma separated values generated from an array returned by func_get_args() function * * @access private */ function getStrArgs($argumentsArray = '', $startFrom = 0) {
$arguments = '';
// continue only if $argumentsArray is not empty and is an array if ($argumentsArray != '' && is_array($argumentsArray)) {
// iterates through the arguments, starting from $startFrom for ($i = $startFrom; $i < count($argumentsArray); $i++) {
// and creates the argument list to return $arguments .= ($arguments != '' ? ',' : '') . var_export($argumentsArray[$i], true);
}
}
// return the arguments ready to be eval'd return $arguments;
}
/** * Appends an error message to an error block's error messages * * You will need to use this method when you do custom validation in order to be able to send * any error message to one of the form's error blocks * * @param string $errorBlock The name of the error block to append the error message to * * @param string $errorMessage The error message to append * * @param string $bindToControl (Optional) The ID of the control to bind the error to. * * This has no importance unless you are relying on the script to automatically generate the form's * output for you. If you do so, than you MUST bind the error message to a control or the script will * not know where to show the error in the form! * */ function addError($errorBlock, $errorMessage, $bindToControl = '') {
// if error block has no error messages yet if (!isset($this->errors[$errorBlock])) {
// create the error message string for the specific error block $this->errors[$errorBlock] = array();
} // if the same exact message is not already in the error block if (!in_array($errorMessage, $this->errors[$errorBlock])) {
// append the error message to the existing messages $this->errors[$errorBlock][] = $errorMessage;
} // if error message is to be bound to one of the form's controls if ($bindToControl != '') {
// iterate throught the form's controls foreach ($this->controls as $control) {
// if a control with the given ID was found if ($control->attributes['id'] == $bindToControl) { // bind the error message to the control $control->setRule(array('auto' => array($errorBlock, $errorMessage)));
// don't look further return true;
}
} // if script gets this far, trigger an error message as it means a control with the given ID could not be found trigger_error('<br>Control with ID <strong>' . $bindToControl . '</strong> was not found in form.<br>Error', E_USER_ERROR);
}
}
/** * Checks if the rules set to the form's controls are obeyed * * @return boolean TRUE if every rule was obeyed, FALSE if not */ function validate() { $method = '_' . strtoupper($this->formMethod); global $$method; // continue only if form was submitted if (isset(${$method}['HTMLForm_formname']) && ${$method}['HTMLForm_formname'] == $this->formName) { // because the HTMLForm_formane and MAX_FILE_SIZE (where available) controls are // added through the template, they are not in the "controls" array therefore // we add them now (with the already submitted value) in order to make sure that // these two also are filtered for XSS injection $this->add('hidden', 'HTMLForm_formname', ${$method}['HTMLForm_formname']);
if (isset(${$method}['MAX_FILE_SIZE'])) {
$this->add('hidden', 'MAX_FILE_SIZE', ${$method}['MAX_FILE_SIZE']);
}
$formIsValid = true;
// iterate through the controls foreach (array_keys($this->controls) as $index) {
// reference to control $control = & $this->controls[$index];
// manage submitted value $control->getSubmittedValue();
// we use this variable to check one rule at a time. // if a rule is not obeyed, no further checks are made // so that only one error message per control is displayed at a time $valid = true;
// get some attributes of the control $attribute = $control->getAttributes(array('name', 'type', 'value', 'multiple'));
// if control was submitted and has rules assigned if (isset($control->submittedValue) && !empty($control->rules)) {
// iterate through rules assigned to the control foreach ($control->rules as $rule) {
// extract the rule name $ruleName = array_pop(array_keys($rule));
// extract rule properties $ruleAttributes = array_pop(array_values($rule));
// if rules were obeyed so far if ($valid) {
// check the rule's name switch (strtolower($ruleName)) {
// if "mandatory" case 'mandatory':
// if control is 'select' if ($attribute['type'] == 'select') {
// get the index which when selected indicated that 'nothing is selected' $notSelectedIndex = array_shift(array_keys($control->attributes['options']));
}
// the rule will be considered as not obeyed when if (
// control is 'password' or 'text' or 'textarea' and the 'value' attribute is empty (($attribute['type'] == 'password' || $attribute['type'] == 'text' || $attribute['type'] == 'textarea') && trim($attribute['value']) == '') || // control is 'file' and no file specified ($attribute['type'] == 'file' && trim($_FILES[$attribute['name']]['name']) == '') || // control is 'checkbox' or 'radio' and the control was not submitted (($attribute['type'] == 'checkbox' || $attribute['type'] == 'radio') && !$control->submittedValue) || // control is 'select', the 'multiple' attribute is set and control was not submitted ($attribute['type'] == 'select' && isset($attribute['multiple']) && !$control->submittedValue) || // control is 'select', the 'multiple' attribute is not set and the select control's first value is selected ($attribute['type'] == 'select' && !isset($attribute['multiple']) && strcmp($control->submittedValue, $notSelectedIndex) == 0)
) {
// add error message to indicated error block $this->addError($ruleAttributes[0], $ruleAttributes[1]);
// mark this control as invalid so that no further checkings are done for it, making sure that only one // error message is displayed at a time for each erroneous control $valid = false;
}
break;
// if "minlength" case 'minlength':
// the rule will be considered as not obeyed when if (
( // control is 'password' $attribute['type'] == 'password' || // control is 'text' $attribute['type'] == 'text' || // control is 'textarea' $attribute['type'] == 'textarea' ) && // the length of entered value is smaller than required strlen($attribute['value']) < $ruleAttributes[0]
) {
// add error message to indicated error block $this->addError($ruleAttributes[1], $ruleAttributes[2]);
// mark this control as invalid so that no further checkings are done for it, making sure that only one // error message is displayed at a time for each erroneous control $valid = false;
}
break;
// if "maxlength" case 'maxlength':
// the rule will be considered as not obeyed when if (
( // control is 'password' $attribute['type'] == 'password' || // control is 'text' $attribute['type'] == 'text' || // control is 'textarea' $attribute['type'] == 'textarea' ) && // the length of entered value is greater than required strlen($attribute['value']) > $ruleAttributes[0]
) {
// add error message to indicated error block $this->addError($ruleAttributes[1], $ruleAttributes[2]);
// mark this control as invalid so that no further checkings are done for it, making sure that only one // error message is displayed at a time for each erroneous control $valid = false;
}
break;
// if "email" case 'email':
if (
( // control is 'password' $attribute['type'] == 'password' || // control is 'text' $attribute['type'] == 'text' || // control is 'textarea' $attribute['type'] == 'textarea' ) && $attribute['value'] != '' && // not a valid email address !preg_match('/^([a-zA-Z0-9_\-\+\~\^\{\}]+[\.]?)+@{1}([a-zA-Z0-9_\-\+\~\^\{\}]+[\.]?)+\.[A-Za-z0-9]{2,}\$/', $attribute['value'])
) {
// add error message to indicated error block $this->addError($ruleAttributes[0], $ruleAttributes[1]);
// mark this control as invalid so that no further checkings are done for it, making sure that only one // error message is displayed at a time for each erroneous control $valid = false;
}
break;
// if "list of emails" case 'emails':
if (
( // control is 'password' $attribute['type'] == 'password' || // control is 'text' $attribute['type'] == 'text' || // control is 'textarea' $attribute['type'] == 'textarea' ) && $attribute['value'] != ''
) {
// convert string to an array of addresses $addresses = explode(',', $attribute['value']);
$validField = true;
// iterate through the addresses foreach ($addresses as $address) { // not a valid email address if (!preg_match('/^([a-zA-Z0-9_\-\+\~\^\{\}]+[\.]?)+@{1}([a-zA-Z0-9_\-\+\~\^\{\}]+[\.]?)+\.[A-Za-z0-9]{2,}\$/', trim($address))) {
$validField = false;
// stop checking the other addresses break;
}
}
// if any of of the addresses was incorrect if (!$validField) {
// add error message to indicated error block $this->addError($ruleAttributes[0], $ruleAttributes[1]);
// mark this control as invalid so that no further checkings are done for it, making sure that only one // error message is displayed at a time for each erroneous control $valid = false;
}
}
break;
// if digits only case 'digitsonly':
if (
( // control is 'password' $attribute['type'] == 'password' || // control is 'text' $attribute['type'] == 'text' || // control is 'textarea' $attribute['type'] == 'textarea' ) && // not a number !preg_match('/^[0-9]*\$/', $attribute['value'])
) {
// add error message to indicated error block $this->addError($ruleAttributes[0], $ruleAttributes[1]);
// mark this control as invalid so that no further checkings are done for it, making sure that only one // error message is displayed at a time for each erroneous control $valid = false;
}
break;
case 'compare':
if (
( // control is 'password' $attribute['type'] == 'password' || // control is 'text' $attribute['type'] == 'text' || // control is 'textarea' $attribute['type'] == 'textarea' ) && isset(${$method}[$ruleAttributes[0]]) &&
$control->submittedValue != ${$method}[$ruleAttributes[0]]
) {
// add error message to indicated error block $this->addError($ruleAttributes[1], $ruleAttributes[2]);
// mark this control as invalid so that no further checkings are done for it, making sure that only one // error message is displayed at a time for each erroneous control $valid = false;
}
break;
case 'captcha':
if (
( // control is 'text' $attribute['type'] == 'text' ) && // control's value is not the one showed in the picture md5(md5(md5(strtolower($control->submittedValue)))) != @$_COOKIE['captcha']
) {
// add error message to indicated error block $this->addError($ruleAttributes[0], $ruleAttributes[1]);
// mark this control as invalid so that no further checkings are done for it, making sure that only one // error message is displayed at a time for each erroneous control $valid = false;
}
break;
case 'custom':
// the total number of arguments of the rule $attributesNr = count($ruleAttributes);
$arguments = var_export($control->submittedValue, true);
// iterates through the arguments, starting from the second one as the first is the custom function's name // and all the way to count($ruleAttributes) - 2 as the last two arguments are the error block name and // the error message respectively for ($i = 1; $i < $attributesNr - 2; $i++) {
// creates the argument list to pass to the custom function $arguments .= ',' . var_export($ruleAttributes[$i], true);
}
// run the custom function if (!eval('return ' . $ruleAttributes[0] . '(' . $arguments . ');')) {
// add error message to indicated error block $this->addError($ruleAttributes[$attributesNr - 2], $ruleAttributes[$attributesNr - 1]);
// mark this control as invalid so that no further checkings are done for it, making sure that only one // error message is displayed at a time for each erroneous control $valid = false;
}
break;
}
}
}
}
// if control is not valid if (!$valid) {
// set the form as not being valid $formIsValid = false;
} //if if (
// "type" attribute is set isset($attribute['type']) &&
// type is password $attribute['type'] == 'password'
) {
// clear the value in the field $control->setAttributes(array('value' => ''));
}
//if if (
// 'type' attribute is set isset($attribute['type']) &&
// type is password $attribute['type'] == 'text'
) { // iterate through the control's rules foreach ($control->rules as $ruleProperties) { // if captcha rule is set if (array_key_exists('captcha', $ruleProperties)) {
// clear the value in the field $control->setAttributes(array('value' => ''));
// don't look further break; }
}
}
}
// after iterating through all the controls, // check if the form is valid if ($formIsValid) {
// and return true return true;
}
// if form was not submitted } else {
// return false return false;
}
}
/** * Renders the form * * @param string $template The form template to parse * * <b>Remember not to include <form> or other tags that appear in the general template set by the * {@link $template} property!</b> * * @param boolean $toVar (optional) If set to TRUE, the output will be returned instead of being outputted to the screen */ function render($template = '', $toVar = false) { // if the xtemplate class is not already included if (!class_exists('XTemplate')) {
// if the file exists if (file_exists($this->absolutePath . '/includes/class.xtemplate.php')) {
// include the xtemplate class require_once $this->absolutePath . '/includes/class.xtemplate.php';
// if the file does not exists } else { trigger_error('<br>File ' . $this->absolutePath . '/includes/class.xtemplate.php could not be found!<br>Error', E_USER_ERROR);
}
}
// start rendering of the main template file $main_xtpl = new XTemplate($this->absolutePath . '/templates/' . $this->template . '/template.xtpl');
// if a user-defined template was specified if ($template != '') {
// start rendering of the form template $xtpl = new XTemplate($template);
// makes user submitted variables available in the template file foreach ($this->user as $variableName => $value) {
if (!is_array($value) || count($value) > 1) {
$xtpl->assign($variableName, $value);
} else {
$xtpl->assign_file($variableName, array_shift($value));
}
}
$controls = array();
// iterate through the controls assigned to the form foreach ($this->controls as $control) {
// read some attributes of the control $attributes = $control->getAttributes('id');
// add generated HTML code to the $controls array $controls[$attributes['id']] = $control->toHTML();
}
// assign controls $xtpl->assign('controls', $controls);
// if there are any error messages if (!empty($this->errors)) {
// iterate through each error block foreach ($this->errors as $errorBlock => $errorMessages) {
// iterate through each message of the error block foreach ($errorMessages as $errorMessage) {
// assign the message itself $main_xtpl->assign('message', $errorMessage);
// parse the error_msg block from the main template giving the actual aspect of the error message $main_xtpl->parse('main.error_msg.entry');
}
$main_xtpl->parse('main.error_msg'); // replace the array of messages with the newly created string $this->errors[$errorBlock] = $main_xtpl->text('main.error_msg');
// reset this block as we use it just for applying templates to the error messages $main_xtpl->reset('main.error_msg');
}
// assign error messages $xtpl->assign('errors', $this->errors);
// iterate through error message blocks foreach (array_keys($this->errors) as $errorBlock) {
// and parse them $xtpl->parse('main.' . $errorBlock);
} }
// parse user defined blocks foreach ($this->blocks as $blockInfo) {
// if there are variables to be passed to the parsed block if (is_array($blockInfo['blockVars'])) {
// iterate through the available variables foreach ($blockInfo['blockVars'] as $varName => $varValue) {
// if value is NOT an array OR is an array with more than one items if (!is_array($varValue) || count($varValue) > 1) {
// assign as variable $xtpl->assign($varName, $varValue);
} else {
// assign as file $xtpl->assign_file($varName, array_shift($varValue));
}
}
}
// parse the custom block $xtpl->parse('main.' . $blockInfo['blockName']);
}
// parse the form template $xtpl->parse('main');
// and store the result in the $html variable $html = $xtpl->text('main');
// if output is not template driven but automatically generated by the script } else { // assume that we have to sort controls so that labels for checkbox and radio buttons are rendered AFTER the control // they are assigned to $sort = true; // while the control's array needs sorting while ($sort) { // presume that everything has been sorted out $sort = false;
// iterate through the form's controls foreach ($this->controls as $position => $control) {
// if control is a label (has the 'for' attribute set) if (isset($control->attributes['for'])) {
// check to see if it is attached to a checkbox or a radio button control foreach ($this->controls as $pos => $ctrl) {
if (
// if the control has its 'type' attribute set (because not all controls have it - i.e. labels) isset($ctrl->attributes['type']) &&
// type is 'checkbox' or 'radio' ($ctrl->attributes['type'] == 'checkbox' || $ctrl->attributes['type'] == 'radio') &&
// the control is the actual control that the label is attached to $ctrl->attributes['id'] == $control->attributes['for'] ) {
// the label is in the wrong position (checkbox/radio button is AFTER the label) if ($pos > $position) {
// tell the script to further look for labels in wrong possitions $sort = true;
// set the new order in the controls property by merging $this->controls = array_merge(
// what is in the array up to where the label having the wrong position has been found array_slice($this->controls, 0, $position),
// with the checkbox/radio button that the label is attached to array_slice($this->controls, $pos, 1),
// with the label in the right position array_slice($this->controls, $position, 1),
// everything in between the two controls (checkbox/radio button and associated label) array_slice($this->controls, $position + 1, $pos - $position - 1),
// with everything that is after the checkbox/radio button that the label is attached to array_slice($this->controls, $pos + 1)
);
// stop both for...each and jump out to the while so we check again for labels in wrong possition break 2;
// if label is before the checkbox/radio button control BUT not right before the control } elseif ($pos < $position && $position - $pos > 1) {
// tell the script to further look for labels in wrong possitions $sort = true;
// set the new order in the controls property by merging $this->controls = array_merge(
// what is in the array up to where the checkbox/radio button having the label in the wron position has been found array_slice($this->controls, 0, $pos + 1),
// with the label in the right position array_slice($this->controls, $position, 1),
// everything in between the two controls (checkbox/radio button and associated label) array_slice($this->controls, $pos + 1, $position - $pos - 1),
// with everything that is after the label array_slice($this->controls, $position + 1)
); // stop both for...each and jump out to the while so we check again for labels in wrong possition break 2;
}
}
} }
}
} $html = ''; $row = '';
// iterate through the form's controls foreach ($this->controls as $control) { // as these two controls are automatically added to the forms controls (so that are scanned for XML injections // at the very top of the validate() method) we need to skip them if (
$control->attributes['id'] != 'HTMLForm_formname' &&
$control->attributes['id'] != 'MAX_FILE_SIZE'
) { // if if (
// control is not a checkbox or a radio button !(
isset($control->attributes['type']) &&
($control->attributes['type'] == 'checkbox' || $control->attributes['type'] == 'radio')
) &&
// and the 'nobr' attribute is not set !isset($control->attributes['nobr'])
) { // if $row is empty (meaning that this is the only control on this row) if ($row == '') {
// parse the appropriate block in the template $main_xtpl->assign('content', $control->toHTML());
$main_xtpl->parse('main.container.control');
$main_xtpl->parse('main.container'); // add resulting content to the variable $html .= $main_xtpl->text('main.container');
$main_xtpl->reset('main.container');
// if $row is NOT empty (meaning that there are also other controls on this row) } else {
// parse the appropriate block in the template $main_xtpl->assign('content', $control->toHTML());
$main_xtpl->parse('main.container.column');
$row .= $main_xtpl->text('main.container.column');
$main_xtpl->reset('main.container.column');
$main_xtpl->assign('content', $row);
$main_xtpl->parse('main.container.control');
$main_xtpl->parse('main.container.clear');
$main_xtpl->parse('main.container');
// add resulting content to the variable $html .= $main_xtpl->text('main.container');
$main_xtpl->reset('main.container'); }
// reset the $row variable $row = '';
// if we're talking about an entry in a row } else {
// parse the appropriate block in the template $main_xtpl->assign('content', $control->toHTML());
$main_xtpl->parse('main.container.column');
// add resulting content to the row $row .= $main_xtpl->text('main.container.column');
$main_xtpl->reset('main.container.column');
}
} $boundRules = array(); // if there are rules defined for the control if (!empty($control->rules)) { // iterate through the defined rules foreach ($control->rules as $rule) { // iterate through each rule's properties foreach ($rule as $properties) { $boundRules[] = $properties[0];
// if there is an error issued for the current property if (array_key_exists($properties[0], $this->errors)) { // iterate through each message of the error block foreach ($this->errors[$properties[0]] as $errorMessage) {
// assign the message itself $main_xtpl->assign('message', $errorMessage);
// parse the error_msg block from the main template giving the actual aspect of the error message $main_xtpl->parse('main.error_msg.entry');
}
$main_xtpl->parse('main.error_msg');
// add the error message to the output generated so far $html .= $main_xtpl->text('main.error_msg');
// reset this block as we use it just for applying templates to the error messages $main_xtpl->reset('main.error_msg');
// because more than one control can have its errors displayed in the same error block, // make sure that an error block is displayed only once unset($this->errors[$properties[0]]);
}
}
}
}
} // look for unbound (orphane) rules $unboundRules = array_diff(array_keys($this->errors), array_values($boundRules)); if (!empty($unboundRules)) { $ruleBlock = array_shift($unboundRules); $ruleMessage = array_pop($this->errors[$ruleBlock]); trigger_error('<br>Unbound error message!<br>You requested that the script to generate the form\'s output automatically.<br>In this case, error messages set manually through the <strong>addError()</strong> method MUST be bound to one of the form\'s controls.<br>In this case, the problem is caused by the following call: <strong>addError(' . $ruleBlock . ', ' . $ruleMessage . ')</strong> where the error message is not bound to any of the form\'s controls.<br>Please correct this by adding an additional parameter when calling the <strong>addError()</strong> method so that it becomes <strong>addError(' . $ruleBlock . ', ' . $ruleMessage . ', control_id_to_bind_to)</strong> <br>Error', E_USER_ERROR);
}
}
// finally assign the content resulted from parsing the form template $main_xtpl->assign('content', $html);
// assign some variables used in the main template $main_xtpl->assign('formName', $this->formName);
$main_xtpl->assign('formMethod', $this->formMethod);
$main_xtpl->assign('formAction', $this->formAction);
$main_xtpl->assign('HTMLAttributes', $this->formHTMLAttributes);
$main_xtpl->assign('templatePath', $this->relativePath . '/templates/' . $this->template);
// if form contains at least one file control (in some PHP installations names are in lower case...) if (in_array('HTMLForm_file', get_declared_classes()) || in_array('htmlform_file', get_declared_classes())) {
// assign the maxFileSize property $main_xtpl->assign('maxFileSize', $this->maxFileSize);
// parse the MAX_FILE_SIZE hidden field $main_xtpl->parse('main.file_upload');
// parse encoding type $main_xtpl->parse('main.enctype');
}
// parse the main template $main_xtpl->parse('main');
// and store the result in the $html variable $html = $main_xtpl->text('main');
// if $toVar argument was TRUE if ($toVar) {
// return the result return $html;
// if $toVar argument was FALSE } else {
// output the content echo $html;
}
}
}
?>
|