MDL-41908 QuickForm: Fix PEAR Non-static method error
[moodle.git] / lib / pear / HTML / QuickForm.php
CommitLineData
da6f8763 1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4: */
3// +----------------------------------------------------------------------+
4// | PHP version 4.0 |
5// +----------------------------------------------------------------------+
6// | Copyright (c) 1997-2003 The PHP Group |
7// +----------------------------------------------------------------------+
8// | This source file is subject to version 2.0 of the PHP license, |
9// | that is bundled with this package in the file LICENSE, and is |
10// | available at through the world-wide-web at |
11// | http://www.php.net/license/2_02.txt. |
12// | If you did not receive a copy of the PHP license and are unable to |
13// | obtain it through the world-wide-web, please send a note to |
14// | license@php.net so we can mail you a copy immediately. |
15// +----------------------------------------------------------------------+
16// | Authors: Adam Daniel <adaniel1@eesus.jnj.com> |
17// | Bertrand Mansion <bmansion@mamasam.com> |
18// +----------------------------------------------------------------------+
19//
20// $Id$
21
22require_once('PEAR.php');
23require_once('HTML/Common.php');
24
e56458a7 25$GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'] =
da6f8763 26 array(
27 'group' =>array('HTML/QuickForm/group.php','HTML_QuickForm_group'),
28 'hidden' =>array('HTML/QuickForm/hidden.php','HTML_QuickForm_hidden'),
29 'reset' =>array('HTML/QuickForm/reset.php','HTML_QuickForm_reset'),
30 'checkbox' =>array('HTML/QuickForm/checkbox.php','HTML_QuickForm_checkbox'),
31 'file' =>array('HTML/QuickForm/file.php','HTML_QuickForm_file'),
32 'image' =>array('HTML/QuickForm/image.php','HTML_QuickForm_image'),
33 'password' =>array('HTML/QuickForm/password.php','HTML_QuickForm_password'),
34 'radio' =>array('HTML/QuickForm/radio.php','HTML_QuickForm_radio'),
35 'button' =>array('HTML/QuickForm/button.php','HTML_QuickForm_button'),
36 'submit' =>array('HTML/QuickForm/submit.php','HTML_QuickForm_submit'),
37 'select' =>array('HTML/QuickForm/select.php','HTML_QuickForm_select'),
38 'hiddenselect' =>array('HTML/QuickForm/hiddenselect.php','HTML_QuickForm_hiddenselect'),
39 'text' =>array('HTML/QuickForm/text.php','HTML_QuickForm_text'),
40 'textarea' =>array('HTML/QuickForm/textarea.php','HTML_QuickForm_textarea'),
41 'link' =>array('HTML/QuickForm/link.php','HTML_QuickForm_link'),
42 'advcheckbox' =>array('HTML/QuickForm/advcheckbox.php','HTML_QuickForm_advcheckbox'),
43 'date' =>array('HTML/QuickForm/date.php','HTML_QuickForm_date'),
44 'static' =>array('HTML/QuickForm/static.php','HTML_QuickForm_static'),
45 'header' =>array('HTML/QuickForm/header.php', 'HTML_QuickForm_header'),
46 'html' =>array('HTML/QuickForm/html.php', 'HTML_QuickForm_html'),
47 'hierselect' =>array('HTML/QuickForm/hierselect.php', 'HTML_QuickForm_hierselect'),
48 'autocomplete' =>array('HTML/QuickForm/autocomplete.php', 'HTML_QuickForm_autocomplete'),
49 'xbutton' =>array('HTML/QuickForm/xbutton.php','HTML_QuickForm_xbutton')
50 );
51
52$GLOBALS['_HTML_QuickForm_registered_rules'] = array(
53 'required' => array('html_quickform_rule_required', 'HTML/QuickForm/Rule/Required.php'),
54 'maxlength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'),
55 'minlength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'),
56 'rangelength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'),
57 'email' => array('html_quickform_rule_email', 'HTML/QuickForm/Rule/Email.php'),
58 'regex' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
59 'lettersonly' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
60 'alphanumeric' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
61 'numeric' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
62 'nopunctuation' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
63 'nonzero' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'),
64 'callback' => array('html_quickform_rule_callback', 'HTML/QuickForm/Rule/Callback.php'),
65 'compare' => array('html_quickform_rule_compare', 'HTML/QuickForm/Rule/Compare.php')
66);
67
68// {{{ error codes
69
70/*
71 * Error codes for the QuickForm interface, which will be mapped to textual messages
72 * in the QuickForm::errorMessage() function. If you are to add a new error code, be
73 * sure to add the textual messages to the QuickForm::errorMessage() function as well
74 */
75
76define('QUICKFORM_OK', 1);
77define('QUICKFORM_ERROR', -1);
78define('QUICKFORM_INVALID_RULE', -2);
79define('QUICKFORM_NONEXIST_ELEMENT', -3);
80define('QUICKFORM_INVALID_FILTER', -4);
81define('QUICKFORM_UNREGISTERED_ELEMENT', -5);
82define('QUICKFORM_INVALID_ELEMENT_NAME', -6);
83define('QUICKFORM_INVALID_PROCESS', -7);
84define('QUICKFORM_DEPRECATED', -8);
85define('QUICKFORM_INVALID_DATASOURCE', -9);
86
87// }}}
88
89/**
90* Create, validate and process HTML forms
91*
92* @author Adam Daniel <adaniel1@eesus.jnj.com>
93* @author Bertrand Mansion <bmansion@mamasam.com>
94* @version 2.0
95* @since PHP 4.0.3pl1
96*/
97class HTML_QuickForm extends HTML_Common {
98 // {{{ properties
99
100 /**
101 * Array containing the form fields
102 * @since 1.0
103 * @var array
104 * @access private
105 */
106 var $_elements = array();
107
108 /**
109 * Array containing element name to index map
110 * @since 1.1
111 * @var array
112 * @access private
113 */
114 var $_elementIndex = array();
115
116 /**
117 * Array containing indexes of duplicate elements
118 * @since 2.10
119 * @var array
120 * @access private
121 */
122 var $_duplicateIndex = array();
123
124 /**
125 * Array containing required field IDs
126 * @since 1.0
127 * @var array
128 * @access private
e56458a7 129 */
da6f8763 130 var $_required = array();
131
132 /**
133 * Prefix message in javascript alert if error
134 * @since 1.0
135 * @var string
136 * @access public
e56458a7 137 */
da6f8763 138 var $_jsPrefix = 'Invalid information entered.';
139
140 /**
141 * Postfix message in javascript alert if error
142 * @since 1.0
143 * @var string
144 * @access public
e56458a7 145 */
da6f8763 146 var $_jsPostfix = 'Please correct these fields.';
147
148 /**
149 * Datasource object implementing the informal
150 * datasource protocol
151 * @since 3.3
152 * @var object
153 * @access private
154 */
155 var $_datasource;
156
157 /**
158 * Array of default form values
159 * @since 2.0
160 * @var array
161 * @access private
162 */
163 var $_defaultValues = array();
164
165 /**
166 * Array of constant form values
167 * @since 2.0
168 * @var array
169 * @access private
170 */
171 var $_constantValues = array();
172
173 /**
174 * Array of submitted form values
175 * @since 1.0
176 * @var array
177 * @access private
178 */
179 var $_submitValues = array();
180
181 /**
182 * Array of submitted form files
183 * @since 1.0
184 * @var integer
185 * @access public
186 */
187 var $_submitFiles = array();
188
189 /**
190 * Value for maxfilesize hidden element if form contains file input
191 * @since 1.0
192 * @var integer
193 * @access public
194 */
195 var $_maxFileSize = 1048576; // 1 Mb = 1048576
196
197 /**
198 * Flag to know if all fields are frozen
199 * @since 1.0
200 * @var boolean
201 * @access private
202 */
203 var $_freezeAll = false;
204
205 /**
206 * Array containing the form rules
207 * @since 1.0
208 * @var array
209 * @access private
210 */
211 var $_rules = array();
212
213 /**
214 * Form rules, global variety
215 * @var array
216 * @access private
217 */
218 var $_formRules = array();
219
220 /**
221 * Array containing the validation errors
222 * @since 1.0
223 * @var array
224 * @access private
225 */
226 var $_errors = array();
227
228 /**
229 * Note for required fields in the form
230 * @var string
231 * @since 1.0
232 * @access private
233 */
234 var $_requiredNote = '<span style="font-size:80%; color:#ff0000;">*</span><span style="font-size:80%;"> denotes required field</span>';
235
236 /**
237 * Whether the form was submitted
238 * @var boolean
239 * @access private
240 */
241 var $_flagSubmitted = false;
242
243 // }}}
244 // {{{ constructor
245
246 /**
247 * Class constructor
248 * @param string $formName Form's name.
249 * @param string $method (optional)Form's method defaults to 'POST'
250 * @param string $action (optional)Form's action
251 * @param string $target (optional)Form's target defaults to '_self'
252 * @param mixed $attributes (optional)Extra attributes for <form> tag
253 * @param bool $trackSubmit (optional)Whether to track if the form was submitted by adding a special hidden field
254 * @access public
255 */
256 function HTML_QuickForm($formName='', $method='post', $action='', $target='', $attributes=null, $trackSubmit = false)
257 {
258 HTML_Common::HTML_Common($attributes);
259 $method = (strtoupper($method) == 'GET') ? 'get' : 'post';
260 $action = ($action == '') ? $_SERVER['PHP_SELF'] : $action;
261 $target = empty($target) ? array() : array('target' => $target);
262 $attributes = array('action'=>$action, 'method'=>$method, 'name'=>$formName, 'id'=>$formName) + $target;
263 $this->updateAttributes($attributes);
264 if (!$trackSubmit || isset($_REQUEST['_qf__' . $formName])) {
265 if (1 == get_magic_quotes_gpc()) {
714dac9f 266 $this->_submitValues = ('get' == $method? $_GET: $_POST); // we already eliminated magic quotes in moodle setup.php
da6f8763 267 foreach ($_FILES as $keyFirst => $valFirst) {
268 foreach ($valFirst as $keySecond => $valSecond) {
269 if ('name' == $keySecond) {
714dac9f 270 $this->_submitFiles[$keyFirst][$keySecond] = $valSecond; // we already eliminated magic quotes in moodle setup.php
da6f8763 271 } else {
272 $this->_submitFiles[$keyFirst][$keySecond] = $valSecond;
273 }
274 }
275 }
276 } else {
277 $this->_submitValues = 'get' == $method? $_GET: $_POST;
278 $this->_submitFiles = $_FILES;
279 }
280 $this->_flagSubmitted = count($this->_submitValues) > 0 || count($this->_submitFiles) > 0;
281 }
282 if ($trackSubmit) {
283 unset($this->_submitValues['_qf__' . $formName]);
284 $this->addElement('hidden', '_qf__' . $formName, null);
285 }
286 if (preg_match('/^([0-9]+)([a-zA-Z]*)$/', ini_get('upload_max_filesize'), $matches)) {
287 // see http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
288 switch (strtoupper($matches['2'])) {
289 case 'G':
290 $this->_maxFileSize = $matches['1'] * 1073741824;
291 break;
292 case 'M':
293 $this->_maxFileSize = $matches['1'] * 1048576;
294 break;
295 case 'K':
296 $this->_maxFileSize = $matches['1'] * 1024;
297 break;
298 default:
299 $this->_maxFileSize = $matches['1'];
300 }
e56458a7 301 }
da6f8763 302 } // end constructor
303
304 // }}}
305 // {{{ apiVersion()
306
307 /**
308 * Returns the current API version
309 *
310 * @since 1.0
311 * @access public
312 * @return float
313 */
314 function apiVersion()
315 {
316 return 3.2;
317 } // end func apiVersion
318
319 // }}}
320 // {{{ registerElementType()
321
322 /**
323 * Registers a new element type
324 *
325 * @param string $typeName Name of element type
326 * @param string $include Include path for element type
327 * @param string $className Element class name
328 * @since 1.0
329 * @access public
330 * @return void
331 */
fabbf439 332 static function registerElementType($typeName, $include, $className)
da6f8763 333 {
334 $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($typeName)] = array($include, $className);
335 } // end func registerElementType
336
337 // }}}
338 // {{{ registerRule()
339
340 /**
341 * Registers a new validation rule
342 *
343 * @param string $ruleName Name of validation rule
344 * @param string $type Either: 'regex', 'function' or 'rule' for an HTML_QuickForm_Rule object
345 * @param string $data1 Name of function, regular expression or HTML_QuickForm_Rule classname
346 * @param string $data2 Object parent of above function or HTML_QuickForm_Rule file path
347 * @since 1.0
348 * @access public
349 * @return void
350 */
fabbf439 351 static function registerRule($ruleName, $type, $data1, $data2 = null)
da6f8763 352 {
353 include_once('HTML/QuickForm/RuleRegistry.php');
354 $registry =& HTML_QuickForm_RuleRegistry::singleton();
355 $registry->registerRule($ruleName, $type, $data1, $data2);
356 } // end func registerRule
357
358 // }}}
359 // {{{ elementExists()
360
361 /**
362 * Returns true if element is in the form
363 *
364 * @param string $element form name of element to check
365 * @since 1.0
366 * @access public
367 * @return boolean
368 */
369 function elementExists($element=null)
370 {
371 return isset($this->_elementIndex[$element]);
372 } // end func elementExists
373
374 // }}}
375 // {{{ setDatasource()
376
377 /**
378 * Sets a datasource object for this form object
379 *
380 * Datasource default and constant values will feed the QuickForm object if
381 * the datasource implements defaultValues() and constantValues() methods.
382 *
383 * @param object $datasource datasource object implementing the informal datasource protocol
384 * @param mixed $defaultsFilter string or array of filter(s) to apply to default values
385 * @param mixed $constantsFilter string or array of filter(s) to apply to constants values
386 * @since 3.3
387 * @access public
388 * @return void
389 */
390 function setDatasource(&$datasource, $defaultsFilter = null, $constantsFilter = null)
391 {
392 if (is_object($datasource)) {
393 $this->_datasource =& $datasource;
394 if (is_callable(array($datasource, 'defaultValues'))) {
395 $this->setDefaults($datasource->defaultValues($this), $defaultsFilter);
396 }
397 if (is_callable(array($datasource, 'constantValues'))) {
398 $this->setConstants($datasource->constantValues($this), $constantsFilter);
399 }
400 } else {
66b3302d 401 return self::raiseError(null, QUICKFORM_INVALID_DATASOURCE, null, E_USER_WARNING, "Datasource is not an object in QuickForm::setDatasource()", 'HTML_QuickForm_Error', true);
da6f8763 402 }
403 } // end func setDatasource
404
405 // }}}
406 // {{{ setDefaults()
407
408 /**
409 * Initializes default form values
410 *
411 * @param array $defaultValues values used to fill the form
412 * @param mixed $filter (optional) filter(s) to apply to all default values
413 * @since 1.0
414 * @access public
415 * @return void
416 */
417 function setDefaults($defaultValues = null, $filter = null)
418 {
419 if (is_array($defaultValues)) {
420 if (isset($filter)) {
421 if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) {
422 foreach ($filter as $val) {
423 if (!is_callable($val)) {
66b3302d 424 return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true);
da6f8763 425 } else {
426 $defaultValues = $this->_recursiveFilter($val, $defaultValues);
427 }
428 }
429 } elseif (!is_callable($filter)) {
66b3302d 430 return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true);
da6f8763 431 } else {
432 $defaultValues = $this->_recursiveFilter($filter, $defaultValues);
433 }
434 }
435 $this->_defaultValues = HTML_QuickForm::arrayMerge($this->_defaultValues, $defaultValues);
436 foreach (array_keys($this->_elements) as $key) {
437 $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this);
438 }
439 }
440 } // end func setDefaults
441
442 // }}}
443 // {{{ setConstants()
444
445 /**
446 * Initializes constant form values.
447 * These values won't get overridden by POST or GET vars
448 *
e56458a7
PS
449 * @param array $constantValues values used to fill the form
450 * @param mixed $filter (optional) filter(s) to apply to all default values
da6f8763 451 *
452 * @since 2.0
453 * @access public
454 * @return void
455 */
456 function setConstants($constantValues = null, $filter = null)
457 {
458 if (is_array($constantValues)) {
459 if (isset($filter)) {
460 if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) {
461 foreach ($filter as $val) {
462 if (!is_callable($val)) {
66b3302d 463 return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true);
da6f8763 464 } else {
465 $constantValues = $this->_recursiveFilter($val, $constantValues);
466 }
467 }
468 } elseif (!is_callable($filter)) {
66b3302d 469 return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true);
da6f8763 470 } else {
471 $constantValues = $this->_recursiveFilter($filter, $constantValues);
472 }
473 }
474 $this->_constantValues = HTML_QuickForm::arrayMerge($this->_constantValues, $constantValues);
475 foreach (array_keys($this->_elements) as $key) {
476 $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this);
477 }
478 }
479 } // end func setConstants
480
481 // }}}
482 // {{{ setMaxFileSize()
483
484 /**
485 * Sets the value of MAX_FILE_SIZE hidden element
486 *
487 * @param int $bytes Size in bytes
488 * @since 3.0
489 * @access public
490 * @return void
491 */
492 function setMaxFileSize($bytes = 0)
493 {
494 if ($bytes > 0) {
495 $this->_maxFileSize = $bytes;
496 }
497 if (!$this->elementExists('MAX_FILE_SIZE')) {
498 $this->addElement('hidden', 'MAX_FILE_SIZE', $this->_maxFileSize);
499 } else {
500 $el =& $this->getElement('MAX_FILE_SIZE');
501 $el->updateAttributes(array('value' => $this->_maxFileSize));
502 }
503 } // end func setMaxFileSize
504
505 // }}}
506 // {{{ getMaxFileSize()
507
508 /**
509 * Returns the value of MAX_FILE_SIZE hidden element
510 *
511 * @since 3.0
512 * @access public
513 * @return int max file size in bytes
514 */
515 function getMaxFileSize()
516 {
517 return $this->_maxFileSize;
518 } // end func getMaxFileSize
519
520 // }}}
521 // {{{ &createElement()
522
523 /**
524 * Creates a new form element of the given type.
e56458a7
PS
525 *
526 * This method accepts variable number of parameters, their
da6f8763 527 * meaning and count depending on $elementType
528 *
529 * @param string $elementType type of element to add (text, textarea, file...)
530 * @since 1.0
531 * @access public
532 * @return object extended class of HTML_element
533 * @throws HTML_QuickForm_Error
534 */
535 function &createElement($elementType)
536 {
537 $args = func_get_args();
538 $element =& HTML_QuickForm::_loadElement('createElement', $elementType, array_slice($args, 1));
539 return $element;
540 } // end func createElement
541
542 // }}}
543 // {{{ _loadElement()
544
545 /**
546 * Returns a form element of the given type
547 *
548 * @param string $event event to send to newly created element ('createElement' or 'addElement')
549 * @param string $type element type
550 * @param array $args arguments for event
551 * @since 2.0
552 * @access private
553 * @return object a new element
554 * @throws HTML_QuickForm_Error
555 */
556 function &_loadElement($event, $type, $args)
557 {
558 $type = strtolower($type);
559 if (!HTML_QuickForm::isTypeRegistered($type)) {
66b3302d 560 $error = self::raiseError(null, QUICKFORM_UNREGISTERED_ELEMENT, null, E_USER_WARNING, "Element '$type' does not exist in HTML_QuickForm::_loadElement()", 'HTML_QuickForm_Error', true);
da6f8763 561 return $error;
562 }
563 $className = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][1];
564 $includeFile = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][0];
565 include_once($includeFile);
66491cf1 566 $elementObject = new $className(); //Moodle: PHP 5.3 compatibility
da6f8763 567 for ($i = 0; $i < 5; $i++) {
568 if (!isset($args[$i])) {
569 $args[$i] = null;
570 }
571 }
572 $err = $elementObject->onQuickFormEvent($event, $args, $this);
573 if ($err !== true) {
574 return $err;
575 }
576 return $elementObject;
577 } // end func _loadElement
578
579 // }}}
580 // {{{ addElement()
581
582 /**
583 * Adds an element into the form
e56458a7
PS
584 *
585 * If $element is a string representing element type, then this
586 * method accepts variable number of parameters, their meaning
da6f8763 587 * and count depending on $element
588 *
589 * @param mixed $element element object or type of element to add (text, textarea, file...)
590 * @since 1.0
591 * @return object reference to element
592 * @access public
593 * @throws HTML_QuickForm_Error
594 */
595 function &addElement($element)
596 {
597 if (is_object($element) && is_subclass_of($element, 'html_quickform_element')) {
598 $elementObject = &$element;
599 $elementObject->onQuickFormEvent('updateValue', null, $this);
600 } else {
601 $args = func_get_args();
602 $elementObject =& $this->_loadElement('addElement', $element, array_slice($args, 1));
9c390d62
TL
603 $pear = new PEAR();
604 if ($pear->isError($elementObject)) {
da6f8763 605 return $elementObject;
606 }
607 }
608 $elementName = $elementObject->getName();
609
610 // Add the element if it is not an incompatible duplicate
611 if (!empty($elementName) && isset($this->_elementIndex[$elementName])) {
612 if ($this->_elements[$this->_elementIndex[$elementName]]->getType() ==
613 $elementObject->getType()) {
614 $this->_elements[] =& $elementObject;
615 $elKeys = array_keys($this->_elements);
616 $this->_duplicateIndex[$elementName][] = end($elKeys);
617 } else {
66b3302d 618 $error = self::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::addElement()", 'HTML_QuickForm_Error', true);
da6f8763 619 return $error;
620 }
621 } else {
622 $this->_elements[] =& $elementObject;
623 $elKeys = array_keys($this->_elements);
624 $this->_elementIndex[$elementName] = end($elKeys);
625 }
626 if ($this->_freezeAll) {
627 $elementObject->freeze();
628 }
629
630 return $elementObject;
631 } // end func addElement
e56458a7 632
da6f8763 633 // }}}
634 // {{{ insertElementBefore()
635
636 /**
637 * Inserts a new element right before the other element
638 *
639 * Warning: it is not possible to check whether the $element is already
640 * added to the form, therefore if you want to move the existing form
641 * element to a new position, you'll have to use removeElement():
642 * $form->insertElementBefore($form->removeElement('foo', false), 'bar');
643 *
644 * @access public
645 * @since 3.2.4
646 * @param object HTML_QuickForm_element Element to insert
647 * @param string Name of the element before which the new one is inserted
648 * @return object HTML_QuickForm_element reference to inserted element
649 * @throws HTML_QuickForm_Error
650 */
651 function &insertElementBefore(&$element, $nameAfter)
652 {
653 if (!empty($this->_duplicateIndex[$nameAfter])) {
66b3302d 654 $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);
da6f8763 655 return $error;
656 } elseif (!$this->elementExists($nameAfter)) {
66b3302d 657 $error = self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$nameAfter' does not exist in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true);
da6f8763 658 return $error;
659 }
660 $elementName = $element->getName();
661 $targetIdx = $this->_elementIndex[$nameAfter];
662 $duplicate = false;
663 // Like in addElement(), check that it's not an incompatible duplicate
664 if (!empty($elementName) && isset($this->_elementIndex[$elementName])) {
665 if ($this->_elements[$this->_elementIndex[$elementName]]->getType() != $element->getType()) {
66b3302d 666 $error = self::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true);
da6f8763 667 return $error;
668 }
669 $duplicate = true;
670 }
671 // Move all the elements after added back one place, reindex _elementIndex and/or _duplicateIndex
672 $elKeys = array_keys($this->_elements);
673 for ($i = end($elKeys); $i >= $targetIdx; $i--) {
674 if (isset($this->_elements[$i])) {
675 $currentName = $this->_elements[$i]->getName();
676 $this->_elements[$i + 1] =& $this->_elements[$i];
677 if ($this->_elementIndex[$currentName] == $i) {
678 $this->_elementIndex[$currentName] = $i + 1;
679 } else {
9f9c7947
DS
680 if (!empty($currentName)) {
681 $dupIdx = array_search($i, $this->_duplicateIndex[$currentName]);
682 $this->_duplicateIndex[$currentName][$dupIdx] = $i + 1;
683 }
da6f8763 684 }
685 unset($this->_elements[$i]);
686 }
687 }
688 // Put the element in place finally
689 $this->_elements[$targetIdx] =& $element;
690 if (!$duplicate) {
691 $this->_elementIndex[$elementName] = $targetIdx;
692 } else {
693 $this->_duplicateIndex[$elementName][] = $targetIdx;
694 }
695 $element->onQuickFormEvent('updateValue', null, $this);
696 if ($this->_freezeAll) {
697 $element->freeze();
698 }
699 // If not done, the elements will appear in reverse order
700 ksort($this->_elements);
701 return $element;
702 }
703
704 // }}}
705 // {{{ addGroup()
706
707 /**
708 * Adds an element group
709 * @param array $elements array of elements composing the group
710 * @param string $name (optional)group name
711 * @param string $groupLabel (optional)group label
712 * @param string $separator (optional)string to separate elements
713 * @param string $appendName (optional)specify whether the group name should be
714 * used in the form element name ex: group[element]
715 * @return object reference to added group of elements
716 * @since 2.8
717 * @access public
718 * @throws PEAR_Error
719 */
720 function &addGroup($elements, $name=null, $groupLabel='', $separator=null, $appendName = true)
721 {
722 static $anonGroups = 1;
723
724 if (0 == strlen($name)) {
725 $name = 'qf_group_' . $anonGroups++;
726 $appendName = false;
727 }
728 $group =& $this->addElement('group', $name, $groupLabel, $elements, $separator, $appendName);
729 return $group;
730 } // end func addGroup
e56458a7 731
da6f8763 732 // }}}
733 // {{{ &getElement()
734
735 /**
736 * Returns a reference to the element
737 *
738 * @param string $element Element name
739 * @since 2.0
740 * @access public
741 * @return object reference to element
742 * @throws HTML_QuickForm_Error
743 */
744 function &getElement($element)
745 {
746 if (isset($this->_elementIndex[$element])) {
747 return $this->_elements[$this->_elementIndex[$element]];
748 } else {
66b3302d 749 $error = self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElement()", 'HTML_QuickForm_Error', true);
da6f8763 750 return $error;
751 }
752 } // end func getElement
753
754 // }}}
755 // {{{ &getElementValue()
756
757 /**
758 * Returns the element's raw value
e56458a7
PS
759 *
760 * This returns the value as submitted by the form (not filtered)
da6f8763 761 * or set via setDefaults() or setConstants()
762 *
763 * @param string $element Element name
764 * @since 2.0
765 * @access public
766 * @return mixed element value
767 * @throws HTML_QuickForm_Error
768 */
769 function &getElementValue($element)
770 {
771 if (!isset($this->_elementIndex[$element])) {
66b3302d 772 $error = self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElementValue()", 'HTML_QuickForm_Error', true);
da6f8763 773 return $error;
774 }
775 $value = $this->_elements[$this->_elementIndex[$element]]->getValue();
776 if (isset($this->_duplicateIndex[$element])) {
777 foreach ($this->_duplicateIndex[$element] as $index) {
778 if (null !== ($v = $this->_elements[$index]->getValue())) {
779 if (is_array($value)) {
780 $value[] = $v;
781 } else {
782 $value = (null === $value)? $v: array($value, $v);
783 }
784 }
785 }
786 }
787 return $value;
788 } // end func getElementValue
789
790 // }}}
791 // {{{ getSubmitValue()
792
793 /**
794 * Returns the elements value after submit and filter
795 *
796 * @param string Element name
797 * @since 2.0
798 * @access public
799 * @return mixed submitted element value or null if not set
e56458a7 800 */
da6f8763 801 function getSubmitValue($elementName)
802 {
803 $value = null;
804 if (isset($this->_submitValues[$elementName]) || isset($this->_submitFiles[$elementName])) {
805 $value = isset($this->_submitValues[$elementName])? $this->_submitValues[$elementName]: array();
806 if (is_array($value) && isset($this->_submitFiles[$elementName])) {
807 foreach ($this->_submitFiles[$elementName] as $k => $v) {
808 $value = HTML_QuickForm::arrayMerge($value, $this->_reindexFiles($this->_submitFiles[$elementName][$k], $k));
809 }
810 }
811
812 } elseif ('file' == $this->getElementType($elementName)) {
813 return $this->getElementValue($elementName);
814
815 } elseif (false !== ($pos = strpos($elementName, '['))) {
816 $base = substr($elementName, 0, $pos);
817 $idx = "['" . str_replace(array(']', '['), array('', "']['"), substr($elementName, $pos + 1, -1)) . "']";
818 if (isset($this->_submitValues[$base])) {
819 $value = eval("return (isset(\$this->_submitValues['{$base}']{$idx})) ? \$this->_submitValues['{$base}']{$idx} : null;");
820 }
821
822 if ((is_array($value) || null === $value) && isset($this->_submitFiles[$base])) {
823 $props = array('name', 'type', 'size', 'tmp_name', 'error');
824 $code = "if (!isset(\$this->_submitFiles['{$base}']['name']{$idx})) {\n" .
825 " return null;\n" .
826 "} else {\n" .
827 " \$v = array();\n";
828 foreach ($props as $prop) {
829 $code .= " \$v = HTML_QuickForm::arrayMerge(\$v, \$this->_reindexFiles(\$this->_submitFiles['{$base}']['{$prop}']{$idx}, '{$prop}'));\n";
830 }
831 $fileValue = eval($code . " return \$v;\n}\n");
832 if (null !== $fileValue) {
833 $value = null === $value? $fileValue: HTML_QuickForm::arrayMerge($value, $fileValue);
834 }
835 }
836 }
e56458a7 837
da6f8763 838 // This is only supposed to work for groups with appendName = false
839 if (null === $value && 'group' == $this->getElementType($elementName)) {
840 $group =& $this->getElement($elementName);
841 $elements =& $group->getElements();
842 foreach (array_keys($elements) as $key) {
843 $name = $group->getElementName($key);
844 // prevent endless recursion in case of radios and such
845 if ($name != $elementName) {
846 if (null !== ($v = $this->getSubmitValue($name))) {
847 $value[$name] = $v;
848 }
849 }
850 }
851 }
852 return $value;
853 } // end func getSubmitValue
854
855 // }}}
856 // {{{ _reindexFiles()
857
858 /**
859 * A helper function to change the indexes in $_FILES array
860 *
861 * @param mixed Some value from the $_FILES array
862 * @param string The key from the $_FILES array that should be appended
863 * @return array
864 */
865 function _reindexFiles($value, $key)
866 {
867 if (!is_array($value)) {
868 return array($key => $value);
869 } else {
870 $ret = array();
871 foreach ($value as $k => $v) {
872 $ret[$k] = $this->_reindexFiles($v, $key);
873 }
874 return $ret;
875 }
876 }
877
878 // }}}
879 // {{{ getElementError()
880
881 /**
882 * Returns error corresponding to validated element
883 *
884 * @param string $element Name of form element to check
885 * @since 1.0
886 * @access public
887 * @return string error message corresponding to checked element
888 */
889 function getElementError($element)
890 {
891 if (isset($this->_errors[$element])) {
892 return $this->_errors[$element];
893 }
894 } // end func getElementError
e56458a7 895
da6f8763 896 // }}}
897 // {{{ setElementError()
898
899 /**
900 * Set error message for a form element
901 *
902 * @param string $element Name of form element to set error for
903 * @param string $message Error message, if empty then removes the current error message
e56458a7 904 * @since 1.0
da6f8763 905 * @access public
906 * @return void
907 */
908 function setElementError($element, $message = null)
909 {
910 if (!empty($message)) {
911 $this->_errors[$element] = $message;
912 } else {
913 unset($this->_errors[$element]);
914 }
915 } // end func setElementError
e56458a7 916
da6f8763 917 // }}}
918 // {{{ getElementType()
919
920 /**
921 * Returns the type of the given element
922 *
923 * @param string $element Name of form element
924 * @since 1.1
925 * @access public
926 * @return string Type of the element, false if the element is not found
927 */
928 function getElementType($element)
929 {
930 if (isset($this->_elementIndex[$element])) {
931 return $this->_elements[$this->_elementIndex[$element]]->getType();
932 }
933 return false;
934 } // end func getElementType
935
936 // }}}
937 // {{{ updateElementAttr()
938
939 /**
940 * Updates Attributes for one or more elements
941 *
942 * @param mixed $elements Array of element names/objects or string of elements to be updated
943 * @param mixed $attrs Array or sting of html attributes
944 * @since 2.10
945 * @access public
946 * @return void
947 */
948 function updateElementAttr($elements, $attrs)
949 {
950 if (is_string($elements)) {
fcbf4b6f 951 $elements = preg_split('/[ ]?,[ ]?/', $elements);
da6f8763 952 }
953 foreach (array_keys($elements) as $key) {
954 if (is_object($elements[$key]) && is_a($elements[$key], 'HTML_QuickForm_element')) {
955 $elements[$key]->updateAttributes($attrs);
956 } elseif (isset($this->_elementIndex[$elements[$key]])) {
957 $this->_elements[$this->_elementIndex[$elements[$key]]]->updateAttributes($attrs);
958 if (isset($this->_duplicateIndex[$elements[$key]])) {
959 foreach ($this->_duplicateIndex[$elements[$key]] as $index) {
960 $this->_elements[$index]->updateAttributes($attrs);
961 }
962 }
963 }
964 }
965 } // end func updateElementAttr
966
967 // }}}
968 // {{{ removeElement()
969
970 /**
971 * Removes an element
972 *
973 * The method "unlinks" an element from the form, returning the reference
e56458a7 974 * to the element object. If several elements named $elementName exist,
da6f8763 975 * it removes the first one, leaving the others intact.
e56458a7 976 *
da6f8763 977 * @param string $elementName The element name
e56458a7 978 * @param boolean $removeRules True if rules for this element are to be removed too
da6f8763 979 * @access public
980 * @since 2.0
981 * @return object HTML_QuickForm_element a reference to the removed element
982 * @throws HTML_QuickForm_Error
983 */
984 function &removeElement($elementName, $removeRules = true)
985 {
986 if (!isset($this->_elementIndex[$elementName])) {
66b3302d 987 $error = self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$elementName' does not exist in HTML_QuickForm::removeElement()", 'HTML_QuickForm_Error', true);
da6f8763 988 return $error;
989 }
990 $el =& $this->_elements[$this->_elementIndex[$elementName]];
991 unset($this->_elements[$this->_elementIndex[$elementName]]);
992 if (empty($this->_duplicateIndex[$elementName])) {
993 unset($this->_elementIndex[$elementName]);
994 } else {
995 $this->_elementIndex[$elementName] = array_shift($this->_duplicateIndex[$elementName]);
996 }
997 if ($removeRules) {
998 unset($this->_rules[$elementName], $this->_errors[$elementName]);
999 }
1000 return $el;
1001 } // end func removeElement
1002
1003 // }}}
1004 // {{{ addRule()
1005
1006 /**
1007 * Adds a validation rule for the given field
1008 *
1009 * If the element is in fact a group, it will be considered as a whole.
e56458a7 1010 * To validate grouped elements as separated entities,
da6f8763 1011 * use addGroupRule instead of addRule.
1012 *
1013 * @param string $element Form element name
1014 * @param string $message Message to display for invalid data
1015 * @param string $type Rule type, use getRegisteredRules() to get types
1016 * @param string $format (optional)Required for extra rule data
1017 * @param string $validation (optional)Where to perform validation: "server", "client"
1018 * @param boolean $reset Client-side validation: reset the form element to its original value if there is an error?
1019 * @param boolean $force Force the rule to be applied, even if the target form element does not exist
1020 * @since 1.0
1021 * @access public
1022 * @throws HTML_QuickForm_Error
1023 */
1024 function addRule($element, $message, $type, $format=null, $validation='server', $reset = false, $force = false)
1025 {
1026 if (!$force) {
1027 if (!is_array($element) && !$this->elementExists($element)) {
66b3302d 1028 return self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true);
da6f8763 1029 } elseif (is_array($element)) {
1030 foreach ($element as $el) {
1031 if (!$this->elementExists($el)) {
66b3302d 1032 return self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$el' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true);
da6f8763 1033 }
1034 }
1035 }
1036 }
1037 if (false === ($newName = $this->isRuleRegistered($type, true))) {
66b3302d 1038 return self::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true);
da6f8763 1039 } elseif (is_string($newName)) {
1040 $type = $newName;
1041 }
1042 if (is_array($element)) {
1043 $dependent = $element;
1044 $element = array_shift($dependent);
1045 } else {
1046 $dependent = null;
1047 }
1048 if ($type == 'required' || $type == 'uploadedfile') {
1049 $this->_required[] = $element;
1050 }
1051 if (!isset($this->_rules[$element])) {
1052 $this->_rules[$element] = array();
1053 }
1054 if ($validation == 'client') {
1055 $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);'));
1056 }
1057 $this->_rules[$element][] = array(
1058 'type' => $type,
1059 'format' => $format,
1060 'message' => $message,
1061 'validation' => $validation,
1062 'reset' => $reset,
1063 'dependent' => $dependent
1064 );
1065 } // end func addRule
1066
1067 // }}}
1068 // {{{ addGroupRule()
1069
1070 /**
1071 * Adds a validation rule for the given group of elements
1072 *
1073 * Only groups with a name can be assigned a validation rule
1074 * Use addGroupRule when you need to validate elements inside the group.
1075 * Use addRule if you need to validate the group as a whole. In this case,
1076 * the same rule will be applied to all elements in the group.
1077 * Use addRule if you need to validate the group against a function.
1078 *
1079 * @param string $group Form group name
1080 * @param mixed $arg1 Array for multiple elements or error message string for one element
1081 * @param string $type (optional)Rule type use getRegisteredRules() to get types
1082 * @param string $format (optional)Required for extra rule data
1083 * @param int $howmany (optional)How many valid elements should be in the group
1084 * @param string $validation (optional)Where to perform validation: "server", "client"
1085 * @param bool $reset Client-side: whether to reset the element's value to its original state if validation failed.
1086 * @since 2.5
1087 * @access public
1088 * @throws HTML_QuickForm_Error
1089 */
1090 function addGroupRule($group, $arg1, $type='', $format=null, $howmany=0, $validation = 'server', $reset = false)
1091 {
1092 if (!$this->elementExists($group)) {
66b3302d 1093 return self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Group '$group' does not exist in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true);
da6f8763 1094 }
1095
1096 $groupObj =& $this->getElement($group);
1097 if (is_array($arg1)) {
1098 $required = 0;
1099 foreach ($arg1 as $elementIndex => $rules) {
1100 $elementName = $groupObj->getElementName($elementIndex);
1101 foreach ($rules as $rule) {
1102 $format = (isset($rule[2])) ? $rule[2] : null;
1103 $validation = (isset($rule[3]) && 'client' == $rule[3])? 'client': 'server';
1104 $reset = isset($rule[4]) && $rule[4];
1105 $type = $rule[1];
1106 if (false === ($newName = $this->isRuleRegistered($type, true))) {
66b3302d 1107 return self::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true);
da6f8763 1108 } elseif (is_string($newName)) {
1109 $type = $newName;
1110 }
1111
1112 $this->_rules[$elementName][] = array(
1113 'type' => $type,
e56458a7 1114 'format' => $format,
da6f8763 1115 'message' => $rule[0],
1116 'validation' => $validation,
1117 'reset' => $reset,
1118 'group' => $group);
1119
1120 if ('required' == $type || 'uploadedfile' == $type) {
1121 $groupObj->_required[] = $elementName;
1122 $this->_required[] = $elementName;
1123 $required++;
1124 }
1125 if ('client' == $validation) {
1126 $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);'));
1127 }
1128 }
1129 }
1130 if ($required > 0 && count($groupObj->getElements()) == $required) {
1131 $this->_required[] = $group;
1132 }
1133 } elseif (is_string($arg1)) {
1134 if (false === ($newName = $this->isRuleRegistered($type, true))) {
66b3302d 1135 return self::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true);
da6f8763 1136 } elseif (is_string($newName)) {
1137 $type = $newName;
1138 }
1139
1140 // addGroupRule() should also handle <select multiple>
1141 if (is_a($groupObj, 'html_quickform_group')) {
1142 // Radios need to be handled differently when required
1143 if ($type == 'required' && $groupObj->getGroupType() == 'radio') {
1144 $howmany = ($howmany == 0) ? 1 : $howmany;
1145 } else {
1146 $howmany = ($howmany == 0) ? count($groupObj->getElements()) : $howmany;
1147 }
1148 }
1149
1150 $this->_rules[$group][] = array('type' => $type,
e56458a7 1151 'format' => $format,
da6f8763 1152 'message' => $arg1,
1153 'validation' => $validation,
1154 'howmany' => $howmany,
1155 'reset' => $reset);
1156 if ($type == 'required') {
1157 $this->_required[] = $group;
1158 }
1159 if ($validation == 'client') {
1160 $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);'));
1161 }
1162 }
1163 } // end func addGroupRule
1164
1165 // }}}
1166 // {{{ addFormRule()
1167
1168 /**
e56458a7
PS
1169 * Adds a global validation rule
1170 *
da6f8763 1171 * This should be used when for a rule involving several fields or if
1172 * you want to use some completely custom validation for your form.
e56458a7 1173 * The rule function/method should return true in case of successful
da6f8763 1174 * validation and array('element name' => 'error') when there were errors.
e56458a7 1175 *
da6f8763 1176 * @access public
1177 * @param mixed Callback, either function name or array(&$object, 'method')
1178 * @throws HTML_QuickForm_Error
1179 */
1180 function addFormRule($rule)
1181 {
1182 if (!is_callable($rule)) {
66b3302d 1183 return self::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, 'Callback function does not exist in HTML_QuickForm::addFormRule()', 'HTML_QuickForm_Error', true);
da6f8763 1184 }
1185 $this->_formRules[] = $rule;
1186 }
e56458a7 1187
da6f8763 1188 // }}}
1189 // {{{ applyFilter()
1190
1191 /**
1192 * Applies a data filter for the given field(s)
1193 *
1194 * @param mixed $element Form element name or array of such names
1195 * @param mixed $filter Callback, either function name or array(&$object, 'method')
1196 * @since 2.0
1197 * @access public
1198 */
1199 function applyFilter($element, $filter)
1200 {
1201 if (!is_callable($filter)) {
66b3302d 1202 return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::applyFilter()", 'HTML_QuickForm_Error', true);
da6f8763 1203 }
1204 if ($element == '__ALL__') {
1205 $this->_submitValues = $this->_recursiveFilter($filter, $this->_submitValues);
1206 } else {
1207 if (!is_array($element)) {
1208 $element = array($element);
1209 }
1210 foreach ($element as $elName) {
1211 $value = $this->getSubmitValue($elName);
1212 if (null !== $value) {
1213 if (false === strpos($elName, '[')) {
1214 $this->_submitValues[$elName] = $this->_recursiveFilter($filter, $value);
1215 } else {
1216 $idx = "['" . str_replace(array(']', '['), array('', "']['"), $elName) . "']";
1217 eval("\$this->_submitValues{$idx} = \$this->_recursiveFilter(\$filter, \$value);");
1218 }
1219 }
1220 }
1221 }
1222 } // end func applyFilter
1223
1224 // }}}
1225 // {{{ _recursiveFilter()
1226
1227 /**
1228 * Recursively apply a filter function
1229 *
1230 * @param string $filter filter to apply
1231 * @param mixed $value submitted values
1232 * @since 2.0
1233 * @access private
1234 * @return cleaned values
1235 */
1236 function _recursiveFilter($filter, $value)
1237 {
1238 if (is_array($value)) {
1239 $cleanValues = array();
1240 foreach ($value as $k => $v) {
1241 $cleanValues[$k] = $this->_recursiveFilter($filter, $v);
1242 }
1243 return $cleanValues;
1244 } else {
1245 return call_user_func($filter, $value);
1246 }
1247 } // end func _recursiveFilter
1248
1249 // }}}
1250 // {{{ arrayMerge()
1251
1252 /**
1253 * Merges two arrays
1254 *
1255 * Merges two array like the PHP function array_merge but recursively.
1256 * The main difference is that existing keys will not be renumbered
1257 * if they are integers.
1258 *
1259 * @access puplic
1260 * @param array $a original array
1261 * @param array $b array which will be merged into first one
1262 * @return array merged array
1263 */
fabbf439 1264 static function arrayMerge($a, $b)
da6f8763 1265 {
fabbf439
PS
1266 if (is_null($a)) {$a = array();}
1267 if (is_null($b)) {$b = array();}
da6f8763 1268 foreach ($b as $k => $v) {
1269 if (is_array($v)) {
1270 if (isset($a[$k]) && !is_array($a[$k])) {
1271 $a[$k] = $v;
1272 } else {
1273 if (!isset($a[$k])) {
1274 $a[$k] = array();
1275 }
1276 $a[$k] = HTML_QuickForm::arrayMerge($a[$k], $v);
1277 }
1278 } else {
1279 $a[$k] = $v;
1280 }
1281 }
1282 return $a;
1283 } // end func arrayMerge
1284
1285 // }}}
1286 // {{{ isTypeRegistered()
1287
1288 /**
1289 * Returns whether or not the form element type is supported
1290 *
1291 * @param string $type Form element type
1292 * @since 1.0
1293 * @access public
1294 * @return boolean
1295 */
1296 function isTypeRegistered($type)
1297 {
1298 return isset($GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($type)]);
1299 } // end func isTypeRegistered
1300
1301 // }}}
1302 // {{{ getRegisteredTypes()
1303
1304 /**
1305 * Returns an array of registered element types
1306 *
1307 * @since 1.0
1308 * @access public
1309 * @return array
1310 */
1311 function getRegisteredTypes()
1312 {
1313 return array_keys($GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES']);
1314 } // end func getRegisteredTypes
1315
1316 // }}}
1317 // {{{ isRuleRegistered()
1318
1319 /**
1320 * Returns whether or not the given rule is supported
1321 *
1322 * @param string $name Validation rule name
1323 * @param bool Whether to automatically register subclasses of HTML_QuickForm_Rule
1324 * @since 1.0
1325 * @access public
1326 * @return mixed true if previously registered, false if not, new rule name if auto-registering worked
1327 */
1328 function isRuleRegistered($name, $autoRegister = false)
1329 {
1330 if (is_scalar($name) && isset($GLOBALS['_HTML_QuickForm_registered_rules'][$name])) {
1331 return true;
1332 } elseif (!$autoRegister) {
1333 return false;
1334 }
1335 // automatically register the rule if requested
1336 include_once 'HTML/QuickForm/RuleRegistry.php';
1337 $ruleName = false;
1338 if (is_object($name) && is_a($name, 'html_quickform_rule')) {
1339 $ruleName = !empty($name->name)? $name->name: strtolower(get_class($name));
1340 } elseif (is_string($name) && class_exists($name)) {
1341 $parent = strtolower($name);
1342 do {
1343 if ('html_quickform_rule' == strtolower($parent)) {
1344 $ruleName = strtolower($name);
1345 break;
1346 }
1347 } while ($parent = get_parent_class($parent));
1348 }
1349 if ($ruleName) {
1350 $registry =& HTML_QuickForm_RuleRegistry::singleton();
1351 $registry->registerRule($ruleName, null, $name);
1352 }
1353 return $ruleName;
1354 } // end func isRuleRegistered
1355
1356 // }}}
1357 // {{{ getRegisteredRules()
1358
1359 /**
1360 * Returns an array of registered validation rules
1361 *
1362 * @since 1.0
1363 * @access public
1364 * @return array
1365 */
1366 function getRegisteredRules()
1367 {
1368 return array_keys($GLOBALS['_HTML_QuickForm_registered_rules']);
1369 } // end func getRegisteredRules
1370
1371 // }}}
1372 // {{{ isElementRequired()
1373
1374 /**
1375 * Returns whether or not the form element is required
1376 *
1377 * @param string $element Form element name
1378 * @since 1.0
1379 * @access public
1380 * @return boolean
1381 */
1382 function isElementRequired($element)
1383 {
1384 return in_array($element, $this->_required, true);
1385 } // end func isElementRequired
1386
1387 // }}}
1388 // {{{ isElementFrozen()
1389
1390 /**
1391 * Returns whether or not the form element is frozen
1392 *
1393 * @param string $element Form element name
1394 * @since 1.0
1395 * @access public
1396 * @return boolean
1397 */
1398 function isElementFrozen($element)
1399 {
1400 if (isset($this->_elementIndex[$element])) {
1401 return $this->_elements[$this->_elementIndex[$element]]->isFrozen();
1402 }
1403 return false;
1404 } // end func isElementFrozen
1405
1406 // }}}
1407 // {{{ setJsWarnings()
1408
1409 /**
1410 * Sets JavaScript warning messages
1411 *
1412 * @param string $pref Prefix warning
1413 * @param string $post Postfix warning
1414 * @since 1.1
1415 * @access public
1416 * @return void
1417 */
1418 function setJsWarnings($pref, $post)
1419 {
1420 $this->_jsPrefix = $pref;
1421 $this->_jsPostfix = $post;
1422 } // end func setJsWarnings
e56458a7 1423
da6f8763 1424 // }}}
1425 // {{{ setRequiredNote()
1426
1427 /**
1428 * Sets required-note
1429 *
1430 * @param string $note Message indicating some elements are required
1431 * @since 1.1
1432 * @access public
1433 * @return void
1434 */
1435 function setRequiredNote($note)
1436 {
1437 $this->_requiredNote = $note;
1438 } // end func setRequiredNote
1439
1440 // }}}
1441 // {{{ getRequiredNote()
1442
1443 /**
1444 * Returns the required note
1445 *
1446 * @since 2.0
1447 * @access public
1448 * @return string
1449 */
1450 function getRequiredNote()
1451 {
1452 return $this->_requiredNote;
1453 } // end func getRequiredNote
1454
1455 // }}}
1456 // {{{ validate()
1457
1458 /**
1459 * Performs the server side validation
1460 * @access public
1461 * @since 1.0
1462 * @return boolean true if no error found
1463 */
1464 function validate()
1465 {
e56458a7 1466 if (count($this->_rules) == 0 && count($this->_formRules) == 0 &&
da6f8763 1467 $this->isSubmitted()) {
1468 return (0 == count($this->_errors));
1469 } elseif (!$this->isSubmitted()) {
1470 return false;
1471 }
1472
1473 include_once('HTML/QuickForm/RuleRegistry.php');
1474 $registry =& HTML_QuickForm_RuleRegistry::singleton();
1475
1476 foreach ($this->_rules as $target => $rules) {
1477 $submitValue = $this->getSubmitValue($target);
1478
1479 foreach ($rules as $rule) {
1480 if ((isset($rule['group']) && isset($this->_errors[$rule['group']])) ||
1481 isset($this->_errors[$target])) {
1482 continue 2;
1483 }
1484 // If element is not required and is empty, we shouldn't validate it
1485 if (!$this->isElementRequired($target)) {
1486 if (!isset($submitValue) || '' == $submitValue) {
1487 continue 2;
1488 // Fix for bug #3501: we shouldn't validate not uploaded files, either.
1489 // Unfortunately, we can't just use $element->isUploadedFile() since
1490 // the element in question can be buried in group. Thus this hack.
1491 } elseif (is_array($submitValue)) {
1492 if (false === ($pos = strpos($target, '['))) {
1493 $isUpload = !empty($this->_submitFiles[$target]);
1494 } else {
1495 $base = substr($target, 0, $pos);
1496 $idx = "['" . str_replace(array(']', '['), array('', "']['"), substr($target, $pos + 1, -1)) . "']";
1497 eval("\$isUpload = isset(\$this->_submitFiles['{$base}']['name']{$idx});");
1498 }
1499 if ($isUpload && (!isset($submitValue['error']) || 0 != $submitValue['error'])) {
1500 continue 2;
1501 }
1502 }
1503 }
1504 if (isset($rule['dependent']) && is_array($rule['dependent'])) {
1505 $values = array($submitValue);
1506 foreach ($rule['dependent'] as $elName) {
1507 $values[] = $this->getSubmitValue($elName);
1508 }
1509 $result = $registry->validate($rule['type'], $values, $rule['format'], true);
1510 } elseif (is_array($submitValue) && !isset($rule['howmany'])) {
1511 $result = $registry->validate($rule['type'], $submitValue, $rule['format'], true);
1512 } else {
1513 $result = $registry->validate($rule['type'], $submitValue, $rule['format'], false);
1514 }
1515
1516 if (!$result || (!empty($rule['howmany']) && $rule['howmany'] > (int)$result)) {
1517 if (isset($rule['group'])) {
1518 $this->_errors[$rule['group']] = $rule['message'];
1519 } else {
1520 $this->_errors[$target] = $rule['message'];
1521 }
1522 }
1523 }
1524 }
1525
1526 // process the global rules now
1527 foreach ($this->_formRules as $rule) {
1528 if (true !== ($res = call_user_func($rule, $this->_submitValues, $this->_submitFiles))) {
1529 if (is_array($res)) {
1530 $this->_errors += $res;
1531 } else {
66b3302d 1532 return self::raiseError(null, QUICKFORM_ERROR, null, E_USER_WARNING, 'Form rule callback returned invalid value in HTML_QuickForm::validate()', 'HTML_QuickForm_Error', true);
da6f8763 1533 }
1534 }
1535 }
1536
1537 return (0 == count($this->_errors));
1538 } // end func validate
1539
1540 // }}}
1541 // {{{ freeze()
1542
1543 /**
1544 * Displays elements without HTML input tags
1545 *
1546 * @param mixed $elementList array or string of element(s) to be frozen
1547 * @since 1.0
1548 * @access public
1549 * @throws HTML_QuickForm_Error
1550 */
1551 function freeze($elementList=null)
1552 {
1553 if (!isset($elementList)) {
1554 $this->_freezeAll = true;
1555 $elementList = array();
1556 } else {
1557 if (!is_array($elementList)) {
1558 $elementList = preg_split('/[ ]*,[ ]*/', $elementList);
1559 }
1560 $elementList = array_flip($elementList);
1561 }
1562
1563 foreach (array_keys($this->_elements) as $key) {
1564 $name = $this->_elements[$key]->getName();
1565 if ($this->_freezeAll || isset($elementList[$name])) {
1566 $this->_elements[$key]->freeze();
1567 unset($elementList[$name]);
1568 }
1569 }
1570
1571 if (!empty($elementList)) {
66b3302d 1572 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);
da6f8763 1573 }
1574 return true;
1575 } // end func freeze
e56458a7 1576
da6f8763 1577 // }}}
1578 // {{{ isFrozen()
1579
1580 /**
1581 * Returns whether or not the whole form is frozen
1582 *
1583 * @since 3.0
1584 * @access public
1585 * @return boolean
1586 */
1587 function isFrozen()
1588 {
1589 return $this->_freezeAll;
1590 } // end func isFrozen
1591
1592 // }}}
1593 // {{{ process()
1594
1595 /**
1596 * Performs the form data processing
1597 *
1598 * @param mixed $callback Callback, either function name or array(&$object, 'method')
1599 * @param bool $mergeFiles Whether uploaded files should be processed too
1600 * @since 1.0
1601 * @access public
1602 * @throws HTML_QuickForm_Error
1603 */
1604 function process($callback, $mergeFiles = true)
1605 {
1606 if (!is_callable($callback)) {
66b3302d 1607 return self::raiseError(null, QUICKFORM_INVALID_PROCESS, null, E_USER_WARNING, "Callback function does not exist in QuickForm::process()", 'HTML_QuickForm_Error', true);
da6f8763 1608 }
1609 $values = ($mergeFiles === true) ? HTML_QuickForm::arrayMerge($this->_submitValues, $this->_submitFiles) : $this->_submitValues;
1610 return call_user_func($callback, $values);
1611 } // end func process
1612
1613 // }}}
1614 // {{{ accept()
1615
1616 /**
1617 * Accepts a renderer
1618 *
1619 * @param object An HTML_QuickForm_Renderer object
1620 * @since 3.0
1621 * @access public
1622 * @return void
1623 */
1624 function accept(&$renderer)
1625 {
1626 $renderer->startForm($this);
1627 foreach (array_keys($this->_elements) as $key) {
1628 $element =& $this->_elements[$key];
1629 $elementName = $element->getName();
1630 $required = ($this->isElementRequired($elementName) && !$element->isFrozen());
1631 $error = $this->getElementError($elementName);
1632 $element->accept($renderer, $required, $error);
1633 }
1634 $renderer->finishForm($this);
1635 } // end func accept
1636
1637 // }}}
1638 // {{{ defaultRenderer()
1639
1640 /**
1641 * Returns a reference to default renderer object
1642 *
1643 * @access public
1644 * @since 3.0
1645 * @return object a default renderer object
1646 */
1647 function &defaultRenderer()
1648 {
1649 if (!isset($GLOBALS['_HTML_QuickForm_default_renderer'])) {
1650 include_once('HTML/QuickForm/Renderer/Default.php');
66491cf1 1651 $GLOBALS['_HTML_QuickForm_default_renderer'] = new HTML_QuickForm_Renderer_Default(); //Moodle: PHP 5.3 compatibility
da6f8763 1652 }
1653 return $GLOBALS['_HTML_QuickForm_default_renderer'];
1654 } // end func defaultRenderer
1655
1656 // }}}
1657 // {{{ toHtml ()
1658
1659 /**
1660 * Returns an HTML version of the form
1661 *
1662 * @param string $in_data (optional) Any extra data to insert right
1663 * before form is rendered. Useful when using templates.
1664 *
1665 * @return string Html version of the form
1666 * @since 1.0
1667 * @access public
1668 */
1669 function toHtml ($in_data = null)
1670 {
1671 if (!is_null($in_data)) {
1672 $this->addElement('html', $in_data);
1673 }
1674 $renderer =& $this->defaultRenderer();
1675 $this->accept($renderer);
1676 return $renderer->toHtml();
1677 } // end func toHtml
1678
1679 // }}}
1680 // {{{ getValidationScript()
1681
1682 /**
1683 * Returns the client side validation script
1684 *
1685 * @since 2.0
1686 * @access public
1687 * @return string Javascript to perform validation, empty string if no 'client' rules were added
1688 */
1689 function getValidationScript()
1690 {
1691 if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) {
1692 return '';
1693 }
1694
1695 include_once('HTML/QuickForm/RuleRegistry.php');
1696 $registry =& HTML_QuickForm_RuleRegistry::singleton();
1697 $test = array();
1698 $js_escape = array(
1699 "\r" => '\r',
1700 "\n" => '\n',
1701 "\t" => '\t',
1702 "'" => "\\'",
1703 '"' => '\"',
1704 '\\' => '\\\\'
1705 );
1706
1707 foreach ($this->_rules as $elementName => $rules) {
1708 foreach ($rules as $rule) {
1709 if ('client' == $rule['validation']) {
1710 unset($element);
1711
1712 $dependent = isset($rule['dependent']) && is_array($rule['dependent']);
1713 $rule['message'] = strtr($rule['message'], $js_escape);
1714
1715 if (isset($rule['group'])) {
1716 $group =& $this->getElement($rule['group']);
1717 // No JavaScript validation for frozen elements
1718 if ($group->isFrozen()) {
1719 continue 2;
1720 }
1721 $elements =& $group->getElements();
1722 foreach (array_keys($elements) as $key) {
1723 if ($elementName == $group->getElementName($key)) {
1724 $element =& $elements[$key];
1725 break;
1726 }
1727 }
1728 } elseif ($dependent) {
1729 $element = array();
1730 $element[] =& $this->getElement($elementName);
1731 foreach ($rule['dependent'] as $elName) {
1732 $element[] =& $this->getElement($elName);
1733 }
1734 } else {
1735 $element =& $this->getElement($elementName);
1736 }
1737 // No JavaScript validation for frozen elements
1738 if (is_object($element) && $element->isFrozen()) {
1739 continue 2;
1740 } elseif (is_array($element)) {
1741 foreach (array_keys($element) as $key) {
1742 if ($element[$key]->isFrozen()) {
1743 continue 3;
1744 }
1745 }
1746 }
1747
1748 $test[] = $registry->getValidationScript($element, $elementName, $rule);
1749 }
1750 }
1751 }
1752 if (count($test) > 0) {
1753 return
1754 "\n<script type=\"text/javascript\">\n" .
e56458a7 1755 "//<![CDATA[\n" .
da6f8763 1756 "function validate_" . $this->_attributes['id'] . "(frm) {\n" .
1757 " var value = '';\n" .
1758 " var errFlag = new Array();\n" .
1759 " var _qfGroups = {};\n" .
1760 " _qfMsg = '';\n\n" .
1761 join("\n", $test) .
1762 "\n if (_qfMsg != '') {\n" .
1763 " _qfMsg = '" . strtr($this->_jsPrefix, $js_escape) . "' + _qfMsg;\n" .
1764 " _qfMsg = _qfMsg + '\\n" . strtr($this->_jsPostfix, $js_escape) . "';\n" .
1765 " alert(_qfMsg);\n" .
1766 " return false;\n" .
1767 " }\n" .
1768 " return true;\n" .
1769 "}\n" .
1770 "//]]>\n" .
1771 "</script>";
1772 }
1773 return '';
1774 } // end func getValidationScript
1775
1776 // }}}
1777 // {{{ getSubmitValues()
1778
1779 /**
1780 * Returns the values submitted by the form
1781 *
1782 * @since 2.0
1783 * @access public
1784 * @param bool Whether uploaded files should be returned too
1785 * @return array
1786 */
1787 function getSubmitValues($mergeFiles = false)
1788 {
1789 return $mergeFiles? HTML_QuickForm::arrayMerge($this->_submitValues, $this->_submitFiles): $this->_submitValues;
1790 } // end func getSubmitValues
1791
1792 // }}}
1793 // {{{ toArray()
1794
1795 /**
1796 * Returns the form's contents in an array.
1797 *
1798 * The description of the array structure is in HTML_QuickForm_Renderer_Array docs
e56458a7 1799 *
da6f8763 1800 * @since 2.0
1801 * @access public
1802 * @param bool Whether to collect hidden elements (passed to the Renderer's constructor)
1803 * @return array of form contents
1804 */
1805 function toArray($collectHidden = false)
1806 {
1807 include_once 'HTML/QuickForm/Renderer/Array.php';
66491cf1 1808 $renderer = new HTML_QuickForm_Renderer_Array($collectHidden); //Moodle: PHP 5.3 compatibility
da6f8763 1809 $this->accept($renderer);
1810 return $renderer->toArray();
1811 } // end func toArray
1812
1813 // }}}
1814 // {{{ exportValue()
1815
1816 /**
1817 * Returns a 'safe' element's value
e56458a7 1818 *
da6f8763 1819 * This method first tries to find a cleaned-up submitted value,
1820 * it will return a value set by setValue()/setDefaults()/setConstants()
1821 * if submitted value does not exist for the given element.
1822 *
1823 * @param string Name of an element
1824 * @access public
1825 * @return mixed
1826 */
1827 function exportValue($element)
1828 {
1829 if (!isset($this->_elementIndex[$element])) {
66b3302d 1830 return self::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElementValue()", 'HTML_QuickForm_Error', true);
da6f8763 1831 }
1832 $value = $this->_elements[$this->_elementIndex[$element]]->exportValue($this->_submitValues, false);
1833 if (isset($this->_duplicateIndex[$element])) {
1834 foreach ($this->_duplicateIndex[$element] as $index) {
1835 if (null !== ($v = $this->_elements[$index]->exportValue($this->_submitValues, false))) {
1836 if (is_array($value)) {
1837 $value[] = $v;
1838 } else {
1839 $value = (null === $value)? $v: array($value, $v);
1840 }
1841 }
1842 }
1843 }
1844 return $value;
1845 }
1846
1847 // }}}
1848 // {{{ exportValues()
1849
1850 /**
1851 * Returns 'safe' elements' values
1852 *
e56458a7 1853 * Unlike getSubmitValues(), this will return only the values
da6f8763 1854 * corresponding to the elements present in the form.
e56458a7 1855 *
da6f8763 1856 * @param mixed Array/string of element names, whose values we want. If not set then return all elements.
1857 * @access public
1858 * @return array An assoc array of elements' values
1859 * @throws HTML_QuickForm_Error
1860 */
1861 function exportValues($elementList = null)
1862 {
1863 $values = array();
1864 if (null === $elementList) {
1865 // iterate over all elements, calling their exportValue() methods
1866 foreach (array_keys($this->_elements) as $key) {
1867 $value = $this->_elements[$key]->exportValue($this->_submitValues, true);
1868 if (is_array($value)) {
1869 // This shit throws a bogus warning in PHP 4.3.x
1870 $values = HTML_QuickForm::arrayMerge($values, $value);
1871 }
1872 }
1873 } else {
1874 if (!is_array($elementList)) {
1875 $elementList = array_map('trim', explode(',', $elementList));
1876 }
1877 foreach ($elementList as $elementName) {
1878 $value = $this->exportValue($elementName);
9c390d62
TL
1879 $pear = new PEAR();
1880 if ($pear->isError($value)) {
da6f8763 1881 return $value;
1882 }
1883 $values[$elementName] = $value;
1884 }
1885 }
1886 return $values;
1887 }
1888
1889 // }}}
1890 // {{{ isSubmitted()
1891
1892 /**
1893 * Tells whether the form was already submitted
1894 *
1895 * This is useful since the _submitFiles and _submitValues arrays
1896 * may be completely empty after the trackSubmit value is removed.
1897 *
1898 * @access public
1899 * @return bool
1900 */
1901 function isSubmitted()
1902 {
1903 return $this->_flagSubmitted;
1904 }
1905
1906
1907 // }}}
1908 // {{{ isError()
1909
1910 /**
1911 * Tell whether a result from a QuickForm method is an error (an instance of HTML_QuickForm_Error)
1912 *
1913 * @access public
1914 * @param mixed result code
1915 * @return bool whether $value is an error
1916 */
66b3302d 1917 static function isError($value)
da6f8763 1918 {
1919 return (is_object($value) && is_a($value, 'html_quickform_error'));
1920 } // end func isError
1921
1922 // }}}
1923 // {{{ errorMessage()
1924
1925 /**
1926 * Return a textual error message for an QuickForm error code
1927 *
1928 * @access public
1929 * @param int error code
1930 * @return string error message
1931 */
66b3302d 1932 static function errorMessage($value)
da6f8763 1933 {
1934 // make the variable static so that it only has to do the defining on the first call
1935 static $errorMessages;
1936
1937 // define the varies error messages
1938 if (!isset($errorMessages)) {
1939 $errorMessages = array(
1940 QUICKFORM_OK => 'no error',
1941 QUICKFORM_ERROR => 'unknown error',
1942 QUICKFORM_INVALID_RULE => 'the rule does not exist as a registered rule',
1943 QUICKFORM_NONEXIST_ELEMENT => 'nonexistent html element',
1944 QUICKFORM_INVALID_FILTER => 'invalid filter',
1945 QUICKFORM_UNREGISTERED_ELEMENT => 'unregistered element',
1946 QUICKFORM_INVALID_ELEMENT_NAME => 'element already exists',
1947 QUICKFORM_INVALID_PROCESS => 'process callback does not exist',
1948 QUICKFORM_DEPRECATED => 'method is deprecated',
1949 QUICKFORM_INVALID_DATASOURCE => 'datasource is not an object'
1950 );
1951 }
1952
1953 // If this is an error object, then grab the corresponding error code
1954 if (HTML_QuickForm::isError($value)) {
1955 $value = $value->getCode();
1956 }
1957
1958 // return the textual error message corresponding to the code
1959 return isset($errorMessages[$value]) ? $errorMessages[$value] : $errorMessages[QUICKFORM_ERROR];
1960 } // end func errorMessage
1961
1962 // }}}
1963} // end class HTML_QuickForm
1964
1965class HTML_QuickForm_Error extends PEAR_Error {
1966
1967 // {{{ properties
1968
1969 /**
1970 * Prefix for all error messages
1971 * @var string
1972 */
1973 var $error_message_prefix = 'QuickForm Error: ';
1974
1975 // }}}
1976 // {{{ constructor
1977
1978 /**
1979 * Creates a quickform error object, extending the PEAR_Error class
1980 *
1981 * @param int $code the error code
1982 * @param int $mode the reaction to the error, either return, die or trigger/callback
1983 * @param int $level intensity of the error (PHP error code)
1984 * @param mixed $debuginfo any information that can inform user as to nature of the error
1985 */
1986 function HTML_QuickForm_Error($code = QUICKFORM_ERROR, $mode = PEAR_ERROR_RETURN,
1987 $level = E_USER_NOTICE, $debuginfo = null)
1988 {
1989 if (is_int($code)) {
1990 $this->PEAR_Error(HTML_QuickForm::errorMessage($code), $code, $mode, $level, $debuginfo);
1991 } else {
1992 $this->PEAR_Error("Invalid error code: $code", QUICKFORM_ERROR, $mode, $level, $debuginfo);
1993 }
1994 }
1995
1996 // }}}
1997} // end class HTML_QuickForm_Error
fcbf4b6f 1998?>