* @author Bertrand Mansion * @author Alexey Borzov * @copyright 2001-2009 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License 3.01 * @version CVS: $Id: QuickForm.php,v 1.166 2009/04/04 21:34:02 avb Exp $ * @link http://pear.php.net/package/HTML_QuickForm */ /** * Validation rules known to HTML_QuickForm * @see HTML_QuickForm::registerRule(), HTML_QuickForm::getRegisteredRules(), * HTML_QuickForm::isRuleRegistered() * @global array $GLOBALS['_HTML_QuickForm_registered_rules'] */ /** * Error codes for HTML_QuickForm * * Codes are mapped to textual messages by errorMessage() method, if you add a * new code be sure to add a new message for it to errorMessage() * * @see HTML_QuickForm::errorMessage() */ define('QUICKFORM_OK', 1); define('QUICKFORM_ERROR', -1); define('QUICKFORM_INVALID_RULE', -2); define('QUICKFORM_NONEXIST_ELEMENT', -3); define('QUICKFORM_INVALID_FILTER', -4); define('QUICKFORM_UNREGISTERED_ELEMENT', -5); define('QUICKFORM_INVALID_ELEMENT_NAME', -6); define('QUICKFORM_INVALID_PROCESS', -7); define('QUICKFORM_DEPRECATED', -8); define('QUICKFORM_INVALID_DATASOURCE', -9); /** * Class HTML_QuickForm * Create, validate and process HTML forms * * @category HTML * @package HTML_QuickForm * @author Adam Daniel * @author Bertrand Mansion * @author Alexey Borzov * @version Release: 3.2.11 */ class HTML_QuickForm extends HTML_Common { const MAX_ELEMENT_ARGUMENT = 10; private $dateTimePickerLibraryAdded; /** * Array containing the form fields * @since 1.0 * @var array * @access private */ public $_elements = array(); /** * Array containing element name to index map * @since 1.1 * @var array * @access private */ public $_elementIndex = array(); /** * Array containing indexes of duplicate elements * @since 2.10 * @var array * @access private */ public $_duplicateIndex = array(); /** * Array containing required field IDs * @since 1.0 * @var array * @access private */ public $_required = array(); /** * Prefix message in javascript alert if error * @since 1.0 * @var string * @access public */ public $_jsPrefix = 'Invalid information entered.'; /** * Postfix message in javascript alert if error * @since 1.0 * @var string * @access public */ public $_jsPostfix = 'Please correct these fields.'; /** * Datasource object implementing the informal * datasource protocol * @since 3.3 * @var object * @access private */ public $_datasource; /** * Array of default form values * @since 2.0 * @var array * @access private */ public $_defaultValues = array(); /** * Array of constant form values * @since 2.0 * @var array * @access private */ public $_constantValues = array(); /** * Array of submitted form values * @since 1.0 * @var array * @access private */ public $_submitValues = array(); /** * Array of submitted form files * @since 1.0 * @var integer * @access public */ public $_submitFiles = array(); /** * Value for maxfilesize hidden element if form contains file input * @since 1.0 * @var integer * @access public */ public $_maxFileSize = 1048576; // 1 Mb = 1048576 /** * Flag to know if all fields are frozen * @since 1.0 * @var boolean * @access private */ public $_freezeAll = false; /** * Array containing the form rules * @since 1.0 * @var array * @access private */ public $_rules = array(); /** * Form rules, global variety * @var array * @access private */ public $_formRules = array(); /** * Array containing the validation errors * @since 1.0 * @var array * @access private */ public $_errors = array(); /** * Note for required fields in the form * @var string * @since 1.0 * @access private */ public $_requiredNote = '* denotes required field'; /** * Whether the form was submitted * @var boolean * @access private */ public $_flagSubmitted = false; /** * Class constructor * @param string $formName Form's name. * @param string $method (optional)Form's method defaults to 'POST' * @param string $action (optional)Form's action * @param string $target (optional)Form's target defaults to '_self' * @param mixed $attributes (optional)Extra attributes for
tag * @param bool $trackSubmit (optional)Whether to track if the form was submitted by adding a special hidden field * @access public */ public function __construct( $formName = '', $method = 'post', $action = '', $target = '', $attributes = null, $trackSubmit = false ) { parent::__construct($attributes); $method = (strtoupper($method) == 'GET') ? 'get' : 'post'; $action = ($action == '') ? api_get_self() : $action; $target = empty($target) ? array() : array('target' => $target); $form_id = $formName; if (isset($attributes['id']) && !empty($attributes['id'])) { $form_id = Security::remove_XSS($attributes['id']); } $attributes = array( 'action' => $action, 'method' => $method, 'name' => $formName, 'id' => $form_id ) + $target; $this->updateAttributes($attributes); if (!$trackSubmit || isset($_REQUEST['_qf__' . $formName])) { $this->_submitValues = 'get' == $method ? $_GET : $_POST; $this->_submitFiles = $_FILES; $this->_flagSubmitted = count($this->_submitValues) > 0 || count($this->_submitFiles) > 0; } if ($trackSubmit) { unset($this->_submitValues['_qf__' . $formName]); $this->addElement('hidden', '_qf__' . $formName, null); } if (preg_match('/^([0-9]+)([a-zA-Z]*)$/', ini_get('upload_max_filesize'), $matches)) { // see http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes switch (strtoupper($matches['2'])) { case 'G': $this->_maxFileSize = $matches['1'] * 1073741824; break; case 'M': $this->_maxFileSize = $matches['1'] * 1048576; break; case 'K': $this->_maxFileSize = $matches['1'] * 1024; break; default: $this->_maxFileSize = $matches['1']; } } } /** * Returns the current API version * * @since 1.0 * @access public * @return float */ function apiVersion() { return 3.2; } /** * Registers a new element type * * @param string $typeName Name of element type * @param string $include Include path for element type * @param string $className Element class name * @since 1.0 * @access public * @return void */ public function registerElementType($typeName, $include, $className) { $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($typeName)] = array($include, $className); } /** * Registers a new validation rule * * @param string $ruleName Name of validation rule * @param string $type Either: 'regex', 'function' or 'rule' for an HTML_QuickForm_Rule object * @param string $data1 Name of function, regular expression or HTML_QuickForm_Rule classname * @param string $data2 Object parent of above function or HTML_QuickForm_Rule file path * @since 1.0 * @access public * @return void */ public static function registerRule($ruleName, $type, $data1, $data2 = null) { $registry =& HTML_QuickForm_RuleRegistry::singleton(); $registry->registerRule($ruleName, $type, $data1, $data2); } /** * Returns true if element is in the form * * @param string $element form name of element to check * @since 1.0 * @access public * @return boolean */ public function elementExists($element = null) { return isset($this->_elementIndex[$element]); } /** * Initializes default form values * * @param array $defaultValues values used to fill the form * @param mixed $filter (optional) filter(s) to apply to all default values * @since 1.0 * @access public */ public function setDefaults($defaultValues = null, $filter = null) { if (is_array($defaultValues)) { if (isset($filter)) { if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) { foreach ($filter as $val) { if (!is_callable($val)) { throw new \Exception('Callback function does not exist in QuickForm::setDefaults()'); } else { $defaultValues = $this->_recursiveFilter($val, $defaultValues); } } } elseif (!is_callable($filter)) { throw new \Exception('Callback function does not exist in QuickForm::setDefaults()'); } else { $defaultValues = $this->_recursiveFilter($filter, $defaultValues); } } $this->_defaultValues = self::arrayMerge($this->_defaultValues, $defaultValues); $this->_constantValues = $this->_defaultValues; foreach (array_keys($this->_elements) as $key) { $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this); } } } /** * Initializes constant form values. * These values won't get overridden by POST or GET vars * * @param array $constantValues values used to fill the form * @param mixed $filter (optional) filter(s) to apply to all default values * * @since 2.0 * @access public * @return void */ public function setConstants($constantValues = null, $filter = null) { if (is_array($constantValues)) { if (isset($filter)) { if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) { foreach ($filter as $val) { if (!is_callable($val)) { throw new \Exception("Callback function does not exist in QuickForm::setConstants()"); } else { $constantValues = $this->_recursiveFilter($val, $constantValues); } } } elseif (!is_callable($filter)) { throw new \Exception("Callback function does not exist in QuickForm::setConstants()"); } else { $constantValues = $this->_recursiveFilter($filter, $constantValues); } } $this->_constantValues = HTML_QuickForm::arrayMerge($this->_constantValues, $constantValues); foreach (array_keys($this->_elements) as $key) { $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this); } } } /** * Sets the value of MAX_FILE_SIZE hidden element * * @param int $bytes Size in bytes * @since 3.0 * @access public * @return void */ public function setMaxFileSize($bytes = 0) { if ($bytes > 0) { $this->_maxFileSize = $bytes; } if (!$this->elementExists('MAX_FILE_SIZE')) { $this->addElement('hidden', 'MAX_FILE_SIZE', $this->_maxFileSize); } else { $el =& $this->getElement('MAX_FILE_SIZE'); $el->updateAttributes(array('value' => $this->_maxFileSize)); } } /** * Returns the value of MAX_FILE_SIZE hidden element * * @since 3.0 * @access public * @return int max file size in bytes */ public function getMaxFileSize() { return $this->_maxFileSize; } /** * Creates a new form element of the given type. * * This method accepts variable number of parameters, their * meaning and count depending on $elementType * * @param string $elementType type of element to add (text, textarea, file...) * @since 1.0 * @access public * @return HTML_QuickForm_Element * @throws HTML_QuickForm_Error */ public function &createElement($elementType) { $args = func_get_args(); $element = $this->_loadElement( 'createElement', $elementType, array_slice($args, 1) ); return $element; } /** * Returns a form element of the given type * * @param string $event event to send to newly created element ('createElement' or 'addElement') * @param string $type element type * @param array $args arguments for event * @since 2.0 * @access private * @return HTML_QuickForm_Element * @throws HTML_QuickForm_Error */ public function &_loadElement($event, $type, $args) { $className = null; // Try if class exists if (!class_exists($type)) { // Try classic class name HTML_QuickForm_ $className = 'HTML_QuickForm_'.$type; if (!class_exists($className)) { // Try classic class name HTML_QuickForm_ with strtolower $lowerType = strtolower($type); $className = 'HTML_QuickForm_'.$lowerType; if (!class_exists($className)) { // Try new class name CamelCase $className = underScoreToCamelCase($type); if (!class_exists($className)) { throw new \Exception("Class '$className' does not exist. "); } } } } else { $className = $type; } if (empty($className)) { throw new \Exception("Class '$className' does not exist. "); } for ($i = 0; $i < self::MAX_ELEMENT_ARGUMENT; $i++) { if (!isset($args[$i])) { $args[$i] = null; } } /** @var HTML_QuickForm_element $element */ $element = new $className( $args[0], $args[1], $args[2], $args[3], $args[4], $args[5], $args[6], $args[7], $args[8], $args[9] ); if ($event != 'createElement') { $err = $element->onQuickFormEvent($event, $args, $this); if ($err !== true) { return $err; } } return $element; } /** * Adds an element into the form * * If $element is a string representing element type, then this * method accepts variable number of parameters, their meaning * and count depending on $element * * @param mixed $element element object or type of element to add (text, textarea, file...) * @since 1.0 * @return HTML_QuickForm_element a reference to newly added element * @access public * @throws HTML_QuickForm_Error */ public function &addElement($element) { if (is_object($element) && is_subclass_of($element, 'html_quickform_element')) { $elementObject = &$element; $elementObject->onQuickFormEvent('updateValue', null, $this); } else { $args = func_get_args(); $elementObject =& $this->_loadElement('addElement', $element, array_slice($args, 1)); if (PEAR::isError($elementObject)) { return $elementObject; } } $elementName = $elementObject->getName(); // Add the element if it is not an incompatible duplicate if (!empty($elementName) && isset($this->_elementIndex[$elementName]) ) { if ($this->_elements[$this->_elementIndex[$elementName]]->getType() == $elementObject->getType()) { $this->_elements[] =& $elementObject; $elKeys = array_keys($this->_elements); $this->_duplicateIndex[$elementName][] = end($elKeys); } else { throw new \Exception("Element '$elementName' already exists in HTML_QuickForm::addElement()"); } } else { $this->_elements[] =& $elementObject; $elKeys = array_keys($this->_elements); $this->_elementIndex[$elementName] = end($elKeys); } $elId = $elementObject->getAttribute('id'); if (empty($elId)) { $elementObject->setAttribute('id', "{$this->getAttribute('name')}_$elementName"); } if ($this->_freezeAll) { $elementObject->freeze(); } return $elementObject; } /** * @return array */ public function getElements() { return $this->_elements; } /** * Inserts a new element right before the other element * * Warning: it is not possible to check whether the $element is already * added to the form, therefore if you want to move the existing form * element to a new position, you'll have to use removeElement(): * $form->insertElementBefore($form->removeElement('foo', false), 'bar'); * * @access public * @since 3.2.4 * @param HTML_QuickForm_element Element to insert * @param string Name of the element before which the new * one is inserted * @return HTML_QuickForm_element reference to inserted element */ public function &insertElementBefore(&$element, $nameAfter) { if (!empty($this->_duplicateIndex[$nameAfter])) { throw new \Exception('Several elements named "' . $nameAfter . '" exist in HTML_QuickForm::insertElementBefore().'); } elseif (!$this->elementExists($nameAfter)) { throw new \Exception("Element '$nameAfter' does not exist in HTML_QuickForm::insertElementBefore()"); } $elementName = $element->getName(); $targetIdx = $this->_elementIndex[$nameAfter]; $duplicate = false; // Like in addElement(), check that it's not an incompatible duplicate if (!empty($elementName) && isset($this->_elementIndex[$elementName])) { if ($this->_elements[$this->_elementIndex[$elementName]]->getType() != $element->getType()) { throw new \Exception("Element '$elementName' already exists in HTML_QuickForm::insertElementBefore()"); } $duplicate = true; } // Move all the elements after added back one place, reindex _elementIndex and/or _duplicateIndex $elKeys = array_keys($this->_elements); for ($i = end($elKeys); $i >= $targetIdx; $i--) { if (isset($this->_elements[$i])) { $currentName = $this->_elements[$i]->getName(); $this->_elements[$i + 1] =& $this->_elements[$i]; if ($this->_elementIndex[$currentName] == $i) { $this->_elementIndex[$currentName] = $i + 1; } else { $dupIdx = array_search($i, $this->_duplicateIndex[$currentName]); $this->_duplicateIndex[$currentName][$dupIdx] = $i + 1; } unset($this->_elements[$i]); } } // Put the element in place finally $this->_elements[$targetIdx] =& $element; if (!$duplicate) { $this->_elementIndex[$elementName] = $targetIdx; } else { $this->_duplicateIndex[$elementName][] = $targetIdx; } $element->onQuickFormEvent('updateValue', null, $this); if ($this->_freezeAll) { $element->freeze(); } // If not done, the elements will appear in reverse order ksort($this->_elements); return $element; } /** * Adds an element group * @param array $elements array of elements composing the group * @param string $name (optional)group name * @param string $groupLabel (optional)group label * @param string $separator (optional)string to separate elements * @param bool $appendName (optional)specify whether the group name should be * used in the form element name ex: group[element] * @return HTML_QuickForm_group reference to a newly added group * @since 2.8 * @access public * @throws HTML_QuickForm_Error */ public function &addGroup( $elements, $name = null, $groupLabel = '', $separator = null, $appendName = true, $createElement = false ) { static $anonGroups = 1; if (0 == strlen($name)) { $name = 'qf_group_'.$anonGroups++; $appendName = false; } if ($createElement) { return $this->createElement('group', $name, $groupLabel, $elements, $separator, $appendName); } $group = & $this->addElement('group', $name, $groupLabel, $elements, $separator, $appendName); return $group; } /** * Returns a reference to the element * * @param string $element Element name * @since 2.0 * @access public * @return HTML_QuickForm_element reference to element * @throws HTML_QuickForm_Error */ public function &getElement($element) { if (isset($this->_elementIndex[$element])) { return $this->_elements[$this->_elementIndex[$element]]; } else { throw new \Exception("Element '$element' does not exist in HTML_QuickForm::getElement()"); } } /** * @param string $name * @return mixed */ public function getElementByName($name) { foreach ($this->_elements as &$element) { $elementName = $element->getName(); if ($elementName == $name) { return $element; } } } /** * @param string $element * @return bool */ public function hasElement($element) { return isset($this->_elementIndex[$element]); } /** * Returns the element's raw value * * This returns the value as submitted by the form (not filtered) * or set via setDefaults() or setConstants() * * @param string $element Element name * @since 2.0 * @access public * @return mixed element value * @throws HTML_QuickForm_Error */ public function &getElementValue($element) { if (!isset($this->_elementIndex[$element])) { throw new \Exception("Element '$element' does not exist in HTML_QuickForm::getElementValue()"); } $value = $this->_elements[$this->_elementIndex[$element]]->getValue(); if (isset($this->_duplicateIndex[$element])) { foreach ($this->_duplicateIndex[$element] as $index) { if (null !== ($v = $this->_elements[$index]->getValue())) { if (is_array($value)) { $value[] = $v; } else { $value = (null === $value)? $v: array($value, $v); } } } } return $value; } /** * Returns the elements value after submit and filter * * @param string Element name * @since 2.0 * @access public * @return mixed submitted element value or null if not set */ public function getSubmitValue($elementName) { $value = null; if (isset($this->_submitValues[$elementName]) || isset($this->_submitFiles[$elementName])) { $value = isset($this->_submitValues[$elementName])? $this->_submitValues[$elementName]: array(); if (is_array($value) && isset($this->_submitFiles[$elementName])) { foreach ($this->_submitFiles[$elementName] as $k => $v) { $value = HTML_QuickForm::arrayMerge( $value, $this->_reindexFiles($this->_submitFiles[$elementName][$k], $k) ); } } } elseif ('file' == $this->getElementType($elementName)) { return $this->getElementValue($elementName); } elseif (false !== ($pos = strpos($elementName, '['))) { $base = str_replace( array('\\', '\''), array('\\\\', '\\\''), substr($elementName, 0, $pos) ); $idx = "['".str_replace( array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), substr($elementName, $pos + 1, -1) )."']"; if (isset($this->_submitValues[$base])) { $value = eval("return (isset(\$this->_submitValues['{$base}']{$idx})) ? \$this->_submitValues['{$base}']{$idx} : null;"); } if ((is_array($value) || null === $value) && isset($this->_submitFiles[$base])) { $props = array('name', 'type', 'size', 'tmp_name', 'error'); $code = "if (!isset(\$this->_submitFiles['{$base}']['name']{$idx})) {\n" . " return null;\n" . "} else {\n" . " \$v = array();\n"; foreach ($props as $prop) { $code .= " \$v = HTML_QuickForm::arrayMerge(\$v, \$this->_reindexFiles(\$this->_submitFiles['{$base}']['{$prop}']{$idx}, '{$prop}'));\n"; } $fileValue = eval($code . " return \$v;\n}\n"); if (null !== $fileValue) { $value = null === $value? $fileValue: HTML_QuickForm::arrayMerge($value, $fileValue); } } } // This is only supposed to work for groups with appendName = false if (null === $value && 'group' == $this->getElementType($elementName)) { $group =& $this->getElement($elementName); $elements =& $group->getElements(); foreach (array_keys($elements) as $key) { $name = $group->getElementName($key); // prevent endless recursion in case of radios and such if ($name != $elementName) { if (null !== ($v = $this->getSubmitValue($name))) { $value[$name] = $v; } } } } if ($this->hasElement($elementName)) { $element = $this->getElement($elementName); if (method_exists($element, 'getSubmitValue')) { $value = $element->getSubmitValue( $value, $this->_submitValues, $this->_errors ); } } return $value; } /** * A helper function to change the indexes in $_FILES array * * @param mixed Some value from the $_FILES array * @param string The key from the $_FILES array that should be appended * @return array */ public function _reindexFiles($value, $key) { if (!is_array($value)) { return array($key => $value); } else { $ret = array(); foreach ($value as $k => $v) { $ret[$k] = $this->_reindexFiles($v, $key); } return $ret; } } /** * Returns error corresponding to validated element * * @param string $element Name of form element to check * @since 1.0 * @access public * @return string error message corresponding to checked element */ public function getElementError($element) { if (isset($this->_errors[$element])) { return $this->_errors[$element]; } } /** * Set error message for a form element * * @param string $element Name of form element to set error for * @param string $message Error message, if empty then removes the current error message * @since 1.0 * @access public * @return void */ public function setElementError($element, $message = null) { if (!empty($message)) { $this->_errors[$element] = $message; } else { unset($this->_errors[$element]); } } /** * Returns the type of the given element * * @param string $element Name of form element * @since 1.1 * @access public * @return string Type of the element, false if the element is not found */ public function getElementType($element) { if (isset($this->_elementIndex[$element])) { return $this->_elements[$this->_elementIndex[$element]]->getType(); } return false; } /** * Updates Attributes for one or more elements * * @param mixed $elements Array of element names/objects or string of elements to be updated * @param mixed $attrs Array or sting of html attributes * @since 2.10 * @access public * @return void */ public function updateElementAttr($elements, $attrs) { if (is_string($elements)) { $elements = split('[ ]?,[ ]?', $elements); } foreach (array_keys($elements) as $key) { if (is_object($elements[$key]) && is_a($elements[$key], 'HTML_QuickForm_element')) { $elements[$key]->updateAttributes($attrs); } elseif (isset($this->_elementIndex[$elements[$key]])) { $this->_elements[$this->_elementIndex[$elements[$key]]]->updateAttributes($attrs); if (isset($this->_duplicateIndex[$elements[$key]])) { foreach ($this->_duplicateIndex[$elements[$key]] as $index) { $this->_elements[$index]->updateAttributes($attrs); } } } } } /** * Removes an element * * The method "unlinks" an element from the form, returning the reference * to the element object. If several elements named $elementName exist, * it removes the first one, leaving the others intact. * * @param string $elementName The element name * @param boolean $removeRules True if rules for this element are to be removed too * @access public * @since 2.0 * @return HTML_QuickForm_element a reference to the removed element * @throws HTML_QuickForm_Error */ public function &removeElement($elementName, $removeRules = true) { if (!isset($this->_elementIndex[$elementName])) { throw new \Exception("Element '$elementName' does not exist in HTML_QuickForm::removeElement()"); } $el =& $this->_elements[$this->_elementIndex[$elementName]]; unset($this->_elements[$this->_elementIndex[$elementName]]); if (empty($this->_duplicateIndex[$elementName])) { unset($this->_elementIndex[$elementName]); } else { $this->_elementIndex[$elementName] = array_shift($this->_duplicateIndex[$elementName]); } if ($removeRules) { $this->_required = array_diff($this->_required, array($elementName)); unset($this->_rules[$elementName], $this->_errors[$elementName]); if ('group' == $el->getType()) { foreach (array_keys($el->getElements()) as $key) { unset($this->_rules[$el->getElementName($key)]); } } } return $el; } /** * Adds a validation rule for the given field * * If the element is in fact a group, it will be considered as a whole. * To validate grouped elements as separated entities, * use addGroupRule instead of addRule. * * @param string $element Form element name * @param string $message Message to display for invalid data * @param string $type Rule type, use getRegisteredRules() to get types * @param string $format (optional)Required for extra rule data * @param string $validation (optional)Where to perform validation: "server", "client" * @param boolean $reset Client-side validation: reset the form element to its original value if there is an error? * @param boolean $force Force the rule to be applied, even if the target form element does not exist * @param array|string $dependent needed when comparing values * @since 1.0 * @access public */ public function addRule( $element, $message, $type, $format = null, $validation = 'server', $reset = false, $force = false, $dependent = null ) { if (!$force) { if (!is_array($element) && !$this->elementExists($element)) { throw new \Exception("Element '$element' does not exist in HTML_QuickForm::addRule()"); } elseif (is_array($element)) { foreach ($element as $el) { if (!$this->elementExists($el)) { throw new \Exception("Element '$el' does not exist in HTML_QuickForm::addRule()"); } } } } if (false === ($newName = $this->isRuleRegistered($type, true))) { throw new \Exception("Rule '$type' is not registered in HTML_QuickForm::addRule()"); } elseif (is_string($newName)) { $type = $newName; } if (is_array($element)) { $dependent = $element; $element = array_shift($dependent); } if ($type == 'required' || $type == 'uploadedfile') { $this->_required[] = $element; } if (!isset($this->_rules[$element])) { $this->_rules[$element] = array(); } if ($validation == 'client') { $this->updateAttributes( array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);') ); } $this->_rules[$element][] = array( 'type' => $type, 'format' => $format, 'message' => $message, 'validation' => $validation, 'reset' => $reset, 'dependent' => $dependent, ); } /** * Adds a validation rule for the given group of elements * * Only groups with a name can be assigned a validation rule * Use addGroupRule when you need to validate elements inside the group. * Use addRule if you need to validate the group as a whole. In this case, * the same rule will be applied to all elements in the group. * Use addRule if you need to validate the group against a function. * * @param string $group Form group name * @param mixed $arg1 Array for multiple elements or error message string for one element * @param string $type (optional)Rule type use getRegisteredRules() to get types * @param string $format (optional)Required for extra rule data * @param int $howmany (optional)How many valid elements should be in the group * @param string $validation (optional)Where to perform validation: "server", "client" * @param bool $reset Client-side: whether to reset the element's value to its original state if validation failed. * @since 2.5 * @access public * @throws HTML_QuickForm_Error */ public function addGroupRule($group, $arg1, $type='', $format=null, $howmany=0, $validation = 'server', $reset = false) { if (!$this->elementExists($group)) { throw new \Exception("Group '$group' does not exist in HTML_QuickForm::addGroupRule()"); } $groupObj =& $this->getElement($group); if (is_array($arg1)) { $required = 0; foreach ($arg1 as $elementIndex => $rules) { $elementName = $groupObj->getElementName($elementIndex); foreach ($rules as $rule) { $format = (isset($rule[2])) ? $rule[2] : null; $validation = (isset($rule[3]) && 'client' == $rule[3])? 'client': 'server'; $reset = isset($rule[4]) && $rule[4]; $type = $rule[1]; if (false === ($newName = $this->isRuleRegistered($type, true))) { throw new \Exception("Rule '$type' is not registered in HTML_QuickForm::addGroupRule()"); } elseif (is_string($newName)) { $type = $newName; } $this->_rules[$elementName][] = array( 'type' => $type, 'format' => $format, 'message' => $rule[0], 'validation' => $validation, 'reset' => $reset, 'group' => $group, ); if ('required' == $type || 'uploadedfile' == $type) { $groupObj->_required[] = $elementName; $this->_required[] = $elementName; $required++; } if ('client' == $validation) { $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);')); } } } if ($required > 0 && count($groupObj->getElements()) == $required) { $this->_required[] = $group; } } elseif (is_string($arg1)) { if (false === ($newName = $this->isRuleRegistered($type, true))) { throw new \Exception("Rule '$type' is not registered in HTML_QuickForm::addGroupRule()"); } elseif (is_string($newName)) { $type = $newName; } // addGroupRule() should also handle