[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/pear/HTML/ -> QuickForm.php (source)

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1