���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home3/cpr76684/public_html/HTML.tar
���ѧ٧ѧ�
QuickForm.php 0000644 00000225765 15152353724 0007205 0 ustar 00 <?php /* vim: set expandtab tabstop=4 shiftwidth=4: */ // +----------------------------------------------------------------------+ // | PHP version 4.0 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2003 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Adam Daniel <adaniel1@eesus.jnj.com> | // | Bertrand Mansion <bmansion@mamasam.com> | // +----------------------------------------------------------------------+ // // $Id$ require_once('PEAR.php'); require_once('HTML/Common.php'); /** * Static utility methods. */ require_once('HTML/QuickForm/utils.php'); $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'] = array( 'group' =>array('HTML/QuickForm/group.php','HTML_QuickForm_group'), 'hidden' =>array('HTML/QuickForm/hidden.php','HTML_QuickForm_hidden'), 'reset' =>array('HTML/QuickForm/reset.php','HTML_QuickForm_reset'), 'checkbox' =>array('HTML/QuickForm/checkbox.php','HTML_QuickForm_checkbox'), 'file' =>array('HTML/QuickForm/file.php','HTML_QuickForm_file'), 'image' =>array('HTML/QuickForm/image.php','HTML_QuickForm_image'), 'password' =>array('HTML/QuickForm/password.php','HTML_QuickForm_password'), 'radio' =>array('HTML/QuickForm/radio.php','HTML_QuickForm_radio'), 'button' =>array('HTML/QuickForm/button.php','HTML_QuickForm_button'), 'submit' =>array('HTML/QuickForm/submit.php','HTML_QuickForm_submit'), 'select' =>array('HTML/QuickForm/select.php','HTML_QuickForm_select'), 'hiddenselect' =>array('HTML/QuickForm/hiddenselect.php','HTML_QuickForm_hiddenselect'), 'text' =>array('HTML/QuickForm/text.php','HTML_QuickForm_text'), 'textarea' =>array('HTML/QuickForm/textarea.php','HTML_QuickForm_textarea'), 'link' =>array('HTML/QuickForm/link.php','HTML_QuickForm_link'), 'advcheckbox' =>array('HTML/QuickForm/advcheckbox.php','HTML_QuickForm_advcheckbox'), 'date' =>array('HTML/QuickForm/date.php','HTML_QuickForm_date'), 'static' =>array('HTML/QuickForm/static.php','HTML_QuickForm_static'), 'header' =>array('HTML/QuickForm/header.php', 'HTML_QuickForm_header'), 'html' =>array('HTML/QuickForm/html.php', 'HTML_QuickForm_html'), 'hierselect' =>array('HTML/QuickForm/hierselect.php', 'HTML_QuickForm_hierselect'), 'autocomplete' =>array('HTML/QuickForm/autocomplete.php', 'HTML_QuickForm_autocomplete'), 'xbutton' =>array('HTML/QuickForm/xbutton.php','HTML_QuickForm_xbutton') ); $GLOBALS['_HTML_QuickForm_registered_rules'] = array( 'required' => array('html_quickform_rule_required', 'HTML/QuickForm/Rule/Required.php'), 'maxlength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'), 'minlength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'), 'rangelength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'), 'email' => array('html_quickform_rule_email', 'HTML/QuickForm/Rule/Email.php'), 'regex' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), 'lettersonly' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), 'alphanumeric' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), 'numeric' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), 'nopunctuation' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), 'nonzero' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), 'positiveint' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), 'callback' => array('html_quickform_rule_callback', 'HTML/QuickForm/Rule/Callback.php'), 'compare' => array('html_quickform_rule_compare', 'HTML/QuickForm/Rule/Compare.php') ); // {{{ error codes /* * Error codes for the QuickForm interface, which will be mapped to textual messages * in the QuickForm::errorMessage() function. If you are to add a new error code, be * sure to add the textual messages to the QuickForm::errorMessage() function as well */ 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); // }}} /** * Create, validate and process HTML forms * * @author Adam Daniel <adaniel1@eesus.jnj.com> * @author Bertrand Mansion <bmansion@mamasam.com> * @version 2.0 * @since PHP 4.0.3pl1 */ class HTML_QuickForm extends HTML_Common { // {{{ properties /** * Array containing the form fields * @since 1.0 * @var array * @access private */ var $_elements = array(); /** * Array containing element name to index map * @since 1.1 * @var array * @access private */ var $_elementIndex = array(); /** * Array containing indexes of duplicate elements * @since 2.10 * @var array * @access private */ var $_duplicateIndex = array(); /** * Array containing required field IDs * @since 1.0 * @var array * @access private */ var $_required = array(); /** * Prefix message in javascript alert if error * @since 1.0 * @var string * @access public */ var $_jsPrefix = 'Invalid information entered.'; /** * Postfix message in javascript alert if error * @since 1.0 * @var string * @access public */ var $_jsPostfix = 'Please correct these fields.'; /** * Datasource object implementing the informal * datasource protocol * @since 3.3 * @var object * @access private */ var $_datasource; /** * Array of default form values * @since 2.0 * @var array * @access private */ var $_defaultValues = array(); /** * Array of constant form values * @since 2.0 * @var array * @access private */ var $_constantValues = array(); /** * Array of submitted form values * @since 1.0 * @var array * @access private */ var $_submitValues = array(); /** * Array of submitted form files * @since 1.0 * @var integer * @access public */ var $_submitFiles = array(); /** * Value for maxfilesize hidden element if form contains file input * @since 1.0 * @var integer * @access public */ var $_maxFileSize = 1048576; // 1 Mb = 1048576 /** * Flag to know if all fields are frozen * @since 1.0 * @var boolean * @access private */ var $_freezeAll = false; /** * Array containing the form rules * @since 1.0 * @var array * @access private */ var $_rules = array(); /** * Form rules, global variety * @var array * @access private */ var $_formRules = array(); /** * Array containing the validation errors * @since 1.0 * @var array * @access private */ var $_errors = array(); /** * Note for required fields in the form * @var string * @since 1.0 * @access private */ var $_requiredNote = '<span style="font-size:80%; color:#ff0000;">*</span><span style="font-size:80%;"> denotes required field</span>'; /** * Whether the form was submitted * @var boolean * @access private */ var $_flagSubmitted = false; // }}} // {{{ constructor /** * 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 <form> 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 == '') ? $_SERVER['PHP_SELF'] : $action; $target = empty($target) ? array() : array('target' => $target); $attributes = array('action'=>$action, 'method'=>$method, 'name'=>$formName, 'id'=>$formName) + $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']; } } } // end constructor /** * Old syntax of class constructor. Deprecated in PHP7. * * @deprecated since Moodle 3.1 */ public function HTML_QuickForm($formName='', $method='post', $action='', $target='', $attributes=null, $trackSubmit = false) { debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER); self::__construct($formName, $method, $action, $target, $attributes, $trackSubmit); } // }}} // {{{ apiVersion() /** * Returns the current API version * * @since 1.0 * @access public * @return float */ function apiVersion() { return 3.2; } // end func apiVersion // }}} // {{{ registerElementType() /** * 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 */ static function registerElementType($typeName, $include, $className) { $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($typeName)] = array($include, $className); } // end func registerElementType // }}} // {{{ registerRule() /** * 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 */ static function registerRule($ruleName, $type, $data1, $data2 = null) { include_once('HTML/QuickForm/RuleRegistry.php'); $registry =& HTML_QuickForm_RuleRegistry::singleton(); $registry->registerRule($ruleName, $type, $data1, $data2); } // end func registerRule // }}} // {{{ elementExists() /** * Returns true if element is in the form * * @param string $element form name of element to check * @since 1.0 * @access public * @return boolean */ function elementExists($element=null) { return isset($this->_elementIndex[$element]); } // end func elementExists // }}} // {{{ setDatasource() /** * Sets a datasource object for this form object * * Datasource default and constant values will feed the QuickForm object if * the datasource implements defaultValues() and constantValues() methods. * * @param object $datasource datasource object implementing the informal datasource protocol * @param mixed $defaultsFilter string or array of filter(s) to apply to default values * @param mixed $constantsFilter string or array of filter(s) to apply to constants values * @since 3.3 * @access public * @return void */ function setDatasource(&$datasource, $defaultsFilter = null, $constantsFilter = null) { if (is_object($datasource)) { $this->_datasource =& $datasource; if (is_callable(array($datasource, 'defaultValues'))) { $this->setDefaults($datasource->defaultValues($this), $defaultsFilter); } if (is_callable(array($datasource, 'constantValues'))) { $this->setConstants($datasource->constantValues($this), $constantsFilter); } } else { return self::raiseError(null, QUICKFORM_INVALID_DATASOURCE, null, E_USER_WARNING, "Datasource is not an object in QuickForm::setDatasource()", 'HTML_QuickForm_Error', true); } } // end func setDatasource // }}} // {{{ setDefaults() /** * 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 * @return void */ 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)) { return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true); } else { $defaultValues = $this->_recursiveFilter($val, $defaultValues); } } } elseif (!is_callable($filter)) { return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true); } else { $defaultValues = $this->_recursiveFilter($filter, $defaultValues); } } $this->_defaultValues = HTML_QuickForm::arrayMerge($this->_defaultValues, $defaultValues); foreach (array_keys($this->_elements) as $key) { $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this); } } } // end func setDefaults // }}} // {{{ setConstants() /** * 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 */ 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)) { return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true); } else { $constantValues = $this->_recursiveFilter($val, $constantValues); } } } elseif (!is_callable($filter)) { return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true); } 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); } } } // end func setConstants // }}} // {{{ setMaxFileSize() /** * Sets the value of MAX_FILE_SIZE hidden element * * @param int $bytes Size in bytes * @since 3.0 * @access public * @return void */ 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)); } } // end func setMaxFileSize // }}} // {{{ getMaxFileSize() /** * Returns the value of MAX_FILE_SIZE hidden element * * @since 3.0 * @access public * @return int max file size in bytes */ function getMaxFileSize() { return $this->_maxFileSize; } // end func getMaxFileSize // }}} // {{{ &createElement() /** * 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 object extended class of HTML_element * @throws HTML_QuickForm_Error */ function &createElement($elementType) { if (!isset($this) || !($this instanceof HTML_QuickForm)) { // Several form elements in Moodle core before 3.2 were calling this method // statically suppressing PHP notices. This debugging message should notify // developers who copied such code and did not test their plugins on PHP 7.1. // Example of fixing group form elements can be found in commit // https://github.com/moodle/moodle/commit/721e2def56a48fab4f8d3ec7847af5cd03f5ec79 debugging('Function createElement() can not be called statically, ' . 'this will no longer work in PHP 7.1', DEBUG_DEVELOPER); } $args = func_get_args(); $element = self::_loadElement('createElement', $elementType, array_slice($args, 1)); return $element; } // end func createElement // }}} // {{{ _loadElement() /** * 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 object a new element * @throws HTML_QuickForm_Error */ function &_loadElement($event, $type, $args) { $type = strtolower($type); if (!self::isTypeRegistered($type)) { $error = self::raiseError(null, QUICKFORM_UNREGISTERED_ELEMENT, null, E_USER_WARNING, "Element '$type' does not exist in HTML_QuickForm::_loadElement()", 'HTML_QuickForm_Error', true); return $error; } $className = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][1]; $includeFile = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][0]; include_once($includeFile); $elementObject = new $className(); //Moodle: PHP 5.3 compatibility for ($i = 0; $i < 5; $i++) { if (!isset($args[$i])) { $args[$i] = null; } } $err = $elementObject->onQuickFormEvent($event, $args, $this); if ($err !== true) { return $err; } return $elementObject; } // end func _loadElement // }}} // {{{ addElement() /** * 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 object reference to element * @access public * @throws HTML_QuickForm_Error */ 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)); $pear = new PEAR(); 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 { $error = self::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::addElement()", 'HTML_QuickForm_Error', true); return $error; } } else { $this->_elements[] =& $elementObject; $elKeys = array_keys($this->_elements); $this->_elementIndex[$elementName] = end($elKeys); } if ($this->_freezeAll) { $elementObject->freeze(); } return $elementObject; } // end func addElement // }}} // {{{ insertElementBefore() /** * 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 object HTML_QuickForm_element Element to insert * @param string Name of the element before which the new one is inserted * @return object HTML_QuickForm_element reference to inserted element * @throws HTML_QuickForm_Error */ function &insertElementBefore(&$element, $nameAfter) { if (!empty($this->_duplicateIndex[$nameAfter])) { $error = self::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, 'Several elements named "' . $nameAfter . '" exist in HTML_QuickForm::insertElementBefore().', 'HTML_QuickForm_Error', true); return $error; } elseif (!$this->elementExists($nameAfter)) { $error = self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$nameAfter' does not exist in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true); return $error; } $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()) { $error = self::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true); return $error; } $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 { if (!empty($currentName)) { $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; } // }}} // {{{ addGroup() /** * 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 string $appendName (optional)specify whether the group name should be * used in the form element name ex: group[element] * @return object reference to added group of elements * @since 2.8 * @access public * @throws PEAR_Error */ function &addGroup($elements, $name=null, $groupLabel='', $separator=null, $appendName = true) { static $anonGroups = 1; if (0 == strlen($name ?? '')) { $name = 'qf_group_' . $anonGroups++; $appendName = false; } $group =& $this->addElement('group', $name, $groupLabel, $elements, $separator, $appendName); return $group; } // end func addGroup // }}} // {{{ &getElement() /** * Returns a reference to the element * * @param string $element Element name * @since 2.0 * @access public * @return object reference to element * @throws HTML_QuickForm_Error */ function &getElement($element) { if (isset($this->_elementIndex[$element])) { return $this->_elements[$this->_elementIndex[$element]]; } else { $error = self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElement()", 'HTML_QuickForm_Error', true); return $error; } } // end func getElement // }}} // {{{ &getElementValue() /** * 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 */ function &getElementValue($element) { if (!isset($this->_elementIndex[$element])) { $error = self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElementValue()", 'HTML_QuickForm_Error', true); return $error; } $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; } // end func getElementValue // }}} // {{{ getSubmitValue() /** * 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 */ function getSubmitValue($elementName) { $value = null; $elementName = $elementName ?? ''; 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 = substr($elementName, 0, $pos); $keys = str_replace( array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), substr($elementName, $pos + 1, -1) ); $idx = "['" . $keys . "']"; $keyArray = explode("']['", $keys); if (isset($this->_submitValues[$base])) { $value = HTML_QuickForm_utils::recursiveValue($this->_submitValues[$base], $keyArray, 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; } } } } return $value; } // end func getSubmitValue // }}} // {{{ _reindexFiles() /** * 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 */ 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; } } // }}} // {{{ getElementError() /** * 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 */ function getElementError($element) { if (isset($this->_errors[$element])) { return $this->_errors[$element]; } } // end func getElementError // }}} // {{{ setElementError() /** * 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 */ function setElementError($element, $message = null) { if (!empty($message)) { $this->_errors[$element] = $message; } else { unset($this->_errors[$element]); } } // end func setElementError // }}} // {{{ getElementType() /** * 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 */ function getElementType($element) { if (isset($this->_elementIndex[$element])) { return $this->_elements[$this->_elementIndex[$element]]->getType(); } return false; } // end func getElementType // }}} // {{{ updateElementAttr() /** * 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 */ function updateElementAttr($elements, $attrs) { if (is_string($elements)) { $elements = preg_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); } } } } } // end func updateElementAttr // }}} // {{{ removeElement() /** * 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 object HTML_QuickForm_element a reference to the removed element * @throws HTML_QuickForm_Error */ function &removeElement($elementName, $removeRules = true) { if (!isset($this->_elementIndex[$elementName])) { $error = self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$elementName' does not exist in HTML_QuickForm::removeElement()", 'HTML_QuickForm_Error', true); return $error; } $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) { unset($this->_rules[$elementName], $this->_errors[$elementName]); } return $el; } // end func removeElement // }}} // {{{ addRule() /** * 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 * @since 1.0 * @access public * @throws HTML_QuickForm_Error */ function addRule($element, $message, $type, $format=null, $validation='server', $reset = false, $force = false) { if (!$force) { if (!is_array($element) && !$this->elementExists($element)) { return self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true); } elseif (is_array($element)) { foreach ($element as $el) { if (!$this->elementExists($el)) { return self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$el' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true); } } } } if (false === ($newName = $this->isRuleRegistered($type, true))) { return self::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true); } elseif (is_string($newName)) { $type = $newName; } if (is_array($element)) { $dependent = $element; $element = array_shift($dependent); } else { $dependent = null; } if ($type == 'required' || $type == 'uploadedfile') { $this->_required[] = $element; } if (!isset($this->_rules[$element])) { $this->_rules[$element] = array(); } $this->_rules[$element][] = array( 'type' => $type, 'format' => $format, 'message' => $message, 'validation' => $validation, 'reset' => $reset, 'dependent' => $dependent ); } // end func addRule // }}} // {{{ addGroupRule() /** * 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 */ function addGroupRule($group, $arg1, $type='', $format=null, $howmany=0, $validation = 'server', $reset = false) { if (!$this->elementExists($group)) { return self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Group '$group' does not exist in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true); } $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))) { return self::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true); } 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 ($required > 0 && count($groupObj->getElements()) == $required) { $this->_required[] = $group; } } elseif (is_string($arg1)) { if (false === ($newName = $this->isRuleRegistered($type, true))) { return self::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true); } elseif (is_string($newName)) { $type = $newName; } // addGroupRule() should also handle <select multiple> if (is_a($groupObj, 'html_quickform_group')) { // Radios need to be handled differently when required if ($type == 'required' && $groupObj->getGroupType() == 'radio') { $howmany = ($howmany == 0) ? 1 : $howmany; } else { $howmany = ($howmany == 0) ? count($groupObj->getElements()) : $howmany; } } $this->_rules[$group][] = array('type' => $type, 'format' => $format, 'message' => $arg1, 'validation' => $validation, 'howmany' => $howmany, 'reset' => $reset); if ($type == 'required') { $this->_required[] = $group; } } } // end func addGroupRule // }}} // {{{ addFormRule() /** * Adds a global validation rule * * This should be used when for a rule involving several fields or if * you want to use some completely custom validation for your form. * The rule function/method should return true in case of successful * validation and array('element name' => 'error') when there were errors. * * @access public * @param mixed Callback, either function name or array(&$object, 'method') * @throws HTML_QuickForm_Error */ function addFormRule($rule) { if (!is_callable($rule)) { return self::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, 'Callback function does not exist in HTML_QuickForm::addFormRule()', 'HTML_QuickForm_Error', true); } $this->_formRules[] = $rule; } // }}} // {{{ applyFilter() /** * Applies a data filter for the given field(s) * * @param mixed $element Form element name or array of such names * @param mixed $filter Callback, either function name or array(&$object, 'method') * @since 2.0 * @access public */ function applyFilter($element, $filter) { if (!is_callable($filter)) { return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::applyFilter()", 'HTML_QuickForm_Error', true); } if ($element == '__ALL__') { $this->_submitValues = $this->_recursiveFilter($filter, $this->_submitValues); } else { if (!is_array($element)) { $element = array($element); } foreach ($element as $elName) { $value = $this->getSubmitValue($elName); if (null !== $value) { if (false === strpos($elName, '[')) { $this->_submitValues[$elName] = $this->_recursiveFilter($filter, $value); } else { $idx = "['" . str_replace(array(']', '['), array('', "']['"), $elName) . "']"; eval("\$this->_submitValues{$idx} = \$this->_recursiveFilter(\$filter, \$value);"); } } } } } // end func applyFilter // }}} // {{{ _recursiveFilter() /** * Recursively apply a filter function * * @param string $filter filter to apply * @param mixed $value submitted values * @since 2.0 * @access private * @return cleaned values */ function _recursiveFilter($filter, $value) { if (is_array($value)) { $cleanValues = array(); foreach ($value as $k => $v) { $cleanValues[$k] = $this->_recursiveFilter($filter, $v); } return $cleanValues; } else { return call_user_func($filter, $value); } } // end func _recursiveFilter // }}} // {{{ arrayMerge() /** * Merges two arrays * * Merges two array like the PHP function array_merge but recursively. * The main difference is that existing keys will not be renumbered * if they are integers. * * @access puplic * @param array $a original array * @param array $b array which will be merged into first one * @return array merged array */ static function arrayMerge($a, $b) { if (is_null($a)) {$a = array();} if (is_null($b)) {$b = array();} foreach ($b as $k => $v) { if (is_array($v)) { if (isset($a[$k]) && !is_array($a[$k])) { $a[$k] = $v; } else { if (!isset($a[$k])) { $a[$k] = array(); } $a[$k] = HTML_QuickForm::arrayMerge($a[$k], $v); } } else { $a[$k] = $v; } } return $a; } // end func arrayMerge // }}} // {{{ isTypeRegistered() /** * Returns whether or not the form element type is supported * * @param string $type Form element type * @since 1.0 * @access public * @return boolean */ function isTypeRegistered($type) { return isset($GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($type)]); } // end func isTypeRegistered // }}} // {{{ getRegisteredTypes() /** * Returns an array of registered element types * * @since 1.0 * @access public * @return array */ function getRegisteredTypes() { return array_keys($GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES']); } // end func getRegisteredTypes // }}} // {{{ isRuleRegistered() /** * Returns whether or not the given rule is supported * * @param string $name Validation rule name * @param bool Whether to automatically register subclasses of HTML_QuickForm_Rule * @since 1.0 * @access public * @return mixed true if previously registered, false if not, new rule name if auto-registering worked */ function isRuleRegistered($name, $autoRegister = false) { if (is_scalar($name) && isset($GLOBALS['_HTML_QuickForm_registered_rules'][$name])) { return true; } elseif (!$autoRegister) { return false; } // automatically register the rule if requested include_once 'HTML/QuickForm/RuleRegistry.php'; $ruleName = false; if (is_object($name) && is_a($name, 'html_quickform_rule')) { $ruleName = !empty($name->name)? $name->name: strtolower(get_class($name)); } elseif (is_string($name) && class_exists($name)) { $parent = strtolower($name); do { if ('html_quickform_rule' == strtolower($parent)) { $ruleName = strtolower($name); break; } } while ($parent = get_parent_class($parent)); } if ($ruleName) { $registry =& HTML_QuickForm_RuleRegistry::singleton(); $registry->registerRule($ruleName, null, $name); } return $ruleName; } // end func isRuleRegistered // }}} // {{{ getRegisteredRules() /** * Returns an array of registered validation rules * * @since 1.0 * @access public * @return array */ function getRegisteredRules() { return array_keys($GLOBALS['_HTML_QuickForm_registered_rules']); } // end func getRegisteredRules // }}} // {{{ isElementRequired() /** * Returns whether or not the form element is required * * @param string $element Form element name * @since 1.0 * @access public * @return boolean */ function isElementRequired($element) { return in_array($element, $this->_required, true); } // end func isElementRequired // }}} // {{{ isElementFrozen() /** * Returns whether or not the form element is frozen * * @param string $element Form element name * @since 1.0 * @access public * @return boolean */ function isElementFrozen($element) { if (isset($this->_elementIndex[$element])) { return $this->_elements[$this->_elementIndex[$element]]->isFrozen(); } return false; } // end func isElementFrozen // }}} // {{{ setJsWarnings() /** * Sets JavaScript warning messages * * @param string $pref Prefix warning * @param string $post Postfix warning * @since 1.1 * @access public * @return void */ function setJsWarnings($pref, $post) { $this->_jsPrefix = $pref; $this->_jsPostfix = $post; } // end func setJsWarnings // }}} // {{{ setRequiredNote() /** * Sets required-note * * @param string $note Message indicating some elements are required * @since 1.1 * @access public * @return void */ function setRequiredNote($note) { $this->_requiredNote = $note; } // end func setRequiredNote // }}} // {{{ getRequiredNote() /** * Returns the required note * * @since 2.0 * @access public * @return string */ function getRequiredNote() { return $this->_requiredNote; } // end func getRequiredNote // }}} // {{{ validate() /** * Performs the server side validation * @access public * @since 1.0 * @return boolean true if no error found */ function validate() { if (count($this->_rules) == 0 && count($this->_formRules) == 0 && $this->isSubmitted()) { return (0 == count($this->_errors)); } elseif (!$this->isSubmitted()) { return false; } include_once('HTML/QuickForm/RuleRegistry.php'); $registry =& HTML_QuickForm_RuleRegistry::singleton(); foreach ($this->_rules as $target => $rules) { $submitValue = $this->getSubmitValue($target); foreach ($rules as $rule) { if ((isset($rule['group']) && isset($this->_errors[$rule['group']])) || isset($this->_errors[$target])) { continue 2; } // If element is not required and is empty, we shouldn't validate it if (!$this->isElementRequired($target)) { if (!isset($submitValue) || '' == $submitValue) { continue 2; // Fix for bug #3501: we shouldn't validate not uploaded files, either. // Unfortunately, we can't just use $element->isUploadedFile() since // the element in question can be buried in group. Thus this hack. } elseif (is_array($submitValue)) { if (false === ($pos = strpos($target, '['))) { $isUpload = !empty($this->_submitFiles[$target]); } else { $base = substr($target, 0, $pos); $idx = "['" . str_replace(array(']', '['), array('', "']['"), substr($target, $pos + 1, -1)) . "']"; eval("\$isUpload = isset(\$this->_submitFiles['{$base}']['name']{$idx});"); } if ($isUpload && (!isset($submitValue['error']) || 0 != $submitValue['error'])) { continue 2; } } } if (isset($rule['dependent']) && is_array($rule['dependent'])) { $values = array($submitValue); foreach ($rule['dependent'] as $elName) { $values[] = $this->getSubmitValue($elName); } $result = $registry->validate($rule['type'], $values, $rule['format'], true); } elseif (is_array($submitValue) && !isset($rule['howmany'])) { $result = $registry->validate($rule['type'], $submitValue, $rule['format'], true); } else { $result = $registry->validate($rule['type'], $submitValue, $rule['format'], false); } if (!$result || (!empty($rule['howmany']) && $rule['howmany'] > (int)$result)) { if (isset($rule['group'])) { $this->_errors[$rule['group']] = $rule['message']; } else { $this->_errors[$target] = $rule['message']; } } } } // process the global rules now foreach ($this->_formRules as $rule) { if (true !== ($res = call_user_func($rule, $this->_submitValues, $this->_submitFiles))) { if (is_array($res)) { $this->_errors += $res; } else { return self::raiseError(null, QUICKFORM_ERROR, null, E_USER_WARNING, 'Form rule callback returned invalid value in HTML_QuickForm::validate()', 'HTML_QuickForm_Error', true); } } } return (0 == count($this->_errors)); } // end func validate // }}} // {{{ freeze() /** * Displays elements without HTML input tags * * @param mixed $elementList array or string of element(s) to be frozen * @since 1.0 * @access public * @throws HTML_QuickForm_Error */ function freeze($elementList=null) { if (!isset($elementList)) { $this->_freezeAll = true; $elementList = array(); } else { if (!is_array($elementList)) { $elementList = preg_split('/[ ]*,[ ]*/', $elementList); } $elementList = array_flip($elementList); } foreach (array_keys($this->_elements) as $key) { $name = $this->_elements[$key]->getName(); if ($this->_freezeAll || isset($elementList[$name])) { $this->_elements[$key]->freeze(); unset($elementList[$name]); } } if (!empty($elementList)) { return self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Nonexistant element(s): '" . implode("', '", array_keys($elementList)) . "' in HTML_QuickForm::freeze()", 'HTML_QuickForm_Error', true); } return true; } // end func freeze // }}} // {{{ isFrozen() /** * Returns whether or not the whole form is frozen * * @since 3.0 * @access public * @return boolean */ function isFrozen() { return $this->_freezeAll; } // end func isFrozen // }}} // {{{ process() /** * Performs the form data processing * * @param mixed $callback Callback, either function name or array(&$object, 'method') * @param bool $mergeFiles Whether uploaded files should be processed too * @since 1.0 * @access public * @throws HTML_QuickForm_Error */ function process($callback, $mergeFiles = true) { if (!is_callable($callback)) { return self::raiseError(null, QUICKFORM_INVALID_PROCESS, null, E_USER_WARNING, "Callback function does not exist in QuickForm::process()", 'HTML_QuickForm_Error', true); } $values = ($mergeFiles === true) ? HTML_QuickForm::arrayMerge($this->_submitValues, $this->_submitFiles) : $this->_submitValues; return call_user_func($callback, $values); } // end func process // }}} // {{{ accept() /** * Accepts a renderer * * @param object An HTML_QuickForm_Renderer object * @since 3.0 * @access public * @return void */ function accept(&$renderer) { $renderer->startForm($this); foreach (array_keys($this->_elements) as $key) { $element =& $this->_elements[$key]; $elementName = $element->getName(); $required = ($this->isElementRequired($elementName) && !$element->isFrozen()); $error = $this->getElementError($elementName); $element->accept($renderer, $required, $error); } $renderer->finishForm($this); } // end func accept // }}} // {{{ defaultRenderer() /** * Returns a reference to default renderer object * * @access public * @since 3.0 * @return object a default renderer object */ function &defaultRenderer() { if (!isset($GLOBALS['_HTML_QuickForm_default_renderer'])) { include_once('HTML/QuickForm/Renderer/Default.php'); $GLOBALS['_HTML_QuickForm_default_renderer'] = new HTML_QuickForm_Renderer_Default(); //Moodle: PHP 5.3 compatibility } return $GLOBALS['_HTML_QuickForm_default_renderer']; } // end func defaultRenderer // }}} // {{{ toHtml () /** * Returns an HTML version of the form * * @param string $in_data (optional) Any extra data to insert right * before form is rendered. Useful when using templates. * * @return string Html version of the form * @since 1.0 * @access public */ function toHtml ($in_data = null) { if (!is_null($in_data)) { $this->addElement('html', $in_data); } $renderer =& $this->defaultRenderer(); $this->accept($renderer); return $renderer->toHtml(); } // end func toHtml // }}} // {{{ getValidationScript() /** * Returns the client side validation script * * @since 2.0 * @access public * @return string Javascript to perform validation, empty string if no 'client' rules were added */ function getValidationScript() { if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) { return ''; } include_once('HTML/QuickForm/RuleRegistry.php'); $registry =& HTML_QuickForm_RuleRegistry::singleton(); $test = array(); $js_escape = array( "\r" => '\r', "\n" => '\n', "\t" => '\t', "'" => "\\'", '"' => '\"', '\\' => '\\\\' ); foreach ($this->_rules as $elementName => $rules) { foreach ($rules as $rule) { if ('client' == $rule['validation']) { unset($element); $dependent = isset($rule['dependent']) && is_array($rule['dependent']); $rule['message'] = strtr($rule['message'], $js_escape); if (isset($rule['group'])) { $group =& $this->getElement($rule['group']); // No JavaScript validation for frozen elements if ($group->isFrozen()) { continue 2; } $elements =& $group->getElements(); foreach (array_keys($elements) as $key) { if ($elementName == $group->getElementName($key)) { $element =& $elements[$key]; break; } } } elseif ($dependent) { $element = array(); $element[] =& $this->getElement($elementName); foreach ($rule['dependent'] as $elName) { $element[] =& $this->getElement($elName); } } else { $element =& $this->getElement($elementName); } // No JavaScript validation for frozen elements if (is_object($element) && $element->isFrozen()) { continue 2; } elseif (is_array($element)) { foreach (array_keys($element) as $key) { if ($element[$key]->isFrozen()) { continue 3; } } } $test[] = $registry->getValidationScript($element, $elementName, $rule); } } } if (count($test) > 0) { return "\n<script type=\"text/javascript\">\n" . "//<![CDATA[\n" . "function validate_" . $this->_attributes['id'] . "(frm) {\n" . " var value = '';\n" . " var errFlag = new Array();\n" . " var _qfGroups = {};\n" . " _qfMsg = '';\n\n" . join("\n", $test) . "\n if (_qfMsg != '') {\n" . " _qfMsg = '" . strtr($this->_jsPrefix, $js_escape) . "' + _qfMsg;\n" . " _qfMsg = _qfMsg + '\\n" . strtr($this->_jsPostfix, $js_escape) . "';\n" . " alert(_qfMsg);\n" . " return false;\n" . " }\n" . " return true;\n" . "}\n" . "//]]>\n" . "</script>"; } return ''; } // end func getValidationScript // }}} // {{{ getSubmitValues() /** * Returns the values submitted by the form * * @since 2.0 * @access public * @param bool Whether uploaded files should be returned too * @return array */ function getSubmitValues($mergeFiles = false) { return $mergeFiles? HTML_QuickForm::arrayMerge($this->_submitValues, $this->_submitFiles): $this->_submitValues; } // end func getSubmitValues // }}} // {{{ toArray() /** * Returns the form's contents in an array. * * The description of the array structure is in HTML_QuickForm_Renderer_Array docs * * @since 2.0 * @access public * @param bool Whether to collect hidden elements (passed to the Renderer's constructor) * @return array of form contents */ function toArray($collectHidden = false) { include_once 'HTML/QuickForm/Renderer/Array.php'; $renderer = new HTML_QuickForm_Renderer_Array($collectHidden); //Moodle: PHP 5.3 compatibility $this->accept($renderer); return $renderer->toArray(); } // end func toArray // }}} // {{{ exportValue() /** * Returns a 'safe' element's value * * This method first tries to find a cleaned-up submitted value, * it will return a value set by setValue()/setDefaults()/setConstants() * if submitted value does not exist for the given element. * * @param string Name of an element * @access public * @return mixed */ function exportValue($element) { if (!isset($this->_elementIndex[$element])) { return self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElementValue()", 'HTML_QuickForm_Error', true); } $value = $this->_elements[$this->_elementIndex[$element]]->exportValue($this->_submitValues, false); if (isset($this->_duplicateIndex[$element])) { foreach ($this->_duplicateIndex[$element] as $index) { if (null !== ($v = $this->_elements[$index]->exportValue($this->_submitValues, false))) { if (is_array($value)) { $value[] = $v; } else { $value = (null === $value)? $v: array($value, $v); } } } } return $value; } // }}} // {{{ exportValues() /** * Returns 'safe' elements' values * * Unlike getSubmitValues(), this will return only the values * corresponding to the elements present in the form. * * @param mixed Array/string of element names, whose values we want. If not set then return all elements. * @access public * @return array An assoc array of elements' values * @throws HTML_QuickForm_Error */ function exportValues($elementList = null) { $values = array(); if (null === $elementList) { // iterate over all elements, calling their exportValue() methods foreach (array_keys($this->_elements) as $key) { $value = $this->_elements[$key]->exportValue($this->_submitValues, true); if (is_array($value)) { // This shit throws a bogus warning in PHP 4.3.x $values = HTML_QuickForm::arrayMerge($values, $value); } } } else { if (!is_array($elementList)) { $elementList = array_map('trim', explode(',', $elementList)); } foreach ($elementList as $elementName) { $value = $this->exportValue($elementName); $pear = new PEAR(); if ($pear->isError($value)) { return $value; } $values[$elementName] = $value; } } return $values; } // }}} // {{{ isSubmitted() /** * Tells whether the form was already submitted * * This is useful since the _submitFiles and _submitValues arrays * may be completely empty after the trackSubmit value is removed. * * @access public * @return bool */ function isSubmitted() { return $this->_flagSubmitted; } // }}} // {{{ isError() /** * Tell whether a result from a QuickForm method is an error (an instance of HTML_QuickForm_Error) * * @access public * @param mixed result code * @return bool whether $value is an error */ static function isError($value) { return (is_object($value) && is_a($value, 'html_quickform_error')); } // end func isError // }}} // {{{ errorMessage() /** * Return a textual error message for an QuickForm error code * * @access public * @param int error code * @return string error message */ static function errorMessage($value) { // make the variable static so that it only has to do the defining on the first call static $errorMessages; // define the varies error messages if (!isset($errorMessages)) { $errorMessages = array( QUICKFORM_OK => 'no error', QUICKFORM_ERROR => 'unknown error', QUICKFORM_INVALID_RULE => 'the rule does not exist as a registered rule', QUICKFORM_NONEXIST_ELEMENT => 'nonexistent html element', QUICKFORM_INVALID_FILTER => 'invalid filter', QUICKFORM_UNREGISTERED_ELEMENT => 'unregistered element', QUICKFORM_INVALID_ELEMENT_NAME => 'element already exists', QUICKFORM_INVALID_PROCESS => 'process callback does not exist', QUICKFORM_DEPRECATED => 'method is deprecated', QUICKFORM_INVALID_DATASOURCE => 'datasource is not an object' ); } // If this is an error object, then grab the corresponding error code if (HTML_QuickForm::isError($value)) { $value = $value->getCode(); } // return the textual error message corresponding to the code return isset($errorMessages[$value]) ? $errorMessages[$value] : $errorMessages[QUICKFORM_ERROR]; } // end func errorMessage // }}} } // end class HTML_QuickForm class HTML_QuickForm_Error extends PEAR_Error { // {{{ properties /** * Prefix for all error messages * @var string */ var $error_message_prefix = 'QuickForm Error: '; // }}} // {{{ constructor /** * Creates a quickform error object, extending the PEAR_Error class * * @param int $code the error code * @param int $mode the reaction to the error, either return, die or trigger/callback * @param int $level intensity of the error (PHP error code) * @param mixed $debuginfo any information that can inform user as to nature of the error */ public function __construct($code = QUICKFORM_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null) { if (is_int($code)) { parent::__construct(HTML_QuickForm::errorMessage($code), $code, $mode, $level, $debuginfo); } else { parent::__construct("Invalid error code: $code", QUICKFORM_ERROR, $mode, $level, $debuginfo); } } /** * Old syntax of class constructor. Deprecated in PHP7. * * @deprecated since Moodle 3.1 */ public function HTML_QuickForm_Error($code = QUICKFORM_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null) { debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER); self::__construct($code, $mode, $level, $debuginfo); } // }}} } // end class HTML_QuickForm_Error ?> QuickForm/button.php 0000644 00000005717 15152353724 0010511 0 ustar 00 <?php /* vim: set expandtab tabstop=4 shiftwidth=4: */ // +----------------------------------------------------------------------+ // | PHP version 4.0 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Adam Daniel <adaniel1@eesus.jnj.com> | // | Bertrand Mansion <bmansion@mamasam.com> | // +----------------------------------------------------------------------+ // // $Id$ require_once("HTML/QuickForm/input.php"); /** * HTML class for a button type element * * @author Adam Daniel <adaniel1@eesus.jnj.com> * @author Bertrand Mansion <bmansion@mamasam.com> * @version 1.1 * @since PHP4.04pl1 * @access public */ class HTML_QuickForm_button extends HTML_QuickForm_input { // {{{ constructor /** * Class constructor * * @param string $elementName (optional)Input field name attribute * @param string $value (optional)Input field value * @param mixed $attributes (optional)Either a typical HTML attribute string * or an associative array * @since 1.0 * @access public * @return void */ public function __construct($elementName=null, $value=null, $attributes=null) { parent::__construct($elementName, null, $attributes); $this->_persistantFreeze = false; $this->setValue($value); $this->setType('button'); } //end constructor /** * Old syntax of class constructor. Deprecated in PHP7. * * @deprecated since Moodle 3.1 */ public function HTML_QuickForm_button($elementName=null, $value=null, $attributes=null) { debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER); self::__construct($elementName, $value, $attributes); } // }}} // {{{ freeze() /** * Freeze the element so that only its value is returned * * @access public * @return void */ function freeze() { return false; } //end func freeze // }}} } //end class HTML_QuickForm_button ?> QuickForm/hidden.php 0000644 00000006324 15152353724 0010424 0 ustar 00 <?php /* vim: set expandtab tabstop=4 shiftwidth=4: */ // +----------------------------------------------------------------------+ // | PHP version 4.0 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Adam Daniel <adaniel1@eesus.jnj.com> | // | Bertrand Mansion <bmansion@mamasam.com> | // +----------------------------------------------------------------------+ // // $Id$ require_once("HTML/QuickForm/input.php"); /** * HTML class for a hidden type element * * @author Adam Daniel <adaniel1@eesus.jnj.com> * @author Bertrand Mansion <bmansion@mamasam.com> * @version 1.0 * @since PHP4.04pl1 * @access public */ class HTML_QuickForm_hidden extends HTML_QuickForm_input { // {{{ constructor /** * Class constructor * * @param string $elementName (optional)Input field name attribute * @param string $value (optional)Input field value * @param mixed $attributes (optional)Either a typical HTML attribute string * or an associative array * @since 1.0 * @access public * @return void */ public function __construct($elementName=null, $value='', $attributes=null) { parent::__construct($elementName, null, $attributes); $this->setType('hidden'); $this->setValue($value); } //end constructor /** * Old syntax of class constructor. Deprecated in PHP7. * * @deprecated since Moodle 3.1 */ public function HTML_QuickForm_hidden($elementName=null, $value='', $attributes=null) { debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER); return self::__construct($elementName, $value, $attributes); } // }}} // {{{ freeze() /** * Freeze the element so that only its value is returned * * @access public * @return void */ function freeze() { return false; } //end func freeze // }}} // {{{ accept() /** * Accepts a renderer * * @param object An HTML_QuickForm_Renderer object * @access public * @return void */ function accept(&$renderer, $required=false, $error=null) { $renderer->renderHidden($this); } // end func accept // }}} } //end class HTML_QuickForm_hidden ?> QuickForm/DHTMLRulesTableless.php 0000644 00000016426 15152353724 0012717 0 ustar 00 <?php /** * DHTML replacement for the standard JavaScript alert window for client-side * validation * * PHP versions 4 and 5 * * LICENSE: This source file is subject to version 3.01 of the PHP license * that is available through the world-wide-web at the following URI: * http://www.php.net/license/3_01.txt. If you did not receive a copy of * the PHP License and are unable to obtain it through the web, please * send a note to license@php.net so we can mail you a copy immediately. * * @category HTML * @package HTML_QuickForm_DHTMLRulesTableless * @author Alexey Borzov <borz_off@cs.msu.su> * @author Adam Daniel <adaniel1@eesus.jnj.com> * @author Bertrand Mansion <bmansion@mamasam.com> * @author Justin Patrin <papercrane@gmail.com> * @author Mark Wiesemann <wiesemann@php.net> * @copyright 2005-2006 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License 3.01 * @version CVS: $Id$ * @link http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless */ require_once 'HTML/QuickForm.php'; /** * This is a DHTML replacement for the standard JavaScript alert window for * client-side validation of forms built with HTML_QuickForm * * @category HTML * @package HTML_QuickForm_DHTMLRulesTableless * @author Alexey Borzov <borz_off@cs.msu.su> * @author Adam Daniel <adaniel1@eesus.jnj.com> * @author Bertrand Mansion <bmansion@mamasam.com> * @author Justin Patrin <papercrane@gmail.com> * @author Mark Wiesemann <wiesemann@php.net> * @license http://www.php.net/license/3_01.txt PHP License 3.01 * @version Release: 0.1.3 * @link http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless */ class HTML_QuickForm_DHTMLRulesTableless extends HTML_QuickForm { // {{{ getValidationScript() /** * Returns the client side validation script * * The code here was copied from HTML_QuickForm and slightly modified to run rules per-element * * @access public * @return string Javascript to perform validation, empty string if no 'client' rules were added */ function getValidationScript() { if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) { return ''; } include_once('HTML/QuickForm/RuleRegistry.php'); $registry =& HTML_QuickForm_RuleRegistry::singleton(); $test = array(); $js_escape = array( "\r" => '\r', "\n" => '\n', "\t" => '\t', "'" => "\\'", '"' => '\"', '\\' => '\\\\' ); foreach ($this->_rules as $elementName => $rules) { foreach ($rules as $rule) { if ('client' == $rule['validation']) { unset($element); $dependent = isset($rule['dependent']) && is_array($rule['dependent']); $rule['message'] = strtr($rule['message'], $js_escape); if (isset($rule['group'])) { $group =& $this->getElement($rule['group']); // No JavaScript validation for frozen elements if ($group->isFrozen()) { continue 2; } $elements =& $group->getElements(); foreach (array_keys($elements) as $key) { if ($elementName == $group->getElementName($key)) { $element =& $elements[$key]; break; } } } elseif ($dependent) { $element = array(); $element[] =& $this->getElement($elementName); foreach ($rule['dependent'] as $idx => $elName) { $element[] =& $this->getElement($elName); } } else { $element =& $this->getElement($elementName); } // No JavaScript validation for frozen elements if (is_object($element) && $element->isFrozen()) { continue 2; } elseif (is_array($element)) { foreach (array_keys($element) as $key) { if ($element[$key]->isFrozen()) { continue 3; } } } $test[$elementName][] = $registry->getValidationScript($element, $elementName, $rule); } } } $js = ' <script type="text/javascript"> //<![CDATA[ function qf_errorHandler(element, _qfMsg) { div = element.parentNode; if (_qfMsg != \'\') { span = document.createElement("span"); span.className = "error"; span.appendChild(document.createTextNode(_qfMsg.substring(3))); br = document.createElement("br"); var errorDiv = document.getElementById(element.name + \'_errorDiv\'); if (!errorDiv) { errorDiv = document.createElement("div"); errorDiv.id = element.name + \'_errorDiv\'; } while (errorDiv.firstChild) { errorDiv.removeChild(errorDiv.firstChild); } errorDiv.insertBefore(br, errorDiv.firstChild); errorDiv.insertBefore(span, errorDiv.firstChild); element.parentNode.insertBefore(errorDiv, element.parentNode.firstChild); if (div.className.substr(div.className.length - 6, 6) != " error" && div.className != "error") { div.className += " error"; } return false; } else { var errorDiv = document.getElementById(element.name + \'_errorDiv\'); if (errorDiv) { errorDiv.parentNode.removeChild(errorDiv); } if (div.className.substr(div.className.length - 6, 6) == " error") { div.className = div.className.substr(0, div.className.length - 6); } else if (div.className == "error") { div.className = ""; } return true; } }'; $validateJS = ''; foreach ($test as $elementName => $jsArr) { $js .= ' function validate_' . $this->_attributes['id'] . '_' . $elementName . '(element) { var value = \'\'; var errFlag = new Array(); var _qfGroups = {}; var _qfMsg = \'\'; var frm = element.parentNode; while (frm && frm.nodeName != "FORM") { frm = frm.parentNode; } ' . join("\n", $jsArr) . ' return qf_errorHandler(element, _qfMsg); } '; $validateJS .= ' ret = validate_' . $this->_attributes['id'] . '_' . $elementName.'(frm.elements[\''.$elementName.'\']) && ret;'; unset($element); $element =& $this->getElement($elementName); $valFunc = 'validate_' . $this->_attributes['id'] . '_' . $elementName . '(this)'; $onBlur = $element->getAttribute('onBlur'); $onChange = $element->getAttribute('onChange'); $element->updateAttributes(array('onBlur' => $onBlur . $valFunc, 'onChange' => $onChange . $valFunc)); } $js .= ' function validate_' . $this->_attributes['id'] . '(frm) { var ret = true; ' . $validateJS . '; return ret; } //]]> </script>'; return $js; } // end func getValidationScript // }}} } ?> QuickForm/utils.php 0000644 00000011030 15152353724 0010317 0 ustar 00 <?php /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /** * utility functions * * PHP versions 4 and 5 * * LICENSE: This source file is subject to version 3.01 of the PHP license * that is available through the world-wide-web at the following URI: * http://www.php.net/license/3_01.txt If you did not receive a copy of * the PHP License and are unable to obtain it through the web, please * send a note to license@php.net so we can mail you a copy immediately. * * @category HTML * @package HTML_QuickForm * @author Chuck Burgess <ashnazg@php.net> * @copyright 2001-2018 The PHP Group * @license http://www.php.net/license/3_01.txt PHP License 3.01 * @version CVS: $Id$ * @link http://pear.php.net/package/HTML_QuickForm */ /** * Provides a collection of static methods for array manipulation. * * (courtesy of CiviCRM project (https://civicrm.org/) * * @category HTML * @package HTML_QuickForm * @author Chuck Burgess <ashnazg@php.net> * @version Release: @package_version@ * @since 3.2 */ class HTML_QuickForm_utils { /** * Get a single value from an array-tree. * * @param array $values Ex: ['foo' => ['bar' => 123]]. * @param array $path Ex: ['foo', 'bar']. * @param mixed $default * @return mixed Ex 123. * * @access public * @static */ static function pathGet($values, $path, $default = NULL) { foreach ($path as $key) { if (!is_array($values) || !isset($values[$key])) { return $default; } $values = $values[$key]; } return $values; } /** * Check if a key isset which may be several layers deep. * * This is a helper for when the calling function does not know how many layers deep * the path array is so cannot easily check. * * @param array $values * @param array $path * @return bool * * @access public * @static */ static function pathIsset($values, $path) { foreach ($path as $key) { if (!is_array($values) || !isset($values[$key])) { return FALSE; } $values = $values[$key]; } return TRUE; } /** * Set a single value in an array tree. * * @param array $values Ex: ['foo' => ['bar' => 123]]. * @param array $pathParts Ex: ['foo', 'bar']. * @param mixed $value Ex: 456. * @return void * * @access public * @static */ static function pathSet(&$values, $pathParts, $value) { $r = &$values; $last = array_pop($pathParts); foreach ($pathParts as $part) { if (!isset($r[$part])) { $r[$part] = array(); } $r = &$r[$part]; } $r[$last] = $value; } /** * Check if a key isset which may be several layers deep. * * This is a helper for when the calling function does not know how many layers deep the * path array is so cannot easily check. * * @param array $array * @param array $path * @return bool * * @access public * @static */ static function recursiveIsset($array, $path) { return self::pathIsset($array, $path); } /** * Check if a key isset which may be several layers deep. * * This is a helper for when the calling function does not know how many layers deep the * path array is so cannot easily check. * * @param array $array * @param array $path An array of keys, * e.g [0, 'bob', 8] where we want to check if $array[0]['bob'][8] * @param mixed $default Value to return if not found. * @return bool * * @access public * @static */ static function recursiveValue($array, $path, $default = NULL) { return self::pathGet($array, $path, $default); } /** * Append the value to the array using the key provided. * * e.g if value is 'llama' & path is [0, 'email', 'location'] result will be * [0 => ['email' => ['location' => 'llama']] * * @param $path * @param $value * @param array $source * @return array * * @access public * @static */ static function recursiveBuild($path, $value, $source = array()) { self::pathSet($source, $path, $value); return $source; } } ?> QuickForm/group.php 0000644 00000043243 15152353724 0010326 0 ustar 00 <?php /* vim: set expandtab tabstop=4 shiftwidth=4: */ // +----------------------------------------------------------------------+ // | PHP version 4.0 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.0 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Adam Daniel <adaniel1@eesus.jnj.com> | // | Bertrand Mansion <bmansion@mamasam.com> | // +----------------------------------------------------------------------+ // // $Id$ require_once("HTML/QuickForm/element.php"); /** * HTML class for a form element group * * @author Adam Daniel <adaniel1@eesus.jnj.com> * @author Bertrand Mansion <bmansion@mamasam.com> * @version 1.0 * @since PHP4.04pl1 * @access public */ class HTML_QuickForm_group extends HTML_QuickForm_element { // {{{ properties /** * Name of the element * @var string * @since 1.0 * @access private */ var $_name = ''; /** * Array of grouped elements * @var array * @since 1.0 * @access private */ var $_elements = array(); /** * String to separate elements * @var mixed * @since 2.5 * @access private */ var $_separator = null; /** * Required elements in this group * @var array * @since 2.5 * @access private */ var $_required = array(); /** * Whether to change elements' names to $groupName[$elementName] or leave them as is * @var bool * @since 3.0 * @access private */ var $_appendName = true; // }}} // {{{ constructor /** * Class constructor * * @param string $elementName (optional)Group name * @param array $elementLabel (optional)Group label * @param array $elements (optional)Group elements * @param mixed $separator (optional)Use a string for one separator, * use an array to alternate the separators. * @param bool $appendName (optional)whether to change elements' names to * the form $groupName[$elementName] or leave * them as is. * @since 1.0 * @access public * @return void */ public function __construct($elementName=null, $elementLabel=null, $elements=null, $separator=null, $appendName = true) { parent::__construct($elementName, $elementLabel); $this->_type = 'group'; if (isset($elements) && is_array($elements)) { $this->setElements($elements); } if (isset($separator)) { $this->_separator = $separator; } if (isset($appendName)) { $this->_appendName = $appendName; } } //end constructor /** * Old syntax of class constructor. Deprecated in PHP7. * * @deprecated since Moodle 3.1 */ public function HTML_QuickForm_group($elementName=null, $elementLabel=null, $elements=null, $separator=null, $appendName = true) { debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER); self::__construct($elementName, $elementLabel, $elements, $separator, $appendName); } // }}} // {{{ setName() /** * Sets the group name * * @param string $name Group name * @since 1.0 * @access public * @return void */ function setName($name) { $this->_name = $name; } //end func setName // }}} // {{{ getName() /** * Returns the group name * * @since 1.0 * @access public * @return string */ function getName() { return $this->_name; } //end func getName // }}} // {{{ setValue() /** * Sets values for group's elements * * @param mixed Values for group's elements * @since 1.0 * @access public * @return void */ function setValue($value) { $this->_createElementsIfNotExist(); foreach (array_keys($this->_elements) as $key) { if (!$this->_appendName) { $v = $this->_elements[$key]->_findValue($value); if (null !== $v) { $this->_elements[$key]->onQuickFormEvent('setGroupValue', $v, $this); } } else { $elementName = $this->_elements[$key]->getName(); $index = strlen($elementName) ? $elementName : $key; if (is_array($value)) { if (isset($value[$index])) { $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value[$index], $this); } } elseif (isset($value)) { $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value, $this); } } } } //end func setValue // }}} // {{{ getValue() /** * Returns the value of the group * * @since 1.0 * @access public * @return mixed */ function getValue() { $value = null; foreach (array_keys($this->_elements) as $key) { $element =& $this->_elements[$key]; switch ($element->getType()) { case 'radio': $v = $element->getChecked()? $element->getValue(): null; break; case 'checkbox': $v = $element->getChecked()? true: null; break; default: $v = $element->getValue(); } if (null !== $v) { $elementName = $element->getName(); if (is_null($elementName)) { $value = $v; } else { if (!is_array($value)) { $value = is_null($value)? array(): array($value); } if ('' === $elementName) { $value[] = $v; } else { $value[$elementName] = $v; } } } } return $value; } // end func getValue // }}} // {{{ setElements() /** * Sets the grouped elements * * @param array $elements Array of elements * @since 1.1 * @access public * @return void */ function setElements($elements) { $this->_elements = array_values($elements); if ($this->_flagFrozen) { $this->freeze(); } } // end func setElements // }}} // {{{ getElements() /** * Gets the grouped elements * * @since 2.4 * @access public * @return array */ function &getElements() { $this->_createElementsIfNotExist(); return $this->_elements; } // end func getElements // }}} // {{{ getGroupType() /** * Gets the group type based on its elements * Will return 'mixed' if elements contained in the group * are of different types. * * @access public * @return string group elements type */ function getGroupType() { $this->_createElementsIfNotExist(); $prevType = ''; foreach (array_keys($this->_elements) as $key) { $type = $this->_elements[$key]->getType(); if ($type != $prevType && $prevType != '') { return 'mixed'; } $prevType = $type; } return $type; } // end func getGroupType // }}} // {{{ toHtml() /** * Returns Html for the group * * @since 1.0 * @access public * @return string */ function toHtml() { include_once('HTML/QuickForm/Renderer/Default.php'); $renderer = new HTML_QuickForm_Renderer_Default(); $renderer->setElementTemplate('{element}'); $this->accept($renderer); return $renderer->toHtml(); } //end func toHtml // }}} // {{{ getElementName() /** * Returns the element name inside the group such as found in the html form * * @param mixed $index Element name or element index in the group * @since 3.0 * @access public * @return mixed string with element name, false if not found */ function getElementName($index) { $this->_createElementsIfNotExist(); $elementName = false; if (is_int($index) && isset($this->_elements[$index])) { $elementName = $this->_elements[$index]->getName(); if (isset($elementName) && $elementName == '') { $elementName = $index; } if ($this->_appendName) { if (is_null($elementName)) { $elementName = $this->getName(); } else { $elementName = $this->getName().'['.$elementName.']'; } } } elseif (is_string($index)) { foreach (array_keys($this->_elements) as $key) { $elementName = $this->_elements[$key]->getName(); if ($index == $elementName) { if ($this->_appendName) { $elementName = $this->getName().'['.$elementName.']'; } break; } elseif ($this->_appendName && $this->getName().'['.$elementName.']' == $index) { break; } } } return $elementName; } //end func getElementName // }}} // {{{ getFrozenHtml() /** * Returns the value of field without HTML tags * * @since 1.3 * @access public * @return string */ function getFrozenHtml() { $flags = array(); $this->_createElementsIfNotExist(); foreach (array_keys($this->_elements) as $key) { if (false === ($flags[$key] = $this->_elements[$key]->isFrozen())) { $this->_elements[$key]->freeze(); } } $html = $this->toHtml(); foreach (array_keys($this->_elements) as $key) { if (!$flags[$key]) { $this->_elements[$key]->unfreeze(); } } return $html; } //end func getFrozenHtml // }}} // {{{ onQuickFormEvent() /** * Called by HTML_QuickForm whenever form event is made on this element * * @param string $event Name of event * @param mixed $arg event arguments * @param object $caller calling object * @since 1.0 * @access public * @return void */ function onQuickFormEvent($event, $arg, &$caller) { switch ($event) { case 'updateValue': $this->_createElementsIfNotExist(); foreach (array_keys($this->_elements) as $key) { if ($this->_appendName) { $elementName = $this->_elements[$key]->getName(); if (is_null($elementName)) { $this->_elements[$key]->setName($this->getName()); } elseif ('' === $elementName) { $this->_elements[$key]->setName($this->getName() . '[' . $key . ']'); } else { $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']'); } } $this->_elements[$key]->onQuickFormEvent('updateValue', $arg, $caller); if ($this->_appendName) { $this->_elements[$key]->setName($elementName); } } break; default: parent::onQuickFormEvent($event, $arg, $caller); } return true; } // end func onQuickFormEvent // }}} // {{{ accept() /** * Accepts a renderer * * @param object An HTML_QuickForm_Renderer object * @param bool Whether a group is required * @param string An error message associated with a group * @access public * @return void */ function accept(&$renderer, $required = false, $error = null) { $this->_createElementsIfNotExist(); $renderer->startGroup($this, $required, $error); $name = $this->getName(); foreach (array_keys($this->_elements) as $key) { $element =& $this->_elements[$key]; if ($this->_appendName) { $elementName = $element->getName(); if (isset($elementName)) { $element->setName($name . '['. (strlen($elementName)? $elementName: $key) .']'); } else { $element->setName($name); } } $required = !$element->isFrozen() && in_array($element->getName(), $this->_required); $element->accept($renderer, $required); // restore the element's name if ($this->_appendName) { $element->setName($elementName); } } $renderer->finishGroup($this); } // end func accept // }}} // {{{ exportValue() /** * As usual, to get the group's value we access its elements and call * their exportValue() methods */ function exportValue(&$submitValues, $assoc = false) { $value = null; foreach (array_keys($this->_elements) as $key) { $elementName = $this->_elements[$key]->getName(); if ($this->_appendName) { if (is_null($elementName)) { $this->_elements[$key]->setName($this->getName()); } elseif ('' === $elementName) { $this->_elements[$key]->setName($this->getName() . '[' . $key . ']'); } else { $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']'); } } $v = $this->_elements[$key]->exportValue($submitValues, $assoc); if ($this->_appendName) { $this->_elements[$key]->setName($elementName); } if (null !== $v) { // Make $value an array, we will use it like one if (null === $value) { $value = array(); } if ($assoc) { // just like HTML_QuickForm::exportValues() $value = HTML_QuickForm::arrayMerge($value, $v); } else { // just like getValue(), but should work OK every time here if (is_null($elementName)) { $value = $v; } elseif ('' === $elementName) { $value[] = $v; } else { $value[$elementName] = $v; } } } } // do not pass the value through _prepareValue, we took care of this already return $value; } // }}} // {{{ _createElements() /** * Creates the group's elements. * * This should be overriden by child classes that need to create their * elements. The method will be called automatically when needed, calling * it from the constructor is discouraged as the constructor is usually * called _twice_ on element creation, first time with _no_ parameters. * * @access private * @abstract */ function _createElements() { // abstract } // }}} // {{{ _createElementsIfNotExist() /** * A wrapper around _createElements() * * This method calls _createElements() if the group's _elements array * is empty. It also performs some updates, e.g. freezes the created * elements if the group is already frozen. * * @access private */ function _createElementsIfNotExist() { if (empty($this->_elements)) { $this->_createElements(); if ($this->_flagFrozen) { $this->freeze(); } } } // }}} // {{{ freeze() function freeze() { parent::freeze(); foreach (array_keys($this->_elements) as $key) { $this->_elements[$key]->freeze(); } } // }}} // {{{ unfreeze() function unfreeze() { parent::unfreeze(); foreach (array_keys($this->_elements) as $key) { $this->_elements[$key]->unfreeze(); } } // }}} // {{{ setPersistantFreeze() function setPersistantFreeze($persistant = false) { parent::setPersistantFreeze($persistant); foreach (array_keys($this->_elements) as $key) { $this->_elements[$key]->setPersistantFreeze($persistant); } } // }}} } //end class HTML_QuickForm_group ?>