HTML_QuickForm
[ class tree: HTML_QuickForm ] [ index: HTML_QuickForm ] [ all elements ]

Source for file QuickForm.php

Documentation is available at QuickForm.php

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

Documentation generated on Mon, 11 Mar 2019 14:16:35 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.