1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981 |
- <?php
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
- /**
- * Create, validate and process HTML forms
- *
- * 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 Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @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
- /**#@+
- * 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 <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Alexey Borzov <avb@php.net>
- * @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 = '<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
- */
- 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 <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 == '') ? 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'];
- }
- }
- // $course_id = api_get_course_int_id();
- // //If I'm in a course replace the default max filesize with the course limits
- // if (!empty($course_id)) {
- // $free_course_quota = DocumentManager::get_course_quota() - DocumentManager::documents_total_space();
- // if (empty($this->_maxFileSize) || $free_course_quota <= $this->_maxFileSize) {
- // $this->_maxFileSize = intval($free_course_quota);
- // }
- // }
- }
- /**
- * 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
- */
- 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
- * @return void
- */
- 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 = HTML_QuickForm::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 = HTML_QuickForm::_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;
- }
- 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 string $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)
- {
- static $anonGroups = 1;
- if (0 == strlen($name)) {
- $name = 'qf_group_' . $anonGroups++;
- $appendName = false;
- }
- $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
- */
- 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
- */
- 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
- */
- 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 = 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
- */
- 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
- */
- 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 <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;
- }
- if ($validation == 'client') {
- $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);'));
- }
- }
- } // 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
- */
- public function addFormRule($rule)
- {
- if (!is_callable($rule)) {
- throw new \Exception('Callback function does not exist in HTML_QuickForm::addFormRule()');
- }
- $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
- * @throws HTML_QuickForm_Error
- */
- function applyFilter($element, $filter)
- {
- if (!is_callable($filter)) {
- throw new \Exception("Callback function does not exist in QuickForm::applyFilter()");
- }
- 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 public
- * @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)
- {
- 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
- */
- static function isTypeRegistered($type)
- {
- return isset($GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($type)]);
- }
- /**
- * 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)
- {
- return true;
- }
- /**
- * 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;
- }
- /**
- * Performs the server side validation
- * @access public
- * @since 1.0
- * @return boolean true if no error found
- * @throws HTML_QuickForm_Error
- */
- public function validate()
- {
- if (count($this->_rules) == 0 && count($this->_formRules) == 0 &&
- $this->isSubmitted()) {
- return (0 == count($this->_errors));
- } elseif (!$this->isSubmitted()) {
- return false;
- }
- $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.
- // See also bug #12014, we should only consider a file that has
- // status UPLOAD_ERR_NO_FILE as not uploaded, in all other cases
- // validation should be performed, so that e.g. 'maxfilesize' rule
- // will display an error if status is UPLOAD_ERR_INI_SIZE
- // or UPLOAD_ERR_FORM_SIZE
- } elseif (is_array($submitValue)) {
- if (false === ($pos = strpos($target, '['))) {
- $isUpload = !empty($this->_submitFiles[$target]);
- } else {
- $base = str_replace(
- array('\\', '\''), array('\\\\', '\\\''),
- 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']) || UPLOAD_ERR_NO_FILE == $submitValue['error'])) {
- continue 2;
- }
- }
- }
- if (isset($rule['dependent'])) {
- $values = array($submitValue);
- if (is_array($rule['dependent'])) {
- foreach ($rule['dependent'] as $elName) {
- $values[] = $this->getSubmitValue($elName);
- }
- } else {
- $values[] = $rule['dependent'];
- }
- $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 {
- throw new \Exception('Form rule callback returned invalid value in HTML_QuickForm::validate()');
- }
- }
- }
- return (0 == count($this->_errors));
- }
- /**
- * 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
- */
- public function freeze($elementList = null, $setTemplateFrozen = '')
- {
- 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])) {
- if (!empty($setTemplateFrozen)) {
- $this->_elements[$key]->setCustomFrozenTemplate($setTemplateFrozen);
- }
- $this->_elements[$key]->freeze();
- unset($elementList[$name]);
- }
- }
- if (!empty($elementList)) {
- throw new \Exception("Nonexistant element(s): '" . implode("', '", array_keys($elementList)) . "' in HTML_QuickForm::freeze()");
- }
- return true;
- }
- /**
- * Returns whether or not the whole form is frozen
- *
- * @since 3.0
- * @access public
- * @return boolean
- */
- public function isFrozen()
- {
- return $this->_freezeAll;
- }
- /**
- * 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
- * @return mixed Whatever value the $callback function returns
- */
- public function process($callback, $mergeFiles = true)
- {
- if (!is_callable($callback)) {
- throw new \Exception("Callback function does not exist in QuickForm::process()");
- }
- $values = ($mergeFiles === true) ? HTML_QuickForm::arrayMerge($this->_submitValues, $this->_submitFiles) : $this->_submitValues;
- return call_user_func($callback, $values);
- }
- /**
- * Accepts a renderer
- *
- * @param object An HTML_QuickForm_Renderer object
- * @since 3.0
- * @access public
- * @return void
- */
- public 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);
- }
- /**
- * Returns a reference to default renderer object
- *
- * @access public
- * @since 3.0
- * @return HTML_QuickForm_Renderer_Default
- */
- public function &defaultRenderer()
- {
- if (!isset($GLOBALS['_HTML_QuickForm_default_renderer'])) {
- // Modified by Ivan Tcholakov, 16-MAR-2010. Suppressing a deprecation warning on PHP 5.3
- //$GLOBALS['_HTML_QuickForm_default_renderer'] =& new HTML_QuickForm_Renderer_Default();
- $GLOBALS['_HTML_QuickForm_default_renderer'] = new HTML_QuickForm_Renderer_Default();
- }
- return $GLOBALS['_HTML_QuickForm_default_renderer'];
- }
- /**
- * 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
- */
- 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();
- }
- /**
- * 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
- */
- public function getValidationScript()
- {
- if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) {
- return '';
- }
- $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
- "<script>" .
- "//<![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 '';
- }
- /**
- * Returns the values submitted by the form
- *
- * @since 2.0
- * @access public
- * @param bool Whether uploaded files should be returned too
- * @return array
- */
- public function getSubmitValues($mergeFiles = false)
- {
- return $mergeFiles ? HTML_QuickForm::arrayMerge($this->_submitValues, $this->_submitFiles): $this->_submitValues;
- }
- /**
- * 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
- */
- public function toArray($collectHidden = false)
- {
- include_once 'HTML/QuickForm/Renderer/Array.php';
- // Modified by Ivan Tcholakov, 16-MAR-2010. Suppressing a deprecation warning on PHP 5.3
- //$renderer =& new HTML_QuickForm_Renderer_Array($collectHidden);
- $renderer = new HTML_QuickForm_Renderer_Array($collectHidden);
- //
- $this->accept($renderer);
- return $renderer->toArray();
- }
- /**
- * 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
- * @throws HTML_QuickForm_Error
- */
- public function exportValue($element)
- {
- if (!isset($this->_elementIndex[$element])) {
- throw new \Exception("Element '$element' does not exist in HTML_QuickForm::getElementValue()");
- }
- $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;
- }
- /**
- * 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
- */
- public 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);
- if (PEAR::isError($value)) {
- return $value;
- }
- $values[$elementName] = $value;
- }
- }
- return $values;
- }
- /**
- * 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
- */
- public function isSubmitted()
- {
- return $this->_flagSubmitted;
- }
- /**
- * 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
- */
- public function isError($value)
- {
- return (is_object($value) && is_a($value, 'html_quickform_error'));
- }
- /**
- * Return a textual error message for an QuickForm error code
- *
- * @access public
- * @param int error code
- * @return string error message
- * @static
- */
- public 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];
- }
- /**
- * @param HTML_QuickForm_element $element
- */
- public function setRequired(HTML_QuickForm_element $element)
- {
- $this->addRule(
- $element->getName(),
- get_lang('ThisFieldIsRequired'),
- 'required'
- );
- }
- }
- /**
- * Class for errors thrown by HTML_QuickForm package
- *
- * @category HTML
- * @package HTML_QuickForm
- * @author Adam Daniel <adaniel1@eesus.jnj.com>
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @version Release: 3.2.11
- */
- class HTML_QuickForm_Error extends PEAR_Error
- {
- /**
- * Prefix for all error messages
- * @var string
- */
- public $error_message_prefix = 'QuickForm Error: ';
- /**
- * 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);
- }
- }
- }
|