[ Index ]

PHP Cross Reference of moodle-2.8

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  // | [email protected] so we can mail you a copy immediately.               |
  15  // +----------------------------------------------------------------------+
  16  // | Authors: Adam Daniel <[email protected]>                        |
  17  // |          Bertrand Mansion <[email protected]>                     |
  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 <[email protected]>
  93  * @author      Bertrand Mansion <[email protected]>
  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      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()) {
 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      // {{{ 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       */
 332      static function registerElementType($typeName, $include, $className)
 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       */
 351      static function registerRule($ruleName, $type, $data1, $data2 = null)
 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 {
 401              return self::raiseError(null, QUICKFORM_INVALID_DATASOURCE, null, E_USER_WARNING, "Datasource is not an object in QuickForm::setDatasource()", 'HTML_QuickForm_Error', true);
 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)) {
 424                              return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true);
 425                          } else {
 426                              $defaultValues = $this->_recursiveFilter($val, $defaultValues);
 427                          }
 428                      }
 429                  } elseif (!is_callable($filter)) {
 430                      return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true);
 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       *
 449       * @param     array   $constantValues        values used to fill the form
 450       * @param     mixed    $filter              (optional) filter(s) to apply to all default values
 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)) {
 463                              return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true);
 464                          } else {
 465                              $constantValues = $this->_recursiveFilter($val, $constantValues);
 466                          }
 467                      }
 468                  } elseif (!is_callable($filter)) {
 469                      return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true);
 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.
 525       *
 526       * This method accepts variable number of parameters, their
 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)) {
 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);
 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);
 566          $elementObject = new $className(); //Moodle: PHP 5.3 compatibility
 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
 584       *
 585       * If $element is a string representing element type, then this
 586       * method accepts variable number of parameters, their meaning
 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));
 603              $pear = new PEAR();
 604              if ($pear->isError($elementObject)) {
 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 {
 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);
 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
 632  
 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])) {
 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);
 655              return $error;
 656          } elseif (!$this->elementExists($nameAfter)) {
 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);
 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()) {
 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);
 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 {
 680                      if (!empty($currentName)) {
 681                          $dupIdx = array_search($i, $this->_duplicateIndex[$currentName]);
 682                          $this->_duplicateIndex[$currentName][$dupIdx] = $i + 1;
 683                      }
 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
 731  
 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 {
 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);
 750              return $error;
 751          }
 752      } // end func getElement
 753  
 754      // }}}
 755      // {{{ &getElementValue()
 756  
 757      /**
 758       * Returns the element's raw value
 759       *
 760       * This returns the value as submitted by the form (not filtered)
 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])) {
 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);
 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
 800       */
 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          }
 837  
 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
 895  
 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
 904       * @since     1.0
 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
 916  
 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)) {
 951              $elements = preg_split('/[ ]?,[ ]?/', $elements);
 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
 974       * to the element object. If several elements named $elementName exist,
 975       * it removes the first one, leaving the others intact.
 976       *
 977       * @param string    $elementName The element name
 978       * @param boolean   $removeRules True if rules for this element are to be removed too
 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])) {
 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);
 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.
1010       * To validate grouped elements as separated entities,
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)) {
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);
1029              } elseif (is_array($element)) {
1030                  foreach ($element as $el) {
1031                      if (!$this->elementExists($el)) {
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);
1033                      }
1034                  }
1035              }
1036          }
1037          if (false === ($newName = $this->isRuleRegistered($type, true))) {
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);
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)) {
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);
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))) {
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);
1108                      } elseif (is_string($newName)) {
1109                          $type = $newName;
1110                      }
1111  
1112                      $this->_rules[$elementName][] = array(
1113                                                          'type'        => $type,
1114                                                          'format'      => $format,
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))) {
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);
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,
1151                                              'format'     => $format,
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     /**
1169      * Adds a global validation rule
1170      *
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.
1173      * The rule function/method should return true in case of successful
1174      * validation and array('element name' => 'error') when there were errors.
1175      *
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)) {
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);
1184          }
1185          $this->_formRules[] = $rule;
1186      }
1187  
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)) {
1202              return self::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::applyFilter()", 'HTML_QuickForm_Error', true);
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      */
1264      static function arrayMerge($a, $b)
1265      {
1266          if (is_null($a)) {$a = array();}
1267          if (is_null($b)) {$b = array();}
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
1423  
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      {
1466          if (count($this->_rules) == 0 && count($this->_formRules) == 0 &&
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 {
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);
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)) {
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);
1573          }
1574          return true;
1575      } // end func freeze
1576  
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)) {
1607              return self::raiseError(null, QUICKFORM_INVALID_PROCESS, null, E_USER_WARNING, "Callback function does not exist in QuickForm::process()", 'HTML_QuickForm_Error', true);
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');
1651              $GLOBALS['_HTML_QuickForm_default_renderer'] = new HTML_QuickForm_Renderer_Default(); //Moodle: PHP 5.3 compatibility
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" .
1755                  "//<![CDATA[\n" .
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
1799       *
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';
1808          $renderer = new HTML_QuickForm_Renderer_Array($collectHidden); //Moodle: PHP 5.3 compatibility
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
1818       *
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])) {
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);
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       *
1853       * Unlike getSubmitValues(), this will return only the values
1854       * corresponding to the elements present in the form.
1855       *
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);
1879                  $pear = new PEAR();
1880                  if ($pear->isError($value)) {
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       */
1917      static function isError($value)
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       */
1932      static function errorMessage($value)
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  
1965  class 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
1998  ?>


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1