]> git.mjollnir.org Git - moodle.git/commitdiff
This is a first cut of a new formslib.php a library of classes for creating and secur...
authorjamiesensei <jamiesensei>
Sun, 24 Sep 2006 17:04:51 +0000 (17:04 +0000)
committerjamiesensei <jamiesensei>
Sun, 24 Sep 2006 17:04:51 +0000 (17:04 +0000)
This is NOT YET PART OF THE MOODLE API it is here for experimental purposes.

68 files changed:
lang/en_utf8/form.php [new file with mode: 0644]
lib/form/checkbox.php [new file with mode: 0644]
lib/form/dateselector.php [new file with mode: 0644]
lib/form/file.php [new file with mode: 0644]
lib/form/group.php [new file with mode: 0644]
lib/form/htmleditor.php [new file with mode: 0644]
lib/form/password.php [new file with mode: 0644]
lib/form/radio.php [new file with mode: 0644]
lib/form/req.gif [new file with mode: 0644]
lib/form/req.png [new file with mode: 0644]
lib/form/select.php [new file with mode: 0644]
lib/form/text.php [new file with mode: 0644]
lib/form/textarea.php [new file with mode: 0644]
lib/formslib.php [new file with mode: 0644]
lib/pear/HTML/Common.php [new file with mode: 0644]
lib/pear/HTML/QuickForm.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/DHTMLRulesTableless.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Renderer.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Renderer/Array.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Renderer/Default.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Renderer/Object.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Renderer/Tableless.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Rule.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Rule/Callback.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Rule/Compare.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Rule/Email.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Rule/Range.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Rule/Regex.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/Rule/Required.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/RuleRegistry.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/advcheckbox.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/autocomplete.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/button.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/checkbox.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/date.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/element.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/file.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/group.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/header.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/hidden.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/hiddenselect.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/hierselect.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/html.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/image.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/input.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/link.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/password.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/radio.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/reset.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/select.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/static.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/submit.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/text.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/textarea.php [new file with mode: 0644]
lib/pear/HTML/QuickForm/xbutton.php [new file with mode: 0644]
theme/chameleon/config.php
theme/formal_white/config.php
theme/metal/config.php
theme/orangewhite/config.php
theme/orangewhitepda/config.php
theme/standard/config.php
theme/standard/styles_form.css [new file with mode: 0644]
theme/standardblue/config.php
theme/standardgreen/config.php
theme/standardlogo/config.php
theme/standardred/config.php
theme/standardwhite/config.php
theme/wood/config.php

diff --git a/lang/en_utf8/form.php b/lang/en_utf8/form.php
new file mode 100644 (file)
index 0000000..ecaebdf
--- /dev/null
@@ -0,0 +1,5 @@
+<?php
+$string['denotesreq']='$a denotes required field.';
+$string['requiredelement']='Required field.';
+$string['nonexistentformelements']='Trying to add help buttons to nonexistent form elements : $a';
+?>
\ No newline at end of file
diff --git a/lib/form/checkbox.php b/lib/form/checkbox.php
new file mode 100644 (file)
index 0000000..9a7f6f9
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+require_once('HTML/QuickForm/checkbox.php');
+
+/**
+ * HTML class for a checkbox type element
+ * 
+ * @author       Jamie Pratt
+ * @access       public
+ */
+class moodleform_checkbox extends HTML_QuickForm_checkbox{
+    /**
+     * html for help button, if empty then no help
+     *
+     * @var string
+     */
+    var $_helpbutton='';
+    /**
+     * set html for help button
+     *
+     * @access   public
+     * @param array $help array of arguments to make a help button
+     */
+    function setHelpButton($helpbuttonargs){
+        if (!is_array($helpbuttonargs)){
+            $helpbuttonargs=array($helpbuttonargs);
+        }else{
+            $helpbuttonargs=$helpbuttonargs;
+        }
+        //we do this to to return html instead of printing it 
+        //without having to specify it in every call to make a button.
+        $defaultargs=array('', '', 'moodle', true, false, '', true);
+        $helpbuttonargs=$helpbuttonargs + $defaultargs ;
+        $this->_helpbutton=call_user_func_array('helpbutton', $helpbuttonargs);
+    }
+    /**
+     * get html for help button
+     *
+     * @access   public
+     * @return  string html for help button
+     */
+    function getHelpButton(){
+        return $this->_helpbutton;
+    }
+}
+?>
\ No newline at end of file
diff --git a/lib/form/dateselector.php b/lib/form/dateselector.php
new file mode 100644 (file)
index 0000000..c3cefd0
--- /dev/null
@@ -0,0 +1,159 @@
+<?php
+global $CFG;
+require_once "$CFG->libdir/form/group.php";
+require_once "$CFG->libdir/formslib.php";
+
+/**
+ * Class for a group of elements used to input a date.
+ * 
+ * Emulates moodle print_date_selector function 
+ * 
+ * @author Jamie Pratt <me@jamiep.org>
+ * @access public
+ */
+class moodleform_date_selector extends moodleform_group
+{
+    /**
+    * Control the fieldnames for form elements
+    *
+    * day => string day   fieldname
+    * month => string month  fieldname
+    * year => string year  fieldname
+    * timezone => float/string timezone
+    * applydst => apply users daylight savings adjustment?
+    */
+    var $_options = array('startyear'=>1970, 'stopyear'=>2020,
+                    'timezone'=>99, 'applydst'=>true);
+
+   /**
+    * These complement separators, they are appended to the resultant HTML
+    * @access   private
+    * @var      array
+    */
+    var $_wrap = array('', '');
+
+   /**
+    * Class constructor
+    * 
+    * @access   public
+    * @param    string  Element's name
+    * @param    mixed   Label(s) for an element
+    * @param    array   Options to control the element's display
+    * @param    mixed   Either a typical HTML attribute string or an associative array
+    */
+    function moodleform_date_selector($elementName = null, $elementLabel = null, $options = array(), $attributes = null)
+    {
+        $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
+        $this->_persistantFreeze = true;
+        $this->_appendName = true;
+        $this->_type = 'date_selector';
+        // set the options, do not bother setting bogus ones
+        if (is_array($options)) {
+            foreach ($options as $name => $value) {
+                if (isset($this->_options[$name])) {
+                    if (is_array($value) && is_array($this->_options[$name])) {
+                        $this->_options[$name] = @array_merge($this->_options[$name], $value);
+                    } else {
+                        $this->_options[$name] = $value;
+                    }
+                }
+            }
+        }
+    }
+
+    // }}}
+    // {{{ _createElements()
+
+    function _createElements()
+    {
+        $this->_elements = array();
+        for ($i=1; $i<=31; $i++) {
+            $days[$i] = $i;
+        }
+        for ($i=1; $i<=12; $i++) {
+            $months[$i] = userdate(gmmktime(12,0,0,$i,1,2000), "%B");
+        }
+        for ($i=$this->_options['startyear']; $i<=$this->_options['stopyear']; $i++) {
+            $years[$i] = $i;
+        }
+        $this->_elements[] =& moodleform::createElement('select', 'day', null, $days, $this->getAttributes(), true);
+        $this->_elements[] =& moodleform::createElement('select','month', null, $months, $this->getAttributes(), true);
+        $this->_elements[] =& moodleform::createElement('select','year', null, $years, $this->getAttributes(), true);
+
+    }
+
+    // }}}
+    // {{{ setValue()
+
+    function setValue($value)
+    {
+        if (!($value)) {
+            $value = time();
+        }
+        if (!is_array($value)) {
+            $currentdate = usergetdate($value);
+            $value = array(
+                'day' => $currentdate['mday'],
+                'month' => $currentdate['mon'],
+                'year' => $currentdate['year']);
+            
+        }
+        parent::setValue($value);
+    }
+
+    // }}}
+    // {{{ toHtml()
+
+    function toHtml()
+    {
+        include_once('HTML/QuickForm/Renderer/Default.php');
+        $renderer =& new HTML_QuickForm_Renderer_Default();
+        $renderer->setElementTemplate('{element}');
+        parent::accept($renderer);
+        return $this->_wrap[0] . $renderer->toHtml() . $this->_wrap[1];
+    }
+
+    // }}}
+    // {{{ accept()
+
+    function accept(&$renderer, $required = false, $error = null)
+    {
+        $renderer->renderElement($this, $required, $error);
+    }
+
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        if ('updateValue' == $event) {
+            return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller);
+        } else {
+            return parent::onQuickFormEvent($event, $arg, $caller);
+        }
+    }
+    /**
+     * Output a timestamp. Give it the name of the group.
+     *
+     * @param array $submitValues
+     * @param bool $assoc
+     * @return array
+     */
+    function exportValue(&$submitValues, $assoc = false)
+    {
+        $value = null;
+        $valuearray = $this->_elements[0]->exportValue($submitValues[$this->getName()], true);
+        $valuearray +=$this->_elements[1]->exportValue($submitValues[$this->getName()], true);
+        $valuearray +=$this->_elements[2]->exportValue($submitValues[$this->getName()], true);
+        $value[$this->getName()]=make_timestamp($valuearray['year'],
+                               $valuearray['month'],
+                               $valuearray['day'],
+                               0,0,0,
+                               $this->_options['timezone'],
+                               $this->_options['applydst']);
+        return $value;
+    }
+
+    // }}}
+}
+?>
\ No newline at end of file
diff --git a/lib/form/file.php b/lib/form/file.php
new file mode 100644 (file)
index 0000000..f877f10
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+require_once('HTML/QuickForm/file.php');
+
+/**
+ * HTML class for a form element to upload a file
+ * 
+ * @author       Jamie Pratt
+ * @access       public
+ */
+class moodleform_file extends HTML_QuickForm_file{
+    /**
+     * html for help button, if empty then no help
+     *
+     * @var string
+     */
+    var $_helpbutton='';
+    /**
+     * set html for help button
+     *
+     * @access   public
+     * @param array $help array of arguments to make a help button
+     */
+    function setHelpButton($helpbuttonargs){
+        if (!is_array($helpbuttonargs)){
+            $helpbuttonargs=array($helpbuttonargs);
+        }else{
+            $helpbuttonargs=$helpbuttonargs;
+        }
+        //we do this to to return html instead of printing it 
+        //without having to specify it in every call to make a button.
+        $defaultargs=array('', '', 'moodle', true, false, '', true);
+        $helpbuttonargs=$helpbuttonargs + $defaultargs ;
+        $this->_helpbutton=call_user_func_array('helpbutton', $helpbuttonargs);
+    }
+    /**
+     * get html for help button
+     *
+     * @access   public
+     * @return  string html for help button
+     */
+    function getHelpButton(){
+        return $this->_helpbutton;
+    }
+}
+?>
\ No newline at end of file
diff --git a/lib/form/group.php b/lib/form/group.php
new file mode 100644 (file)
index 0000000..b83a740
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+require_once("HTML/QuickForm/group.php");
+
+/**
+ * HTML class for a form element group
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class moodleform_group extends HTML_QuickForm_group{
+    /**
+     * html for help button, if empty then no help
+     *
+     * @var string
+     */
+    var $_helpbutton='';
+    /**
+     * set html for help button
+     *
+     * @access   public
+     * @param array $help array of arguments to make a help button
+     */
+    function setHelpButton($helpbuttonargs){
+        if (!is_array($helpbuttonargs)){
+            $helpbuttonargs=array($helpbuttonargs);
+        }else{
+            $helpbuttonargs=$helpbuttonargs;
+        }
+        //we do this to to return html instead of printing it 
+        //without having to specify it in every call to make a button.
+        $defaultargs=array('', '', 'moodle', true, false, '', true);
+        $helpbuttonargs=$helpbuttonargs + $defaultargs ;
+        $this->_helpbutton=call_user_func_array('helpbutton', $helpbuttonargs);
+    }
+    /**
+     * get html for help button
+     *
+     * @access   public
+     * @return  string html for help button
+     */
+    function getHelpButton(){
+        return $this->_helpbutton;
+    }
+}
\ No newline at end of file
diff --git a/lib/form/htmleditor.php b/lib/form/htmleditor.php
new file mode 100644 (file)
index 0000000..5882cf4
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+global $CFG;
+require_once("$CFG->libdir/form/textarea.php");
+
+/**
+ * HTML class for htmleditor type element
+ * 
+ * @author       Jamie Pratt
+ * @access       public
+ */
+class moodleform_htmleditor extends moodleform_textarea{
+    var $_type = 'htmleditor';
+    var $_elementTemplateType='default';
+    var $_canUseHtmlEditor;
+    var $_options=array('course'=>0);
+    function moodleform_htmleditor($elementName=null, $elementLabel=null, $attributes=null){
+        $this->_canUseHtmlEditor=can_use_html_editor();
+        if ($this->_canUseHtmlEditor){
+            $this->_elementTemplateType='wide';
+        }else{
+            $this->_elementTemplateType='default';
+        }
+        parent::moodleform_textarea($elementName, $elementLabel, $attributes);
+    }
+    function getElementTemplateType(){
+        return $this->_elementTemplateType;
+    }
+    function toHtml(){
+        ob_start();
+        use_html_editor($this->getName());
+        $script=ob_get_clean();
+        if ($this->_flagFrozen) {
+            return $this->getFrozenHtml();
+        } else {
+            return $this->_getTabs() .
+                    print_textarea($this->_canUseHtmlEditor, 
+                                    $this->getAttribute('rows'),
+                                    $this->getAttribute('cols'),
+                                    $this->getAttribute('width'),
+                                    $this->getAttribute('height'),
+                                    $this->getName(),
+                                    preg_replace("/(\r\n|\n|\r)/", '&#010;',$this->getValue()),
+                                    $this->_options['course'],
+                                    true).$script;
+        }
+    } //end func toHtml
+
+}
+?>
\ No newline at end of file
diff --git a/lib/form/password.php b/lib/form/password.php
new file mode 100644 (file)
index 0000000..d719da8
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+require_once('HTML/QuickForm/password.php');
+
+/**
+ * HTML class for a password type element
+ * 
+ * @author       Jamie Pratt
+ * @access       public
+ */
+class moodleform_password extends HTML_QuickForm_password{
+    /**
+     * html for help button, if empty then no help
+     *
+     * @var string
+     */
+    var $_helpbutton='';
+    /**
+     * set html for help button
+     *
+     * @access   public
+     * @param array $help array of arguments to make a help button
+     */
+    function setHelpButton($helpbuttonargs){
+        if (!is_array($helpbuttonargs)){
+            $helpbuttonargs=array($helpbuttonargs);
+        }else{
+            $helpbuttonargs=$helpbuttonargs;
+        }
+        //we do this to to return html instead of printing it 
+        //without having to specify it in every call to make a button.
+        $defaultargs=array('', '', 'moodle', true, false, '', true);
+        $helpbuttonargs=$helpbuttonargs + $defaultargs ;
+        $this->_helpbutton=call_user_func_array('helpbutton', $helpbuttonargs);
+    }
+    /**
+     * get html for help button
+     *
+     * @access   public
+     * @return  string html for help button
+     */
+    function getHelpButton(){
+        return $this->_helpbutton;
+    }
+}
+?>
\ No newline at end of file
diff --git a/lib/form/radio.php b/lib/form/radio.php
new file mode 100644 (file)
index 0000000..d9a57da
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+require_once('HTML/QuickForm/radio.php');
+
+/**
+ * HTML class for a radio type element
+ * 
+ * @author       Jamie Pratt
+ * @access       public
+ */
+class moodleform_radio extends HTML_QuickForm_radio{
+    /**
+     * html for help button, if empty then no help
+     *
+     * @var string
+     */
+    var $_helpbutton='';
+    /**
+     * set html for help button
+     *
+     * @access   public
+     * @param array $help array of arguments to make a help button
+     */
+    function setHelpButton($helpbuttonargs){
+        if (!is_array($helpbuttonargs)){
+            $helpbuttonargs=array($helpbuttonargs);
+        }else{
+            $helpbuttonargs=$helpbuttonargs;
+        }
+        //we do this to to return html instead of printing it 
+        //without having to specify it in every call to make a button.
+        $defaultargs=array('', '', 'moodle', true, false, '', true);
+        $helpbuttonargs=$helpbuttonargs + $defaultargs ;
+        $this->_helpbutton=call_user_func_array('helpbutton', $helpbuttonargs);
+    }
+    /**
+     * get html for help button
+     *
+     * @access   public
+     * @return  string html for help button
+     */
+    function getHelpButton(){
+        return $this->_helpbutton;
+    }
+}
+?>
\ No newline at end of file
diff --git a/lib/form/req.gif b/lib/form/req.gif
new file mode 100644 (file)
index 0000000..42e5502
Binary files /dev/null and b/lib/form/req.gif differ
diff --git a/lib/form/req.png b/lib/form/req.png
new file mode 100644 (file)
index 0000000..e843ed3
Binary files /dev/null and b/lib/form/req.png differ
diff --git a/lib/form/select.php b/lib/form/select.php
new file mode 100644 (file)
index 0000000..521ca17
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+require_once('HTML/QuickForm/select.php');
+
+/**
+ * HTML class for a select type element
+ * 
+ * @author       Jamie Pratt
+ * @access       public
+ */
+class moodleform_select extends HTML_QuickForm_select{
+    /**
+     * html for help button, if empty then no help
+     *
+     * @var string
+     */
+    var $_helpbutton='';
+    /**
+     * set html for help button
+     *
+     * @access   public
+     * @param array $help array of arguments to make a help button
+     */
+    function setHelpButton($helpbuttonargs){
+        if (!is_array($helpbuttonargs)){
+            $helpbuttonargs=array($helpbuttonargs);
+        }else{
+            $helpbuttonargs=$helpbuttonargs;
+        }
+        //we do this to to return html instead of printing it 
+        //without having to specify it in every call to make a button.
+        $defaultargs=array('', '', 'moodle', true, false, '', true);
+        $helpbuttonargs=$helpbuttonargs + $defaultargs ;
+        $this->_helpbutton=call_user_func_array('helpbutton', $helpbuttonargs);
+    }
+    /**
+     * get html for help button
+     *
+     * @access   public
+     * @return  string html for help button
+     */
+    function getHelpButton(){
+        return $this->_helpbutton;
+    }
+}
+?>
\ No newline at end of file
diff --git a/lib/form/text.php b/lib/form/text.php
new file mode 100644 (file)
index 0000000..d1bf0c4
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+require_once("HTML/QuickForm/text.php");
+
+/**
+ * HTML class for a text type element
+ * 
+ * @author       Jamie Pratt
+ * @access       public
+ */
+class moodleform_text extends HTML_QuickForm_text{
+    /**
+     * html for help button, if empty then no help
+     *
+     * @var string
+     */
+    var $_helpbutton='';
+    /**
+     * set html for help button
+     *
+     * @access   public
+     * @param array $help array of arguments to make a help button
+     */
+    function setHelpButton($helpbuttonargs){
+        if (!is_array($helpbuttonargs)){
+            $helpbuttonargs=array($helpbuttonargs);
+        }else{
+            $helpbuttonargs=$helpbuttonargs;
+        }
+        //we do this to to return html instead of printing it 
+        //without having to specify it in every call to make a button.
+        $defaultargs=array('', '', 'moodle', true, false, '', true);
+        $helpbuttonargs=$helpbuttonargs + $defaultargs ;
+        $this->_helpbutton=call_user_func_array('helpbutton', $helpbuttonargs);
+    }
+    /**
+     * get html for help button
+     *
+     * @access   public
+     * @return  string html for help button
+     */
+    function getHelpButton(){
+        return $this->_helpbutton;
+    }
+}
\ No newline at end of file
diff --git a/lib/form/textarea.php b/lib/form/textarea.php
new file mode 100644 (file)
index 0000000..2e3450a
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+require_once('HTML/QuickForm/textarea.php');
+
+/**
+ * HTML class for a textarea type element
+ * 
+ * @author       Jamie Pratt
+ * @access       public
+ */
+class moodleform_textarea extends HTML_QuickForm_textarea{
+    /**
+     * html for help button, if empty then no help
+     *
+     * @var string
+     */
+    var $_helpbutton='';
+    /**
+     * set html for help button
+     *
+     * @access   public
+     * @param array $help array of arguments to make a help button
+     */
+    function setHelpButton($helpbuttonargs){
+        if (!is_array($helpbuttonargs)){
+            $helpbuttonargs=array($helpbuttonargs);
+        }else{
+            $helpbuttonargs=$helpbuttonargs;
+        }
+        //we do this to to return html instead of printing it 
+        //without having to specify it in every call to make a button.
+        $defaultargs=array('', '', 'moodle', true, false, '', true);
+        $helpbuttonargs=$helpbuttonargs + $defaultargs ;
+        $this->_helpbutton=call_user_func_array('helpbutton', $helpbuttonargs);
+    }
+    /**
+     * get html for help button
+     *
+     * @access   public
+     * @return  string html for help button
+     */
+    function getHelpButton(){
+        return $this->_helpbutton;
+    }
+}
+?>
\ No newline at end of file
diff --git a/lib/formslib.php b/lib/formslib.php
new file mode 100644 (file)
index 0000000..bc1e108
--- /dev/null
@@ -0,0 +1,279 @@
+<?php
+/**
+ * formslib.php - library of classes for creating forms in Moodle, based on PEAR QuickForms.
+ * THIS IS NOT YET PART OF THE MOODLE API, IT IS HERE FOR TESTING ONLY
+ * @author  Jamie Pratt
+ * @version $Id$
+ * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
+ */
+
+//point pear include path to moodles lib/pear so that includes and requires will search there for files before anywhere else.
+if (FALSE===strstr(ini_get('include_path'), $CFG->libdir.'/pear' )){
+    ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include_path'));
+}
+require_once 'HTML/QuickForm.php';
+require_once 'HTML/QuickForm/DHTMLRulesTableless.php';
+require_once 'HTML/QuickForm/Renderer/Tableless.php';
+
+class moodleform extends HTML_QuickForm_DHTMLRulesTableless{
+    /**
+     * Class constructor - same parameters as HTML_QuickForm_DHTMLRulesTableless
+     * @param    string      $formName          Form's name.
+     * @param    string      $method            (optional)Form's method defaults to 'POST'
+     * @param    string      $action            (optional)Form's action
+     * @param    string      $target            (optional)Form's target defaults to none
+     * @param    mixed       $attributes        (optional)Extra attributes for <form> tag
+     * @param    bool        $trackSubmit       (optional)Whether to track if the form was submitted by adding a special hidden field
+     * @access   public
+     */
+    function moodleform($formName='', $method='post', $action='', $target='', $attributes=null){
+        global $CFG;
+        //we need to override the constructor, we don't call the parent constructor
+        //at all because it strips slashes depending on the magic quotes setting
+        //whereas Moodle already has added slashes whether magic quotes is on or not.
+        
+        //also added check for sesskey and added sesskey to all forms
+        //and told class to ask Moodle for the max upload file size       
+        HTML_Common::HTML_Common($attributes);
+        $method = (strtoupper($method) == 'GET') ? 'get' : 'post';
+        $action = ($action == '') ? $_SERVER['PHP_SELF'] : $action;
+        $target = empty($target) ? array() : array('target' => $target);
+        //no 'name' atttribute for form in xhtml strict :
+        $attributes = array('action'=>$action, 'method'=>$method, 'id'=>$formName) + $target;
+        $this->updateAttributes($attributes);
+        //check for sesskey for this form 
+        //if it is not present then we don't accept any input
+        if (isset($_REQUEST['_qf__' . $formName])) {
+            $this->_submitValues = $this->_recursiveFilter('stripslashes', 'get' == $method? $_GET: $_POST);
+            foreach ($_FILES as $keyFirst => $valFirst) {
+                foreach ($valFirst as $keySecond => $valSecond) {
+                    if ('name' == $keySecond) {
+                        $this->_submitFiles[$keyFirst][$keySecond] = $this->_recursiveFilter('stripslashes', $valSecond);
+                    } else {
+                        $this->_submitFiles[$keyFirst][$keySecond] = $valSecond;
+                    }
+                }
+            }
+
+            $this->_flagSubmitted = count($this->_submitValues) > 0 || count($this->_submitFiles) > 0;
+        }
+        
+        //check sesskey
+        if ($this->_flagSubmitted){
+            confirm_sesskey($this->_submitValues['_qf__' . $formName]);
+        }
+        unset($this->_submitValues['_qf__' . $formName]);
+        //add sesskey to all forms
+        $this->addElement('hidden', '_qf__' . $formName, sesskey());
+        
+        if (preg_match('/^([0-9]+)([a-zA-Z]*)$/', get_max_upload_file_size(), $matches)) {
+            // see http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
+            switch (strtoupper($matches['2'])) {
+                case 'G':
+                    $this->_maxFileSize = $matches['1'] * 1073741824;
+                    break;
+                case 'M':
+                    $this->_maxFileSize = $matches['1'] * 1048576;
+                    break;
+                case 'K':
+                    $this->_maxFileSize = $matches['1'] * 1024;
+                    break;
+                default:
+                    $this->_maxFileSize = $matches['1'];
+            }
+        }
+        //this is custom stuff for Moodle : 
+        $oldclass=   $this->getAttribute('class');
+        if (!empty($oldclass)){
+            $this->updateAttributes(array('class'=>$oldclass.' mform'));
+        }else {
+             $this->updateAttributes(array('class'=>'mform'));
+        }
+        $this->_helpImageURL="$CFG->wwwroot/lib/form/req.gif"; 
+        $this->_reqHTML = 
+            helpbutton('requiredelement', get_string('requiredelement', 'form'),'moodle',
+                 true, false, '', true, '<img alt="'.get_string('requiredelement', 'form').'" src="'.
+                    $this->_helpImageURL.'" />');
+        $this->setRequiredNote(get_string('denotesreq', 'form', $this->getReqHTML()));
+    }
+    function getReqHTML(){
+        return $this->_reqHTML;
+    }
+    /**
+     * Class constructor - same parameters as HTML_QuickForm_DHTMLRulesTableless
+     * @param    array       $buttons          An associative array representing help button to attach to 
+     *                                          to the form. keys of array correspond to names of elements in form.
+     * 
+     * @access   public
+    */
+    function add_help_buttons($buttons, $suppresscheck=false){
+        
+        foreach ($this->_elements as $no => $element){
+            if (array_key_exists($element->getName(), $buttons)){
+
+                //dynamically create a property so we don't have to modify element
+                //class :
+                $this->_elements[$no]->setHelpButton($buttons[$element->getName()]);
+                unset($buttons[$element->getName()]);
+            }
+            
+        }
+        if (count($buttons)&& !$suppresscheck){
+            print_error('nonexistentformelements', 'form', '', join(', ', array_keys($buttons)));
+        }
+    }
+    /**
+     * Applies a data filter for the given field(s)
+     * We can use any PARAM_ 
+     *
+     * @param    mixed     $element       Form element name or array of such names
+     * @param    mixed     $filter        Callback, either function name or array(&$object, 'method') or PARAM_ integer
+     * @since    2.0
+     * @access   public
+     */
+    function applyFilter($element, $filter){
+        if (is_numeric($filter)){
+            $filter=create_function('$value', "clean_param(\$value, $filter);");
+        }
+        parent::applyFilter($element, $filter);
+    }
+    function exportValue($element, $addslashes=true){
+        $unfiltered=parent::exportValue($element);
+        if ($addslashes){
+            return HTML_QuickForm::_recursiveFilter('addslashes',$unfiltered);
+        } else {
+            return $unfiltered;
+        }
+    }
+    function exportValues($elementList, $addslashes=true){
+        $unfiltered=parent::exportValues($elementList);
+        if ($addslashes){
+            return HTML_QuickForm::_recursiveFilter('addslashes',$unfiltered);
+        } else {
+            return $unfiltered;
+        }
+    }
+}
+
+/**
+ * A renderer for moodleform that only uses XHTML and CSS and no
+ * table tags, extends PEAR class HTML_QuickForm_Renderer_Tableless
+ * 
+ * Stylesheet is part of standard theme and should be automatically included.
+ *
+ * @author      Jamie Pratt <me@jamiep.org>
+ * @license    gpl license
+ */
+class moodleform_renderer extends HTML_QuickForm_Renderer_Tableless{
+
+    /**
+    * Element template array
+    * @var      array
+    * @access   private
+    */
+    var $_elementTemplates;
+    var $_htmleditors=array();
+    function moodleform_renderer(){
+        $this->_elementTemplates=array('default'=>"\n\t\t<div class=\"qfrow\"><label class=\"qflabel\">{label}{help}<!-- BEGIN required -->{req}<!-- END required --></label><div class=\"qfelement<!-- BEGIN error --> error<!-- END error -->\"><!-- BEGIN error --><span class=\"error\">{error}</span><br /><!-- END error -->{element}</div></div><br />",
+        'wide'=>"\n\t\t<div class=\"qfrow\"><label class=\"qflabel\">{label}{help}<!-- BEGIN required -->{req}<!-- END required --></label><br /><div class=\"qfelementwide<!-- BEGIN error --> error<!-- END error -->\"><!-- BEGIN error --><span class=\"error\">{error}</span><br /><!-- END error -->{element}</span></div><br />");
+
+        parent::HTML_QuickForm_Renderer_Tableless();
+    }
+    function startForm(&$form){
+        $this->_reqHTML=$form->getReqHTML();
+        $this->_elementTemplates=str_replace('{req}', $this->_reqHTML, $this->_elementTemplates);
+        parent::startForm($form);
+    }
+    function startGroup(&$group, $required, $error){
+        if (method_exists($group, 'getElementTemplateType')){
+            $html = $this->_elementTemplates[$element->getElementTemplateType()];
+        }else{
+            $html = $this->_elementTemplates['default'];
+           
+        }
+        if (method_exists($group, 'getHelpButton')){
+            $html =str_replace('{help}', $group->getHelpButton(), $html);
+        }else{
+            $html =str_replace('{help}', '', $html);
+            
+        }
+        $this->_templates[$group->getName()]=$html;
+        // Fix for bug in tableless quickforms that didn't allow you to stop a
+        // fieldset before a group of elements.
+        // if the element name indicates the end of a fieldset, close the fieldset
+        if (   in_array($group->getName(), $this->_stopFieldsetElements)
+            && $this->_fieldsetsOpen > 0
+           ) {
+            $this->_html .= $this->_closeFieldsetTemplate;
+            $this->_fieldsetsOpen--;
+        }
+        parent::startGroup($group, $required, $error);
+    }
+    function renderElement(&$element, $required, $error){
+        if (method_exists($element, 'getElementTemplateType')){
+            $html = $this->_elementTemplates[$element->getElementTemplateType()];
+        }else{
+            $html = $this->_elementTemplates['default'];
+           
+        }
+        if (method_exists($element, 'getHelpButton')){
+            $html=str_replace('{help}', $element->getHelpButton(), $html);
+        }else{
+            $html=str_replace('{help}', '', $html);
+            
+        }
+        $this->_templates[$element->getName()]=$html;
+        
+        parent::renderElement($element, $required, $error);
+    }
+
+    
+}
+
+class moodleform_filter{
+    var $paramtype;
+    var $default;
+    function moodleform_filter($paramtype, $default){
+        $this->paramtype=$paramtype;
+        $this->default=$default;
+    }
+    function required_param($value){
+        if (isset($value)) {
+            $param = $value;
+        } else {
+            error('A required parameter was missing');
+        }
+    
+        return $this->clean_param($param);
+    }
+    function optional_param($value){
+        if (!isset($value)) {
+           return $this->default;
+        }
+        return $this->clean_param($value);
+    }
+    function clean_param($value){
+        //clean param expects vars with slashes
+        $value=HTML_QuickForm::_recursiveFilter('addslashes', $value);
+        $value=clean_param($value, $this->paramtype);
+        return HTML_QuickForm::_recursiveFilter('stripslashes', $value);
+    }
+}    
+
+$GLOBALS['_HTML_QuickForm_default_renderer']=& new moodleform_renderer();
+
+moodleform::registerElementType('checkbox', "$CFG->libdir/form/checkbox.php", 'moodleform_checkbox');
+moodleform::registerElementType('file', "$CFG->libdir/form/file.php", 'moodleform_file');
+moodleform::registerElementType('group', "$CFG->libdir/form/group.php", 'moodleform_group');
+moodleform::registerElementType('password', "$CFG->libdir/form/password.php", 'moodleform_password');
+moodleform::registerElementType('radio', "$CFG->libdir/form/radio.php", 'moodleform_radio');
+moodleform::registerElementType('select', "$CFG->libdir/form/select.php", 'moodleform_select');
+moodleform::registerElementType('text', "$CFG->libdir/form/text.php", 'moodleform_text');
+moodleform::registerElementType('textarea', "$CFG->libdir/form/textarea.php", 'moodleform_textarea');
+moodleform::registerElementType('date_selector', "$CFG->libdir/form/dateselector.php", 'moodleform_date_selector');
+moodleform::registerElementType('htmleditor', "$CFG->libdir/form/htmleditor.php", 'moodleform_htmleditor');
+
+if ($CFG->debug >= DEBUG_ALL){
+    PEAR::setErrorHandling(PEAR_ERROR_PRINT);
+}
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/Common.php b/lib/pear/HTML/Common.php
new file mode 100644 (file)
index 0000000..2c687dd
--- /dev/null
@@ -0,0 +1,428 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Author: Adam Daniel <adaniel1@eesus.jnj.com>                         |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+/**
+ * Base class for all HTML classes
+ * 
+ * @author    Adam Daniel <adaniel1@eesus.jnj.com>
+ * @category  HTML
+ * @package   HTML_Common
+ * @version   1.2.2
+ * @abstract
+ */
+
+/**
+ * Base class for all HTML classes
+ *
+ * @author      Adam Daniel <adaniel1@eesus.jnj.com>
+ * @version     1.7
+ * @since       PHP 4.0.3pl1
+ * @abstract
+ */
+class HTML_Common {
+
+    /**
+     * Associative array of table attributes
+     * @var     array
+     * @access  private
+     */
+    var $_attributes = array();
+
+    /**
+     * Tab offset of the table
+     * @var     int
+     * @access  private
+     */
+    var $_tabOffset = 0;
+
+    /**
+     * Tab string
+     * @var       string
+     * @since     1.7
+     * @access    private
+     */
+    var $_tab = "\11";
+
+    /**
+     * Contains the line end string
+     * @var       string
+     * @since     1.7
+     * @access    private
+     */
+    var $_lineEnd = "\12";
+
+    /**
+     * HTML comment on the object
+     * @var       string
+     * @since     1.5
+     * @access    private
+     */
+    var $_comment = '';
+
+    /**
+     * Class constructor
+     * @param    mixed   $attributes     Associative array of table tag attributes 
+     *                                   or HTML attributes name="value" pairs
+     * @param    int     $tabOffset      Indent offset in tabs
+     * @access   public
+     */
+    function HTML_Common($attributes = null, $tabOffset = 0)
+    {
+        $this->setAttributes($attributes);
+        $this->setTabOffset($tabOffset);
+    } // end constructor
+
+    /**
+     * Returns the current API version
+     * @access   public
+     * @returns  double
+     */
+    function apiVersion()
+    {
+        return 1.7;
+    } // end func apiVersion
+
+    /**
+     * Returns the lineEnd
+     * 
+     * @since     1.7
+     * @access    private
+     * @return    string
+     * @throws
+     */
+    function _getLineEnd()
+    {
+        return $this->_lineEnd;
+    } // end func getLineEnd
+
+    /**
+     * Returns a string containing the unit for indenting HTML
+     * 
+     * @since     1.7
+     * @access    private
+     * @return    string
+     */
+    function _getTab()
+    {
+        return $this->_tab;
+    } // end func _getTab
+
+    /**
+     * Returns a string containing the offset for the whole HTML code
+     * 
+     * @return    string
+     * @access   private
+     */
+    function _getTabs()
+    {
+        return str_repeat($this->_getTab(), $this->_tabOffset);
+    } // end func _getTabs
+
+    /**
+     * Returns an HTML formatted attribute string
+     * @param    array   $attributes
+     * @return   string
+     * @access   private
+     */
+    function _getAttrString($attributes)
+    {
+        $strAttr = '';
+
+        if (is_array($attributes)) {
+            foreach ($attributes as $key => $value) {
+                $strAttr .= ' ' . $key . '="' . htmlspecialchars($value) . '"';
+            }
+        }
+        return $strAttr;
+    } // end func _getAttrString
+
+    /**
+     * Returns a valid atrributes array from either a string or array
+     * @param    mixed   $attributes     Either a typical HTML attribute string or an associative array
+     * @access   private
+     */
+    function _parseAttributes($attributes)
+    {
+        if (is_array($attributes)) {
+            $ret = array();
+            foreach ($attributes as $key => $value) {
+                if (is_int($key)) {
+                    $key = $value = strtolower($value);
+                } else {
+                    $key = strtolower($key);
+                }
+                $ret[$key] = $value;
+            }
+            return $ret;
+
+        } elseif (is_string($attributes)) {
+            $preg = "/(([A-Za-z_:]|[^\\x00-\\x7F])([A-Za-z0-9_:.-]|[^\\x00-\\x7F])*)" .
+                "([ \\n\\t\\r]+)?(=([ \\n\\t\\r]+)?(\"[^\"]*\"|'[^']*'|[^ \\n\\t\\r]*))?/";
+            if (preg_match_all($preg, $attributes, $regs)) {
+                for ($counter=0; $counter<count($regs[1]); $counter++) {
+                    $name  = $regs[1][$counter];
+                    $check = $regs[0][$counter];
+                    $value = $regs[7][$counter];
+                    if (trim($name) == trim($check)) {
+                        $arrAttr[strtolower(trim($name))] = strtolower(trim($name));
+                    } else {
+                        if (substr($value, 0, 1) == "\"" || substr($value, 0, 1) == "'") {
+                            $value = substr($value, 1, -1);
+                        }
+                        $arrAttr[strtolower(trim($name))] = trim($value);
+                    }
+                }
+                return $arrAttr;
+            }
+        }
+    } // end func _parseAttributes
+
+    /**
+     * Returns the array key for the given non-name-value pair attribute
+     * 
+     * @param     string    $attr         Attribute
+     * @param     array     $attributes   Array of attribute
+     * @since     1.0
+     * @access    private
+     * @return    bool
+     * @throws
+     */
+    function _getAttrKey($attr, $attributes)
+    {
+        if (isset($attributes[strtolower($attr)])) {
+            return true;
+        } else {
+            return null;
+        }
+    } //end func _getAttrKey
+
+    /**
+     * Updates the attributes in $attr1 with the values in $attr2 without changing the other existing attributes
+     * @param    array   $attr1      Original attributes array
+     * @param    array   $attr2      New attributes array
+     * @access   private
+     */
+    function _updateAttrArray(&$attr1, $attr2)
+    {
+        if (!is_array($attr2)) {
+            return false;
+        }
+        foreach ($attr2 as $key => $value) {
+            $attr1[$key] = $value;
+        }
+    } // end func _updateAtrrArray
+
+    /**
+     * Removes the given attribute from the given array
+     * 
+     * @param     string    $attr           Attribute name
+     * @param     array     $attributes     Attribute array
+     * @since     1.4
+     * @access    private
+     * @return    void
+     * @throws
+     */
+    function _removeAttr($attr, &$attributes)
+    {
+        $attr = strtolower($attr);
+        if (isset($attributes[$attr])) {
+            unset($attributes[$attr]);
+        }
+    } //end func _removeAttr
+
+    /**
+     * Returns the value of the given attribute
+     * 
+     * @param     string    $attr   Attribute name
+     * @since     1.5
+     * @access    public
+     * @return    void
+     * @throws
+     */
+    function getAttribute($attr)
+    {
+        $attr = strtolower($attr);
+        if (isset($this->_attributes[$attr])) {
+            return $this->_attributes[$attr];
+        }
+        return null;
+    } //end func getAttribute
+
+    /**
+     * Sets the HTML attributes
+     * @param    mixed   $attributes     Either a typical HTML attribute string or an associative array
+     * @access   public
+     */
+    function setAttributes($attributes)
+    {
+        $this->_attributes = $this->_parseAttributes($attributes);
+    } // end func setAttributes
+
+    /**
+     * Returns the assoc array (default) or string of attributes
+     *
+     * @param     bool    Whether to return the attributes as string 
+     * @since     1.6
+     * @access    public
+     * @return    mixed   attributes
+     */
+    function getAttributes($asString = false)
+    {
+        if ($asString) {
+            return $this->_getAttrString($this->_attributes);
+        } else {
+            return $this->_attributes;
+        }
+    } //end func getAttributes
+
+    /**
+     * Updates the passed attributes without changing the other existing attributes
+     * @param    mixed   $attributes     Either a typical HTML attribute string or an associative array
+     * @access   public
+     */
+    function updateAttributes($attributes)
+    {
+        $this->_updateAttrArray($this->_attributes, $this->_parseAttributes($attributes));
+    } // end func updateAttributes
+
+    /**
+     * Removes an attribute
+     * 
+     * @param     string    $attr   Attribute name
+     * @since     1.4
+     * @access    public
+     * @return    void
+     * @throws
+     */
+    function removeAttribute($attr)
+    {
+        $this->_removeAttr($attr, $this->_attributes);
+    } //end func removeAttribute
+
+    /**
+     * Sets the line end style to Windows, Mac, Unix or a custom string.
+     * 
+     * @param   string  $style  "win", "mac", "unix" or custom string.
+     * @since   1.7
+     * @access  public
+     * @return  void
+     */
+    function setLineEnd($style)
+    {
+        switch ($style) {
+            case 'win':
+                $this->_lineEnd = "\15\12";
+                break;
+            case 'unix':
+                $this->_lineEnd = "\12";
+                break;
+            case 'mac':
+                $this->_lineEnd = "\15";
+                break;
+            default:
+                $this->_lineEnd = $style;
+        }
+    } // end func setLineEnd
+
+    /**
+     * Sets the tab offset
+     *
+     * @param    int     $offset
+     * @access   public
+     */
+    function setTabOffset($offset)
+    {
+        $this->_tabOffset = $offset;
+    } // end func setTabOffset
+
+    /**
+     * Returns the tabOffset
+     * 
+     * @since     1.5
+     * @access    public
+     * @return    int
+     */
+    function getTabOffset()
+    {
+        return $this->_tabOffset;
+    } //end func getTabOffset
+
+    /**
+     * Sets the string used to indent HTML
+     * 
+     * @since     1.7
+     * @param     string    $string     String used to indent ("\11", "\t", '  ', etc.).
+     * @access    public
+     * @return    void
+     */
+    function setTab($string)
+    {
+        $this->_tab = $string;
+    } // end func setTab
+
+    /**
+     * Sets the HTML comment to be displayed at the beginning of the HTML string
+     *
+     * @param     string
+     * @since     1.4
+     * @access    public
+     * @return    void
+     */
+    function setComment($comment)
+    {
+        $this->_comment = $comment;
+    } // end func setHtmlComment
+
+    /**
+     * Returns the HTML comment
+     * 
+     * @since     1.5
+     * @access    public
+     * @return    string
+     */
+    function getComment()
+    {
+        return $this->_comment;
+    } //end func getComment
+
+    /**
+     * Abstract method.  Must be extended to return the objects HTML
+     *
+     * @access    public
+     * @return    string
+     * @abstract
+     */
+    function toHtml()
+    {
+        return '';
+    } // end func toHtml
+
+    /**
+     * Displays the HTML to the screen
+     *
+     * @access    public
+     */
+    function display()
+    {
+        print $this->toHtml();
+    } // end func display
+
+} // end class HTML_Common
+?>
diff --git a/lib/pear/HTML/QuickForm.php b/lib/pear/HTML/QuickForm.php
new file mode 100644 (file)
index 0000000..b16ef0b
--- /dev/null
@@ -0,0 +1,1992 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('PEAR.php');
+require_once('HTML/Common.php');
+
+$GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'] = 
+        array(
+            'group'         =>array('HTML/QuickForm/group.php','HTML_QuickForm_group'),
+            'hidden'        =>array('HTML/QuickForm/hidden.php','HTML_QuickForm_hidden'),
+            'reset'         =>array('HTML/QuickForm/reset.php','HTML_QuickForm_reset'),
+            'checkbox'      =>array('HTML/QuickForm/checkbox.php','HTML_QuickForm_checkbox'),
+            'file'          =>array('HTML/QuickForm/file.php','HTML_QuickForm_file'),
+            'image'         =>array('HTML/QuickForm/image.php','HTML_QuickForm_image'),
+            'password'      =>array('HTML/QuickForm/password.php','HTML_QuickForm_password'),
+            'radio'         =>array('HTML/QuickForm/radio.php','HTML_QuickForm_radio'),
+            'button'        =>array('HTML/QuickForm/button.php','HTML_QuickForm_button'),
+            'submit'        =>array('HTML/QuickForm/submit.php','HTML_QuickForm_submit'),
+            'select'        =>array('HTML/QuickForm/select.php','HTML_QuickForm_select'),
+            'hiddenselect'  =>array('HTML/QuickForm/hiddenselect.php','HTML_QuickForm_hiddenselect'),
+            'text'          =>array('HTML/QuickForm/text.php','HTML_QuickForm_text'),
+            'textarea'      =>array('HTML/QuickForm/textarea.php','HTML_QuickForm_textarea'),
+            'link'          =>array('HTML/QuickForm/link.php','HTML_QuickForm_link'),
+            'advcheckbox'   =>array('HTML/QuickForm/advcheckbox.php','HTML_QuickForm_advcheckbox'),
+            'date'          =>array('HTML/QuickForm/date.php','HTML_QuickForm_date'),
+            'static'        =>array('HTML/QuickForm/static.php','HTML_QuickForm_static'),
+            'header'        =>array('HTML/QuickForm/header.php', 'HTML_QuickForm_header'),
+            'html'          =>array('HTML/QuickForm/html.php', 'HTML_QuickForm_html'),
+            'hierselect'    =>array('HTML/QuickForm/hierselect.php', 'HTML_QuickForm_hierselect'),
+            'autocomplete'  =>array('HTML/QuickForm/autocomplete.php', 'HTML_QuickForm_autocomplete'),
+            'xbutton'       =>array('HTML/QuickForm/xbutton.php','HTML_QuickForm_xbutton')
+        );
+
+$GLOBALS['_HTML_QuickForm_registered_rules'] = array(
+    'required'      => array('html_quickform_rule_required', 'HTML/QuickForm/Rule/Required.php'),
+    'maxlength'     => array('html_quickform_rule_range',    'HTML/QuickForm/Rule/Range.php'),
+    'minlength'     => array('html_quickform_rule_range',    'HTML/QuickForm/Rule/Range.php'),
+    'rangelength'   => array('html_quickform_rule_range',    'HTML/QuickForm/Rule/Range.php'),
+    'email'         => array('html_quickform_rule_email',    'HTML/QuickForm/Rule/Email.php'),
+    'regex'         => array('html_quickform_rule_regex',    'HTML/QuickForm/Rule/Regex.php'),
+    'lettersonly'   => array('html_quickform_rule_regex',    'HTML/QuickForm/Rule/Regex.php'),
+    'alphanumeric'  => array('html_quickform_rule_regex',    'HTML/QuickForm/Rule/Regex.php'),
+    'numeric'       => array('html_quickform_rule_regex',    'HTML/QuickForm/Rule/Regex.php'),
+    'nopunctuation' => array('html_quickform_rule_regex',    'HTML/QuickForm/Rule/Regex.php'),
+    'nonzero'       => array('html_quickform_rule_regex',    'HTML/QuickForm/Rule/Regex.php'),
+    'callback'      => array('html_quickform_rule_callback', 'HTML/QuickForm/Rule/Callback.php'),
+    'compare'       => array('html_quickform_rule_compare',  'HTML/QuickForm/Rule/Compare.php')
+);
+
+// {{{ error codes
+
+/*
+ * Error codes for the QuickForm interface, which will be mapped to textual messages
+ * in the QuickForm::errorMessage() function.  If you are to add a new error code, be
+ * sure to add the textual messages to the QuickForm::errorMessage() function as well
+ */
+
+define('QUICKFORM_OK',                      1);
+define('QUICKFORM_ERROR',                  -1);
+define('QUICKFORM_INVALID_RULE',           -2);
+define('QUICKFORM_NONEXIST_ELEMENT',       -3);
+define('QUICKFORM_INVALID_FILTER',         -4);
+define('QUICKFORM_UNREGISTERED_ELEMENT',   -5);
+define('QUICKFORM_INVALID_ELEMENT_NAME',   -6);
+define('QUICKFORM_INVALID_PROCESS',        -7);
+define('QUICKFORM_DEPRECATED',             -8);
+define('QUICKFORM_INVALID_DATASOURCE',     -9);
+
+// }}}
+
+/**
+* Create, validate and process HTML forms
+*
+* @author      Adam Daniel <adaniel1@eesus.jnj.com>
+* @author      Bertrand Mansion <bmansion@mamasam.com>
+* @version     2.0
+* @since       PHP 4.0.3pl1
+*/
+class HTML_QuickForm extends HTML_Common {
+    // {{{ properties
+
+    /**
+     * Array containing the form fields
+     * @since     1.0
+     * @var  array
+     * @access   private
+     */
+    var $_elements = array();
+
+    /**
+     * Array containing element name to index map
+     * @since     1.1
+     * @var  array
+     * @access   private
+     */
+    var $_elementIndex = array();
+
+    /**
+     * Array containing indexes of duplicate elements
+     * @since     2.10
+     * @var  array
+     * @access   private
+     */
+    var $_duplicateIndex = array();
+
+    /**
+     * Array containing required field IDs
+     * @since     1.0
+     * @var  array
+     * @access   private
+     */ 
+    var $_required = array();
+
+    /**
+     * Prefix message in javascript alert if error
+     * @since     1.0
+     * @var  string
+     * @access   public
+     */ 
+    var $_jsPrefix = 'Invalid information entered.';
+
+    /**
+     * Postfix message in javascript alert if error
+     * @since     1.0
+     * @var  string
+     * @access   public
+     */ 
+    var $_jsPostfix = 'Please correct these fields.';
+
+    /**
+     * Datasource object implementing the informal
+     * datasource protocol
+     * @since     3.3
+     * @var  object
+     * @access   private
+     */
+    var $_datasource;
+
+    /**
+     * Array of default form values
+     * @since     2.0
+     * @var  array
+     * @access   private
+     */
+    var $_defaultValues = array();
+
+    /**
+     * Array of constant form values
+     * @since     2.0
+     * @var  array
+     * @access   private
+     */
+    var $_constantValues = array();
+
+    /**
+     * Array of submitted form values
+     * @since     1.0
+     * @var  array
+     * @access   private
+     */
+    var $_submitValues = array();
+
+    /**
+     * Array of submitted form files
+     * @since     1.0
+     * @var  integer
+     * @access   public
+     */
+    var $_submitFiles = array();
+
+    /**
+     * Value for maxfilesize hidden element if form contains file input
+     * @since     1.0
+     * @var  integer
+     * @access   public
+     */
+    var $_maxFileSize = 1048576; // 1 Mb = 1048576
+
+    /**
+     * Flag to know if all fields are frozen
+     * @since     1.0
+     * @var  boolean
+     * @access   private
+     */
+    var $_freezeAll = false;
+
+    /**
+     * Array containing the form rules
+     * @since     1.0
+     * @var  array
+     * @access   private
+     */
+    var $_rules = array();
+
+    /**
+     * Form rules, global variety
+     * @var     array
+     * @access  private
+     */
+    var $_formRules = array();
+
+    /**
+     * Array containing the validation errors
+     * @since     1.0
+     * @var  array
+     * @access   private
+     */
+    var $_errors = array();
+
+    /**
+     * Note for required fields in the form
+     * @var       string
+     * @since     1.0
+     * @access    private
+     */
+    var $_requiredNote = '<span style="font-size:80%; color:#ff0000;">*</span><span style="font-size:80%;"> denotes required field</span>';
+
+    /**
+     * Whether the form was submitted
+     * @var       boolean
+     * @access    private
+     */
+    var $_flagSubmitted = false;
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * @param    string      $formName          Form's name.
+     * @param    string      $method            (optional)Form's method defaults to 'POST'
+     * @param    string      $action            (optional)Form's action
+     * @param    string      $target            (optional)Form's target defaults to '_self'
+     * @param    mixed       $attributes        (optional)Extra attributes for <form> tag
+     * @param    bool        $trackSubmit       (optional)Whether to track if the form was submitted by adding a special hidden field
+     * @access   public
+     */
+    function HTML_QuickForm($formName='', $method='post', $action='', $target='', $attributes=null, $trackSubmit = false)
+    {
+        HTML_Common::HTML_Common($attributes);
+        $method = (strtoupper($method) == 'GET') ? 'get' : 'post';
+        $action = ($action == '') ? $_SERVER['PHP_SELF'] : $action;
+        $target = empty($target) ? array() : array('target' => $target);
+        $attributes = array('action'=>$action, 'method'=>$method, 'name'=>$formName, 'id'=>$formName) + $target;
+        $this->updateAttributes($attributes);
+        if (!$trackSubmit || isset($_REQUEST['_qf__' . $formName])) {
+            if (1 == get_magic_quotes_gpc()) {
+                $this->_submitValues = $this->_recursiveFilter('stripslashes', 'get' == $method? $_GET: $_POST);
+                foreach ($_FILES as $keyFirst => $valFirst) {
+                    foreach ($valFirst as $keySecond => $valSecond) {
+                        if ('name' == $keySecond) {
+                            $this->_submitFiles[$keyFirst][$keySecond] = $this->_recursiveFilter('stripslashes', $valSecond);
+                        } else {
+                            $this->_submitFiles[$keyFirst][$keySecond] = $valSecond;
+                        }
+                    }
+                }
+            } else {
+                $this->_submitValues = 'get' == $method? $_GET: $_POST;
+                $this->_submitFiles  = $_FILES;
+            }
+            $this->_flagSubmitted = count($this->_submitValues) > 0 || count($this->_submitFiles) > 0;
+        }
+        if ($trackSubmit) {
+            unset($this->_submitValues['_qf__' . $formName]);
+            $this->addElement('hidden', '_qf__' . $formName, null);
+        }
+        if (preg_match('/^([0-9]+)([a-zA-Z]*)$/', ini_get('upload_max_filesize'), $matches)) {
+            // see http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
+            switch (strtoupper($matches['2'])) {
+                case 'G':
+                    $this->_maxFileSize = $matches['1'] * 1073741824;
+                    break;
+                case 'M':
+                    $this->_maxFileSize = $matches['1'] * 1048576;
+                    break;
+                case 'K':
+                    $this->_maxFileSize = $matches['1'] * 1024;
+                    break;
+                default:
+                    $this->_maxFileSize = $matches['1'];
+            }
+        }    
+    } // end constructor
+
+    // }}}
+    // {{{ apiVersion()
+
+    /**
+     * Returns the current API version
+     *
+     * @since     1.0
+     * @access    public
+     * @return    float
+     */
+    function apiVersion()
+    {
+        return 3.2;
+    } // end func apiVersion
+
+    // }}}
+    // {{{ registerElementType()
+
+    /**
+     * Registers a new element type
+     *
+     * @param     string    $typeName   Name of element type
+     * @param     string    $include    Include path for element type
+     * @param     string    $className  Element class name
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function registerElementType($typeName, $include, $className)
+    {
+        $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($typeName)] = array($include, $className);
+    } // end func registerElementType
+
+    // }}}
+    // {{{ registerRule()
+
+    /**
+     * Registers a new validation rule
+     *
+     * @param     string    $ruleName   Name of validation rule
+     * @param     string    $type       Either: 'regex', 'function' or 'rule' for an HTML_QuickForm_Rule object
+     * @param     string    $data1      Name of function, regular expression or HTML_QuickForm_Rule classname
+     * @param     string    $data2      Object parent of above function or HTML_QuickForm_Rule file path
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function registerRule($ruleName, $type, $data1, $data2 = null)
+    {
+        include_once('HTML/QuickForm/RuleRegistry.php');
+        $registry =& HTML_QuickForm_RuleRegistry::singleton();
+        $registry->registerRule($ruleName, $type, $data1, $data2);
+    } // end func registerRule
+
+    // }}}
+    // {{{ elementExists()
+
+    /**
+     * Returns true if element is in the form
+     *
+     * @param     string   $element         form name of element to check
+     * @since     1.0
+     * @access    public
+     * @return    boolean
+     */
+    function elementExists($element=null)
+    {
+        return isset($this->_elementIndex[$element]);
+    } // end func elementExists
+
+    // }}}
+    // {{{ setDatasource()
+
+    /**
+     * Sets a datasource object for this form object
+     *
+     * Datasource default and constant values will feed the QuickForm object if
+     * the datasource implements defaultValues() and constantValues() methods.
+     *
+     * @param     object   $datasource          datasource object implementing the informal datasource protocol
+     * @param     mixed    $defaultsFilter      string or array of filter(s) to apply to default values
+     * @param     mixed    $constantsFilter     string or array of filter(s) to apply to constants values
+     * @since     3.3
+     * @access    public
+     * @return    void
+     */
+    function setDatasource(&$datasource, $defaultsFilter = null, $constantsFilter = null)
+    {
+        if (is_object($datasource)) {
+            $this->_datasource =& $datasource;
+            if (is_callable(array($datasource, 'defaultValues'))) {
+                $this->setDefaults($datasource->defaultValues($this), $defaultsFilter);
+            }
+            if (is_callable(array($datasource, 'constantValues'))) {
+                $this->setConstants($datasource->constantValues($this), $constantsFilter);
+            }
+        } else {
+            return PEAR::raiseError(null, QUICKFORM_INVALID_DATASOURCE, null, E_USER_WARNING, "Datasource is not an object in QuickForm::setDatasource()", 'HTML_QuickForm_Error', true);
+        }
+    } // end func setDatasource
+
+    // }}}
+    // {{{ setDefaults()
+
+    /**
+     * Initializes default form values
+     *
+     * @param     array    $defaultValues       values used to fill the form
+     * @param     mixed    $filter              (optional) filter(s) to apply to all default values
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setDefaults($defaultValues = null, $filter = null)
+    {
+        if (is_array($defaultValues)) {
+            if (isset($filter)) {
+                if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) {
+                    foreach ($filter as $val) {
+                        if (!is_callable($val)) {
+                            return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true);
+                        } else {
+                            $defaultValues = $this->_recursiveFilter($val, $defaultValues);
+                        }
+                    }
+                } elseif (!is_callable($filter)) {
+                    return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true);
+                } else {
+                    $defaultValues = $this->_recursiveFilter($filter, $defaultValues);
+                }
+            }
+            $this->_defaultValues = HTML_QuickForm::arrayMerge($this->_defaultValues, $defaultValues);
+            foreach (array_keys($this->_elements) as $key) {
+                $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this);
+            }
+        }
+    } // end func setDefaults
+
+    // }}}
+    // {{{ setConstants()
+
+    /**
+     * Initializes constant form values.
+     * These values won't get overridden by POST or GET vars
+     *
+     * @param     array   $constantValues        values used to fill the form    
+     * @param     mixed    $filter              (optional) filter(s) to apply to all default values    
+     *
+     * @since     2.0
+     * @access    public
+     * @return    void
+     */
+    function setConstants($constantValues = null, $filter = null)
+    {
+        if (is_array($constantValues)) {
+            if (isset($filter)) {
+                if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) {
+                    foreach ($filter as $val) {
+                        if (!is_callable($val)) {
+                            return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true);
+                        } else {
+                            $constantValues = $this->_recursiveFilter($val, $constantValues);
+                        }
+                    }
+                } elseif (!is_callable($filter)) {
+                    return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true);
+                } else {
+                    $constantValues = $this->_recursiveFilter($filter, $constantValues);
+                }
+            }
+            $this->_constantValues = HTML_QuickForm::arrayMerge($this->_constantValues, $constantValues);
+            foreach (array_keys($this->_elements) as $key) {
+                $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this);
+            }
+        }
+    } // end func setConstants
+
+    // }}}
+    // {{{ setMaxFileSize()
+
+    /**
+     * Sets the value of MAX_FILE_SIZE hidden element
+     *
+     * @param     int    $bytes    Size in bytes
+     * @since     3.0
+     * @access    public
+     * @return    void
+     */
+    function setMaxFileSize($bytes = 0)
+    {
+        if ($bytes > 0) {
+            $this->_maxFileSize = $bytes;
+        }
+        if (!$this->elementExists('MAX_FILE_SIZE')) {
+            $this->addElement('hidden', 'MAX_FILE_SIZE', $this->_maxFileSize);
+        } else {
+            $el =& $this->getElement('MAX_FILE_SIZE');
+            $el->updateAttributes(array('value' => $this->_maxFileSize));
+        }
+    } // end func setMaxFileSize
+
+    // }}}
+    // {{{ getMaxFileSize()
+
+    /**
+     * Returns the value of MAX_FILE_SIZE hidden element
+     *
+     * @since     3.0
+     * @access    public
+     * @return    int   max file size in bytes
+     */
+    function getMaxFileSize()
+    {
+        return $this->_maxFileSize;
+    } // end func getMaxFileSize
+
+    // }}}
+    // {{{ &createElement()
+
+    /**
+     * Creates a new form element of the given type.
+     * 
+     * This method accepts variable number of parameters, their 
+     * meaning and count depending on $elementType
+     *
+     * @param     string     $elementType    type of element to add (text, textarea, file...)
+     * @since     1.0
+     * @access    public
+     * @return    object extended class of HTML_element
+     * @throws    HTML_QuickForm_Error
+     */
+    function &createElement($elementType)
+    {
+        $args    =  func_get_args();
+        $element =& HTML_QuickForm::_loadElement('createElement', $elementType, array_slice($args, 1));
+        return $element;
+    } // end func createElement
+
+    // }}}
+    // {{{ _loadElement()
+
+    /**
+     * Returns a form element of the given type
+     *
+     * @param     string   $event   event to send to newly created element ('createElement' or 'addElement')
+     * @param     string   $type    element type
+     * @param     array    $args    arguments for event
+     * @since     2.0
+     * @access    private
+     * @return    object    a new element
+     * @throws    HTML_QuickForm_Error
+     */
+    function &_loadElement($event, $type, $args)
+    {
+        $type = strtolower($type);
+        if (!HTML_QuickForm::isTypeRegistered($type)) {
+            $error = PEAR::raiseError(null, QUICKFORM_UNREGISTERED_ELEMENT, null, E_USER_WARNING, "Element '$type' does not exist in HTML_QuickForm::_loadElement()", 'HTML_QuickForm_Error', true);
+            return $error;
+        }
+        $className = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][1];
+        $includeFile = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][0];
+        include_once($includeFile);
+        $elementObject =& new $className();
+        for ($i = 0; $i < 5; $i++) {
+            if (!isset($args[$i])) {
+                $args[$i] = null;
+            }
+        }
+        $err = $elementObject->onQuickFormEvent($event, $args, $this);
+        if ($err !== true) {
+            return $err;
+        }
+        return $elementObject;
+    } // end func _loadElement
+
+    // }}}
+    // {{{ addElement()
+
+    /**
+     * Adds an element into the form
+     * 
+     * If $element is a string representing element type, then this 
+     * method accepts variable number of parameters, their meaning 
+     * and count depending on $element
+     *
+     * @param    mixed      $element        element object or type of element to add (text, textarea, file...)
+     * @since    1.0
+     * @return   object     reference to element
+     * @access   public
+     * @throws   HTML_QuickForm_Error
+     */
+    function &addElement($element)
+    {
+        if (is_object($element) && is_subclass_of($element, 'html_quickform_element')) {
+           $elementObject = &$element;
+           $elementObject->onQuickFormEvent('updateValue', null, $this);
+        } else {
+            $args = func_get_args();
+            $elementObject =& $this->_loadElement('addElement', $element, array_slice($args, 1));
+            if (PEAR::isError($elementObject)) {
+                return $elementObject;
+            }
+        }
+        $elementName = $elementObject->getName();
+
+        // Add the element if it is not an incompatible duplicate
+        if (!empty($elementName) && isset($this->_elementIndex[$elementName])) {
+            if ($this->_elements[$this->_elementIndex[$elementName]]->getType() ==
+                $elementObject->getType()) {
+                $this->_elements[] =& $elementObject;
+                $elKeys = array_keys($this->_elements);
+                $this->_duplicateIndex[$elementName][] = end($elKeys);
+            } else {
+                $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::addElement()", 'HTML_QuickForm_Error', true);
+                return $error;
+            }
+        } else {
+            $this->_elements[] =& $elementObject;
+            $elKeys = array_keys($this->_elements);
+            $this->_elementIndex[$elementName] = end($elKeys);
+        }
+        if ($this->_freezeAll) {
+            $elementObject->freeze();
+        }
+
+        return $elementObject;
+    } // end func addElement
+    
+    // }}}
+    // {{{ insertElementBefore()
+
+   /**
+    * Inserts a new element right before the other element
+    *
+    * Warning: it is not possible to check whether the $element is already
+    * added to the form, therefore if you want to move the existing form
+    * element to a new position, you'll have to use removeElement():
+    * $form->insertElementBefore($form->removeElement('foo', false), 'bar');
+    *
+    * @access   public
+    * @since    3.2.4
+    * @param    object  HTML_QuickForm_element  Element to insert
+    * @param    string  Name of the element before which the new one is inserted
+    * @return   object  HTML_QuickForm_element  reference to inserted element
+    * @throws   HTML_QuickForm_Error
+    */
+    function &insertElementBefore(&$element, $nameAfter)
+    {
+        if (!empty($this->_duplicateIndex[$nameAfter])) {
+            $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, 'Several elements named "' . $nameAfter . '" exist in HTML_QuickForm::insertElementBefore().', 'HTML_QuickForm_Error', true);
+            return $error;
+        } elseif (!$this->elementExists($nameAfter)) {
+            $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$nameAfter' does not exist in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true);
+            return $error;
+        }
+        $elementName = $element->getName();
+        $targetIdx   = $this->_elementIndex[$nameAfter];
+        $duplicate   = false;
+        // Like in addElement(), check that it's not an incompatible duplicate
+        if (!empty($elementName) && isset($this->_elementIndex[$elementName])) {
+            if ($this->_elements[$this->_elementIndex[$elementName]]->getType() != $element->getType()) {
+                $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true);
+                return $error;
+            }
+            $duplicate = true;
+        }
+        // Move all the elements after added back one place, reindex _elementIndex and/or _duplicateIndex
+        $elKeys = array_keys($this->_elements);
+        for ($i = end($elKeys); $i >= $targetIdx; $i--) {
+            if (isset($this->_elements[$i])) {
+                $currentName = $this->_elements[$i]->getName();
+                $this->_elements[$i + 1] =& $this->_elements[$i];
+                if ($this->_elementIndex[$currentName] == $i) {
+                    $this->_elementIndex[$currentName] = $i + 1;
+                } else {
+                    $dupIdx = array_search($i, $this->_duplicateIndex[$currentName]);
+                    $this->_duplicateIndex[$currentName][$dupIdx] = $i + 1;
+                }
+                unset($this->_elements[$i]);
+            }
+        }
+        // Put the element in place finally
+        $this->_elements[$targetIdx] =& $element;
+        if (!$duplicate) {
+            $this->_elementIndex[$elementName] = $targetIdx;
+        } else {
+            $this->_duplicateIndex[$elementName][] = $targetIdx;
+        }
+        $element->onQuickFormEvent('updateValue', null, $this);
+        if ($this->_freezeAll) {
+            $element->freeze();
+        }
+        // If not done, the elements will appear in reverse order
+        ksort($this->_elements);
+        return $element;
+    }
+
+    // }}}
+    // {{{ addGroup()
+
+    /**
+     * Adds an element group
+     * @param    array      $elements       array of elements composing the group
+     * @param    string     $name           (optional)group name
+     * @param    string     $groupLabel     (optional)group label
+     * @param    string     $separator      (optional)string to separate elements
+     * @param    string     $appendName     (optional)specify whether the group name should be
+     *                                      used in the form element name ex: group[element]
+     * @return   object     reference to added group of elements
+     * @since    2.8
+     * @access   public
+     * @throws   PEAR_Error
+     */
+    function &addGroup($elements, $name=null, $groupLabel='', $separator=null, $appendName = true)
+    {
+        static $anonGroups = 1;
+
+        if (0 == strlen($name)) {
+            $name       = 'qf_group_' . $anonGroups++;
+            $appendName = false;
+        }
+        $group =& $this->addElement('group', $name, $groupLabel, $elements, $separator, $appendName);
+        return $group;
+    } // end func addGroup
+    
+    // }}}
+    // {{{ &getElement()
+
+    /**
+     * Returns a reference to the element
+     *
+     * @param     string     $element    Element name
+     * @since     2.0
+     * @access    public
+     * @return    object     reference to element
+     * @throws    HTML_QuickForm_Error
+     */
+    function &getElement($element)
+    {
+        if (isset($this->_elementIndex[$element])) {
+            return $this->_elements[$this->_elementIndex[$element]];
+        } else {
+            $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElement()", 'HTML_QuickForm_Error', true);
+            return $error;
+        }
+    } // end func getElement
+
+    // }}}
+    // {{{ &getElementValue()
+
+    /**
+     * Returns the element's raw value
+     * 
+     * This returns the value as submitted by the form (not filtered) 
+     * or set via setDefaults() or setConstants()
+     *
+     * @param     string     $element    Element name
+     * @since     2.0
+     * @access    public
+     * @return    mixed     element value
+     * @throws    HTML_QuickForm_Error
+     */
+    function &getElementValue($element)
+    {
+        if (!isset($this->_elementIndex[$element])) {
+            $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElementValue()", 'HTML_QuickForm_Error', true);
+            return $error;
+        }
+        $value = $this->_elements[$this->_elementIndex[$element]]->getValue();
+        if (isset($this->_duplicateIndex[$element])) {
+            foreach ($this->_duplicateIndex[$element] as $index) {
+                if (null !== ($v = $this->_elements[$index]->getValue())) {
+                    if (is_array($value)) {
+                        $value[] = $v;
+                    } else {
+                        $value = (null === $value)? $v: array($value, $v);
+                    }
+                }
+            }
+        }
+        return $value;
+    } // end func getElementValue
+
+    // }}}
+    // {{{ getSubmitValue()
+
+    /**
+     * Returns the elements value after submit and filter
+     *
+     * @param     string     Element name
+     * @since     2.0
+     * @access    public
+     * @return    mixed     submitted element value or null if not set
+     */    
+    function getSubmitValue($elementName)
+    {
+        $value = null;
+        if (isset($this->_submitValues[$elementName]) || isset($this->_submitFiles[$elementName])) {
+            $value = isset($this->_submitValues[$elementName])? $this->_submitValues[$elementName]: array();
+            if (is_array($value) && isset($this->_submitFiles[$elementName])) {
+                foreach ($this->_submitFiles[$elementName] as $k => $v) {
+                    $value = HTML_QuickForm::arrayMerge($value, $this->_reindexFiles($this->_submitFiles[$elementName][$k], $k));
+                }
+            }
+
+        } elseif ('file' == $this->getElementType($elementName)) {
+            return $this->getElementValue($elementName);
+
+        } elseif (false !== ($pos = strpos($elementName, '['))) {
+            $base = substr($elementName, 0, $pos);
+            $idx  = "['" . str_replace(array(']', '['), array('', "']['"), substr($elementName, $pos + 1, -1)) . "']";
+            if (isset($this->_submitValues[$base])) {
+                $value = eval("return (isset(\$this->_submitValues['{$base}']{$idx})) ? \$this->_submitValues['{$base}']{$idx} : null;");
+            }
+
+            if ((is_array($value) || null === $value) && isset($this->_submitFiles[$base])) {
+                $props = array('name', 'type', 'size', 'tmp_name', 'error');
+                $code  = "if (!isset(\$this->_submitFiles['{$base}']['name']{$idx})) {\n" .
+                         "    return null;\n" .
+                         "} else {\n" .
+                         "    \$v = array();\n";
+                foreach ($props as $prop) {
+                    $code .= "    \$v = HTML_QuickForm::arrayMerge(\$v, \$this->_reindexFiles(\$this->_submitFiles['{$base}']['{$prop}']{$idx}, '{$prop}'));\n";
+                }
+                $fileValue = eval($code . "    return \$v;\n}\n");
+                if (null !== $fileValue) {
+                    $value = null === $value? $fileValue: HTML_QuickForm::arrayMerge($value, $fileValue);
+                }
+            }
+        }
+        
+        // This is only supposed to work for groups with appendName = false
+        if (null === $value && 'group' == $this->getElementType($elementName)) {
+            $group    =& $this->getElement($elementName);
+            $elements =& $group->getElements();
+            foreach (array_keys($elements) as $key) {
+                $name = $group->getElementName($key);
+                // prevent endless recursion in case of radios and such
+                if ($name != $elementName) {
+                    if (null !== ($v = $this->getSubmitValue($name))) {
+                        $value[$name] = $v;
+                    }
+                }
+            }
+        }
+        return $value;
+    } // end func getSubmitValue
+
+    // }}}
+    // {{{ _reindexFiles()
+
+   /**
+    * A helper function to change the indexes in $_FILES array
+    *
+    * @param  mixed   Some value from the $_FILES array
+    * @param  string  The key from the $_FILES array that should be appended
+    * @return array
+    */
+    function _reindexFiles($value, $key)
+    {
+        if (!is_array($value)) {
+            return array($key => $value);
+        } else {
+            $ret = array();
+            foreach ($value as $k => $v) {
+                $ret[$k] = $this->_reindexFiles($v, $key);
+            }
+            return $ret;
+        }
+    }
+
+    // }}}
+    // {{{ getElementError()
+
+    /**
+     * Returns error corresponding to validated element
+     *
+     * @param     string    $element        Name of form element to check
+     * @since     1.0
+     * @access    public
+     * @return    string    error message corresponding to checked element
+     */
+    function getElementError($element)
+    {
+        if (isset($this->_errors[$element])) {
+            return $this->_errors[$element];
+        }
+    } // end func getElementError
+    
+    // }}}
+    // {{{ setElementError()
+
+    /**
+     * Set error message for a form element
+     *
+     * @param     string    $element    Name of form element to set error for
+     * @param     string    $message    Error message, if empty then removes the current error message
+     * @since     1.0       
+     * @access    public
+     * @return    void
+     */
+    function setElementError($element, $message = null)
+    {
+        if (!empty($message)) {
+            $this->_errors[$element] = $message;
+        } else {
+            unset($this->_errors[$element]);
+        }
+    } // end func setElementError
+         
+     // }}}
+     // {{{ getElementType()
+
+     /**
+      * Returns the type of the given element
+      *
+      * @param      string    $element    Name of form element
+      * @since      1.1
+      * @access     public
+      * @return     string    Type of the element, false if the element is not found
+      */
+     function getElementType($element)
+     {
+         if (isset($this->_elementIndex[$element])) {
+             return $this->_elements[$this->_elementIndex[$element]]->getType();
+         }
+         return false;
+     } // end func getElementType
+
+     // }}}
+     // {{{ updateElementAttr()
+
+    /**
+     * Updates Attributes for one or more elements
+     *
+     * @param      mixed    $elements   Array of element names/objects or string of elements to be updated
+     * @param      mixed    $attrs      Array or sting of html attributes
+     * @since      2.10
+     * @access     public
+     * @return     void
+     */
+    function updateElementAttr($elements, $attrs)
+    {
+        if (is_string($elements)) {
+            $elements = split('[ ]?,[ ]?', $elements);
+        }
+        foreach (array_keys($elements) as $key) {
+            if (is_object($elements[$key]) && is_a($elements[$key], 'HTML_QuickForm_element')) {
+                $elements[$key]->updateAttributes($attrs);
+            } elseif (isset($this->_elementIndex[$elements[$key]])) {
+                $this->_elements[$this->_elementIndex[$elements[$key]]]->updateAttributes($attrs);
+                if (isset($this->_duplicateIndex[$elements[$key]])) {
+                    foreach ($this->_duplicateIndex[$elements[$key]] as $index) {
+                        $this->_elements[$index]->updateAttributes($attrs);
+                    }
+                }
+            }
+        }
+    } // end func updateElementAttr
+
+    // }}}
+    // {{{ removeElement()
+
+    /**
+     * Removes an element
+     *
+     * The method "unlinks" an element from the form, returning the reference
+     * to the element object. If several elements named $elementName exist, 
+     * it removes the first one, leaving the others intact.
+     * 
+     * @param string    $elementName The element name
+     * @param boolean   $removeRules True if rules for this element are to be removed too                     
+     * @access public
+     * @since 2.0
+     * @return object HTML_QuickForm_element    a reference to the removed element
+     * @throws HTML_QuickForm_Error
+     */
+    function &removeElement($elementName, $removeRules = true)
+    {
+        if (!isset($this->_elementIndex[$elementName])) {
+            $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$elementName' does not exist in HTML_QuickForm::removeElement()", 'HTML_QuickForm_Error', true);
+            return $error;
+        }
+        $el =& $this->_elements[$this->_elementIndex[$elementName]];
+        unset($this->_elements[$this->_elementIndex[$elementName]]);
+        if (empty($this->_duplicateIndex[$elementName])) {
+            unset($this->_elementIndex[$elementName]);
+        } else {
+            $this->_elementIndex[$elementName] = array_shift($this->_duplicateIndex[$elementName]);
+        }
+        if ($removeRules) {
+            unset($this->_rules[$elementName], $this->_errors[$elementName]);
+        }
+        return $el;
+    } // end func removeElement
+
+    // }}}
+    // {{{ addRule()
+
+    /**
+     * Adds a validation rule for the given field
+     *
+     * If the element is in fact a group, it will be considered as a whole.
+     * To validate grouped elements as separated entities, 
+     * use addGroupRule instead of addRule.
+     *
+     * @param    string     $element       Form element name
+     * @param    string     $message       Message to display for invalid data
+     * @param    string     $type          Rule type, use getRegisteredRules() to get types
+     * @param    string     $format        (optional)Required for extra rule data
+     * @param    string     $validation    (optional)Where to perform validation: "server", "client"
+     * @param    boolean    $reset         Client-side validation: reset the form element to its original value if there is an error?
+     * @param    boolean    $force         Force the rule to be applied, even if the target form element does not exist
+     * @since    1.0
+     * @access   public
+     * @throws   HTML_QuickForm_Error
+     */
+    function addRule($element, $message, $type, $format=null, $validation='server', $reset = false, $force = false)
+    {
+        if (!$force) {
+            if (!is_array($element) && !$this->elementExists($element)) {
+                return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true);
+            } elseif (is_array($element)) {
+                foreach ($element as $el) {
+                    if (!$this->elementExists($el)) {
+                        return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$el' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true);
+                    }
+                }
+            }
+        }
+        if (false === ($newName = $this->isRuleRegistered($type, true))) {
+            return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true);
+        } elseif (is_string($newName)) {
+            $type = $newName;
+        }
+        if (is_array($element)) {
+            $dependent = $element;
+            $element   = array_shift($dependent);
+        } else {
+            $dependent = null;
+        }
+        if ($type == 'required' || $type == 'uploadedfile') {
+            $this->_required[] = $element;
+        }
+        if (!isset($this->_rules[$element])) {
+            $this->_rules[$element] = array();
+        }
+        if ($validation == 'client') {
+            $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);'));
+        }
+        $this->_rules[$element][] = array(
+            'type'        => $type,
+            'format'      => $format,
+            'message'     => $message,
+            'validation'  => $validation,
+            'reset'       => $reset,
+            'dependent'   => $dependent
+        );
+    } // end func addRule
+
+    // }}}
+    // {{{ addGroupRule()
+
+    /**
+     * Adds a validation rule for the given group of elements
+     *
+     * Only groups with a name can be assigned a validation rule
+     * Use addGroupRule when you need to validate elements inside the group.
+     * Use addRule if you need to validate the group as a whole. In this case,
+     * the same rule will be applied to all elements in the group.
+     * Use addRule if you need to validate the group against a function.
+     *
+     * @param    string     $group         Form group name
+     * @param    mixed      $arg1          Array for multiple elements or error message string for one element
+     * @param    string     $type          (optional)Rule type use getRegisteredRules() to get types
+     * @param    string     $format        (optional)Required for extra rule data
+     * @param    int        $howmany       (optional)How many valid elements should be in the group
+     * @param    string     $validation    (optional)Where to perform validation: "server", "client"
+     * @param    bool       $reset         Client-side: whether to reset the element's value to its original state if validation failed.
+     * @since    2.5
+     * @access   public
+     * @throws   HTML_QuickForm_Error
+     */
+    function addGroupRule($group, $arg1, $type='', $format=null, $howmany=0, $validation = 'server', $reset = false)
+    {
+        if (!$this->elementExists($group)) {
+            return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Group '$group' does not exist in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true);
+        }
+
+        $groupObj =& $this->getElement($group);
+        if (is_array($arg1)) {
+            $required = 0;
+            foreach ($arg1 as $elementIndex => $rules) {
+                $elementName = $groupObj->getElementName($elementIndex);
+                foreach ($rules as $rule) {
+                    $format = (isset($rule[2])) ? $rule[2] : null;
+                    $validation = (isset($rule[3]) && 'client' == $rule[3])? 'client': 'server';
+                    $reset = isset($rule[4]) && $rule[4];
+                    $type = $rule[1];
+                    if (false === ($newName = $this->isRuleRegistered($type, true))) {
+                        return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true);
+                    } elseif (is_string($newName)) {
+                        $type = $newName;
+                    }
+
+                    $this->_rules[$elementName][] = array(
+                                                        'type'        => $type,
+                                                        'format'      => $format, 
+                                                        'message'     => $rule[0],
+                                                        'validation'  => $validation,
+                                                        'reset'       => $reset,
+                                                        'group'       => $group);
+
+                    if ('required' == $type || 'uploadedfile' == $type) {
+                        $groupObj->_required[] = $elementName;
+                        $this->_required[] = $elementName;
+                        $required++;
+                    }
+                    if ('client' == $validation) {
+                        $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);'));
+                    }
+                }
+            }
+            if ($required > 0 && count($groupObj->getElements()) == $required) {
+                $this->_required[] = $group;
+            }
+        } elseif (is_string($arg1)) {
+            if (false === ($newName = $this->isRuleRegistered($type, true))) {
+                return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true);
+            } elseif (is_string($newName)) {
+                $type = $newName;
+            }
+
+            // addGroupRule() should also handle <select multiple>
+            if (is_a($groupObj, 'html_quickform_group')) {
+                // Radios need to be handled differently when required
+                if ($type == 'required' && $groupObj->getGroupType() == 'radio') {
+                    $howmany = ($howmany == 0) ? 1 : $howmany;
+                } else {
+                    $howmany = ($howmany == 0) ? count($groupObj->getElements()) : $howmany;
+                }
+            }
+
+            $this->_rules[$group][] = array('type'       => $type,
+                                            'format'     => $format, 
+                                            'message'    => $arg1,
+                                            'validation' => $validation,
+                                            'howmany'    => $howmany,
+                                            'reset'      => $reset);
+            if ($type == 'required') {
+                $this->_required[] = $group;
+            }
+            if ($validation == 'client') {
+                $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);'));
+            }
+        }
+    } // end func addGroupRule
+
+    // }}}
+    // {{{ addFormRule()
+
+   /**
+    * Adds a global validation rule 
+    * 
+    * This should be used when for a rule involving several fields or if
+    * you want to use some completely custom validation for your form.
+    * The rule function/method should return true in case of successful 
+    * validation and array('element name' => 'error') when there were errors.
+    * 
+    * @access   public
+    * @param    mixed   Callback, either function name or array(&$object, 'method')
+    * @throws   HTML_QuickForm_Error
+    */
+    function addFormRule($rule)
+    {
+        if (!is_callable($rule)) {
+            return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, 'Callback function does not exist in HTML_QuickForm::addFormRule()', 'HTML_QuickForm_Error', true);
+        }
+        $this->_formRules[] = $rule;
+    }
+    
+    // }}}
+    // {{{ applyFilter()
+
+    /**
+     * Applies a data filter for the given field(s)
+     *
+     * @param    mixed     $element       Form element name or array of such names
+     * @param    mixed     $filter        Callback, either function name or array(&$object, 'method')
+     * @since    2.0
+     * @access   public
+     */
+    function applyFilter($element, $filter)
+    {
+        if (!is_callable($filter)) {
+            return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::applyFilter()", 'HTML_QuickForm_Error', true);
+        }
+        if ($element == '__ALL__') {
+            $this->_submitValues = $this->_recursiveFilter($filter, $this->_submitValues);
+        } else {
+            if (!is_array($element)) {
+                $element = array($element);
+            }
+            foreach ($element as $elName) {
+                $value = $this->getSubmitValue($elName);
+                if (null !== $value) {
+                    if (false === strpos($elName, '[')) {
+                        $this->_submitValues[$elName] = $this->_recursiveFilter($filter, $value);
+                    } else {
+                        $idx  = "['" . str_replace(array(']', '['), array('', "']['"), $elName) . "']";
+                        eval("\$this->_submitValues{$idx} = \$this->_recursiveFilter(\$filter, \$value);");
+                    }
+                }
+            }
+        }
+    } // end func applyFilter
+
+    // }}}
+    // {{{ _recursiveFilter()
+
+    /**
+     * Recursively apply a filter function
+     *
+     * @param     string   $filter    filter to apply
+     * @param     mixed    $value     submitted values
+     * @since     2.0
+     * @access    private
+     * @return    cleaned values
+     */
+    function _recursiveFilter($filter, $value)
+    {
+        if (is_array($value)) {
+            $cleanValues = array();
+            foreach ($value as $k => $v) {
+                $cleanValues[$k] = $this->_recursiveFilter($filter, $v);
+            }
+            return $cleanValues;
+        } else {
+            return call_user_func($filter, $value);
+        }
+    } // end func _recursiveFilter
+
+    // }}}
+    // {{{ arrayMerge()
+
+   /**
+    * Merges two arrays
+    *
+    * Merges two array like the PHP function array_merge but recursively.
+    * The main difference is that existing keys will not be renumbered
+    * if they are integers.
+    *
+    * @access   puplic
+    * @param    array   $a  original array
+    * @param    array   $b  array which will be merged into first one
+    * @return   array   merged array
+    */
+    function arrayMerge($a, $b)
+    {
+        foreach ($b as $k => $v) {
+            if (is_array($v)) {
+                if (isset($a[$k]) && !is_array($a[$k])) {
+                    $a[$k] = $v;
+                } else {
+                    if (!isset($a[$k])) {
+                        $a[$k] = array();
+                    }
+                    $a[$k] = HTML_QuickForm::arrayMerge($a[$k], $v);
+                }
+            } else {
+                $a[$k] = $v;
+            }
+        }
+        return $a;
+    } // end func arrayMerge
+
+    // }}}
+    // {{{ isTypeRegistered()
+
+    /**
+     * Returns whether or not the form element type is supported
+     *
+     * @param     string   $type     Form element type
+     * @since     1.0
+     * @access    public
+     * @return    boolean
+     */
+    function isTypeRegistered($type)
+    {
+        return isset($GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($type)]);
+    } // end func isTypeRegistered
+
+    // }}}
+    // {{{ getRegisteredTypes()
+
+    /**
+     * Returns an array of registered element types
+     *
+     * @since     1.0
+     * @access    public
+     * @return    array
+     */
+    function getRegisteredTypes()
+    {
+        return array_keys($GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES']);
+    } // end func getRegisteredTypes
+
+    // }}}
+    // {{{ isRuleRegistered()
+
+    /**
+     * Returns whether or not the given rule is supported
+     *
+     * @param     string   $name    Validation rule name
+     * @param     bool     Whether to automatically register subclasses of HTML_QuickForm_Rule
+     * @since     1.0
+     * @access    public
+     * @return    mixed    true if previously registered, false if not, new rule name if auto-registering worked
+     */
+    function isRuleRegistered($name, $autoRegister = false)
+    {
+        if (is_scalar($name) && isset($GLOBALS['_HTML_QuickForm_registered_rules'][$name])) {
+            return true;
+        } elseif (!$autoRegister) {
+            return false;
+        }
+        // automatically register the rule if requested
+        include_once 'HTML/QuickForm/RuleRegistry.php';
+        $ruleName = false;
+        if (is_object($name) && is_a($name, 'html_quickform_rule')) {
+            $ruleName = !empty($name->name)? $name->name: strtolower(get_class($name));
+        } elseif (is_string($name) && class_exists($name)) {
+            $parent = strtolower($name);
+            do {
+                if ('html_quickform_rule' == strtolower($parent)) {
+                    $ruleName = strtolower($name);
+                    break;
+                }
+            } while ($parent = get_parent_class($parent));
+        }
+        if ($ruleName) {
+            $registry =& HTML_QuickForm_RuleRegistry::singleton();
+            $registry->registerRule($ruleName, null, $name);
+        }
+        return $ruleName;
+    } // end func isRuleRegistered
+
+    // }}}
+    // {{{ getRegisteredRules()
+
+    /**
+     * Returns an array of registered validation rules
+     *
+     * @since     1.0
+     * @access    public
+     * @return    array
+     */
+    function getRegisteredRules()
+    {
+        return array_keys($GLOBALS['_HTML_QuickForm_registered_rules']);
+    } // end func getRegisteredRules
+
+    // }}}
+    // {{{ isElementRequired()
+
+    /**
+     * Returns whether or not the form element is required
+     *
+     * @param     string   $element     Form element name
+     * @since     1.0
+     * @access    public
+     * @return    boolean
+     */
+    function isElementRequired($element)
+    {
+        return in_array($element, $this->_required, true);
+    } // end func isElementRequired
+
+    // }}}
+    // {{{ isElementFrozen()
+
+    /**
+     * Returns whether or not the form element is frozen
+     *
+     * @param     string   $element     Form element name
+     * @since     1.0
+     * @access    public
+     * @return    boolean
+     */
+    function isElementFrozen($element)
+    {
+         if (isset($this->_elementIndex[$element])) {
+             return $this->_elements[$this->_elementIndex[$element]]->isFrozen();
+         }
+         return false;
+    } // end func isElementFrozen
+
+    // }}}
+    // {{{ setJsWarnings()
+
+    /**
+     * Sets JavaScript warning messages
+     *
+     * @param     string   $pref        Prefix warning
+     * @param     string   $post        Postfix warning
+     * @since     1.1
+     * @access    public
+     * @return    void
+     */
+    function setJsWarnings($pref, $post)
+    {
+        $this->_jsPrefix = $pref;
+        $this->_jsPostfix = $post;
+    } // end func setJsWarnings
+    
+    // }}}
+    // {{{ setRequiredNote()
+
+    /**
+     * Sets required-note
+     *
+     * @param     string   $note        Message indicating some elements are required
+     * @since     1.1
+     * @access    public
+     * @return    void
+     */
+    function setRequiredNote($note)
+    {
+        $this->_requiredNote = $note;
+    } // end func setRequiredNote
+
+    // }}}
+    // {{{ getRequiredNote()
+
+    /**
+     * Returns the required note
+     *
+     * @since     2.0
+     * @access    public
+     * @return    string
+     */
+    function getRequiredNote()
+    {
+        return $this->_requiredNote;
+    } // end func getRequiredNote
+
+    // }}}
+    // {{{ validate()
+
+    /**
+     * Performs the server side validation
+     * @access    public
+     * @since     1.0
+     * @return    boolean   true if no error found
+     */
+    function validate()
+    {
+        if (count($this->_rules) == 0 && count($this->_formRules) == 0 && 
+            $this->isSubmitted()) {
+            return (0 == count($this->_errors));
+        } elseif (!$this->isSubmitted()) {
+            return false;
+        }
+
+        include_once('HTML/QuickForm/RuleRegistry.php');
+        $registry =& HTML_QuickForm_RuleRegistry::singleton();
+
+        foreach ($this->_rules as $target => $rules) {
+            $submitValue = $this->getSubmitValue($target);
+
+            foreach ($rules as $rule) {
+                if ((isset($rule['group']) && isset($this->_errors[$rule['group']])) ||
+                     isset($this->_errors[$target])) {
+                    continue 2;
+                }
+                // If element is not required and is empty, we shouldn't validate it
+                if (!$this->isElementRequired($target)) {
+                    if (!isset($submitValue) || '' == $submitValue) {
+                        continue 2;
+                    // Fix for bug #3501: we shouldn't validate not uploaded files, either.
+                    // Unfortunately, we can't just use $element->isUploadedFile() since
+                    // the element in question can be buried in group. Thus this hack.
+                    } elseif (is_array($submitValue)) {
+                        if (false === ($pos = strpos($target, '['))) {
+                            $isUpload = !empty($this->_submitFiles[$target]);
+                        } else {
+                            $base = substr($target, 0, $pos);
+                            $idx  = "['" . str_replace(array(']', '['), array('', "']['"), substr($target, $pos + 1, -1)) . "']";
+                            eval("\$isUpload = isset(\$this->_submitFiles['{$base}']['name']{$idx});");
+                        }
+                        if ($isUpload && (!isset($submitValue['error']) || 0 != $submitValue['error'])) {
+                            continue 2;
+                        }
+                    }
+                }
+                if (isset($rule['dependent']) && is_array($rule['dependent'])) {
+                    $values = array($submitValue);
+                    foreach ($rule['dependent'] as $elName) {
+                        $values[] = $this->getSubmitValue($elName);
+                    }
+                    $result = $registry->validate($rule['type'], $values, $rule['format'], true);
+                } elseif (is_array($submitValue) && !isset($rule['howmany'])) {
+                    $result = $registry->validate($rule['type'], $submitValue, $rule['format'], true);
+                } else {
+                    $result = $registry->validate($rule['type'], $submitValue, $rule['format'], false);
+                }
+
+                if (!$result || (!empty($rule['howmany']) && $rule['howmany'] > (int)$result)) {
+                    if (isset($rule['group'])) {
+                        $this->_errors[$rule['group']] = $rule['message'];
+                    } else {
+                        $this->_errors[$target] = $rule['message'];
+                    }
+                }
+            }
+        }
+
+        // process the global rules now
+        foreach ($this->_formRules as $rule) {
+            if (true !== ($res = call_user_func($rule, $this->_submitValues, $this->_submitFiles))) {
+                if (is_array($res)) {
+                    $this->_errors += $res;
+                } else {
+                    return PEAR::raiseError(null, QUICKFORM_ERROR, null, E_USER_WARNING, 'Form rule callback returned invalid value in HTML_QuickForm::validate()', 'HTML_QuickForm_Error', true);
+                }
+            }
+        }
+
+        return (0 == count($this->_errors));
+    } // end func validate
+
+    // }}}
+    // {{{ freeze()
+
+    /**
+     * Displays elements without HTML input tags
+     *
+     * @param    mixed   $elementList       array or string of element(s) to be frozen
+     * @since     1.0
+     * @access   public
+     * @throws   HTML_QuickForm_Error
+     */
+    function freeze($elementList=null)
+    {
+        if (!isset($elementList)) {
+            $this->_freezeAll = true;
+            $elementList = array();
+        } else {
+            if (!is_array($elementList)) {
+                $elementList = preg_split('/[ ]*,[ ]*/', $elementList);
+            }
+            $elementList = array_flip($elementList);
+        }
+
+        foreach (array_keys($this->_elements) as $key) {
+            $name = $this->_elements[$key]->getName();
+            if ($this->_freezeAll || isset($elementList[$name])) {
+                $this->_elements[$key]->freeze();
+                unset($elementList[$name]);
+            }
+        }
+
+        if (!empty($elementList)) {
+            return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Nonexistant element(s): '" . implode("', '", array_keys($elementList)) . "' in HTML_QuickForm::freeze()", 'HTML_QuickForm_Error', true);
+        }
+        return true;
+    } // end func freeze
+        
+    // }}}
+    // {{{ isFrozen()
+
+    /**
+     * Returns whether or not the whole form is frozen
+     *
+     * @since     3.0
+     * @access    public
+     * @return    boolean
+     */
+    function isFrozen()
+    {
+         return $this->_freezeAll;
+    } // end func isFrozen
+
+    // }}}
+    // {{{ process()
+
+    /**
+     * Performs the form data processing
+     *
+     * @param    mixed     $callback        Callback, either function name or array(&$object, 'method')
+     * @param    bool      $mergeFiles      Whether uploaded files should be processed too
+     * @since    1.0
+     * @access   public
+     * @throws   HTML_QuickForm_Error
+     */
+    function process($callback, $mergeFiles = true)
+    {
+        if (!is_callable($callback)) {
+            return PEAR::raiseError(null, QUICKFORM_INVALID_PROCESS, null, E_USER_WARNING, "Callback function does not exist in QuickForm::process()", 'HTML_QuickForm_Error', true);
+        }
+        $values = ($mergeFiles === true) ? HTML_QuickForm::arrayMerge($this->_submitValues, $this->_submitFiles) : $this->_submitValues;
+        return call_user_func($callback, $values);
+    } // end func process
+
+    // }}}
+    // {{{ accept()
+
+   /**
+    * Accepts a renderer
+    *
+    * @param object     An HTML_QuickForm_Renderer object
+    * @since 3.0
+    * @access public
+    * @return void
+    */
+    function accept(&$renderer)
+    {
+        $renderer->startForm($this);
+        foreach (array_keys($this->_elements) as $key) {
+            $element =& $this->_elements[$key];
+            $elementName = $element->getName();
+            $required    = ($this->isElementRequired($elementName) && !$element->isFrozen());
+            $error       = $this->getElementError($elementName);
+            $element->accept($renderer, $required, $error);
+        }
+        $renderer->finishForm($this);
+    } // end func accept
+
+    // }}}
+    // {{{ defaultRenderer()
+
+   /**
+    * Returns a reference to default renderer object
+    *
+    * @access public
+    * @since 3.0
+    * @return object a default renderer object
+    */
+    function &defaultRenderer()
+    {
+        if (!isset($GLOBALS['_HTML_QuickForm_default_renderer'])) {
+            include_once('HTML/QuickForm/Renderer/Default.php');
+            $GLOBALS['_HTML_QuickForm_default_renderer'] =& new HTML_QuickForm_Renderer_Default();
+        }
+        return $GLOBALS['_HTML_QuickForm_default_renderer'];
+    } // end func defaultRenderer
+
+    // }}}
+    // {{{ toHtml ()
+
+    /**
+     * Returns an HTML version of the form
+     *
+     * @param string $in_data (optional) Any extra data to insert right
+     *               before form is rendered.  Useful when using templates.
+     *
+     * @return   string     Html version of the form
+     * @since     1.0
+     * @access   public
+     */
+    function toHtml ($in_data = null)
+    {
+        if (!is_null($in_data)) {
+            $this->addElement('html', $in_data);
+        }
+        $renderer =& $this->defaultRenderer();
+        $this->accept($renderer);
+        return $renderer->toHtml();
+    } // end func toHtml
+
+    // }}}
+    // {{{ getValidationScript()
+
+    /**
+     * Returns the client side validation script
+     *
+     * @since     2.0
+     * @access    public
+     * @return    string    Javascript to perform validation, empty string if no 'client' rules were added
+     */
+    function getValidationScript()
+    {
+        if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) {
+            return '';
+        }
+
+        include_once('HTML/QuickForm/RuleRegistry.php');
+        $registry =& HTML_QuickForm_RuleRegistry::singleton();
+        $test = array();
+        $js_escape = array(
+            "\r"    => '\r',
+            "\n"    => '\n',
+            "\t"    => '\t',
+            "'"     => "\\'",
+            '"'     => '\"',
+            '\\'    => '\\\\'
+        );
+
+        foreach ($this->_rules as $elementName => $rules) {
+            foreach ($rules as $rule) {
+                if ('client' == $rule['validation']) {
+                    unset($element);
+
+                    $dependent  = isset($rule['dependent']) && is_array($rule['dependent']);
+                    $rule['message'] = strtr($rule['message'], $js_escape);
+
+                    if (isset($rule['group'])) {
+                        $group    =& $this->getElement($rule['group']);
+                        // No JavaScript validation for frozen elements
+                        if ($group->isFrozen()) {
+                            continue 2;
+                        }
+                        $elements =& $group->getElements();
+                        foreach (array_keys($elements) as $key) {
+                            if ($elementName == $group->getElementName($key)) {
+                                $element =& $elements[$key];
+                                break;
+                            }
+                        }
+                    } elseif ($dependent) {
+                        $element   =  array();
+                        $element[] =& $this->getElement($elementName);
+                        foreach ($rule['dependent'] as $elName) {
+                            $element[] =& $this->getElement($elName);
+                        }
+                    } else {
+                        $element =& $this->getElement($elementName);
+                    }
+                    // No JavaScript validation for frozen elements
+                    if (is_object($element) && $element->isFrozen()) {
+                        continue 2;
+                    } elseif (is_array($element)) {
+                        foreach (array_keys($element) as $key) {
+                            if ($element[$key]->isFrozen()) {
+                                continue 3;
+                            }
+                        }
+                    }
+
+                    $test[] = $registry->getValidationScript($element, $elementName, $rule);
+                }
+            }
+        }
+        if (count($test) > 0) {
+            return
+                "\n<script type=\"text/javascript\">\n" .
+                "//<![CDATA[\n" . 
+                "function validate_" . $this->_attributes['id'] . "(frm) {\n" .
+                "  var value = '';\n" .
+                "  var errFlag = new Array();\n" .
+                "  var _qfGroups = {};\n" .
+                "  _qfMsg = '';\n\n" .
+                join("\n", $test) .
+                "\n  if (_qfMsg != '') {\n" .
+                "    _qfMsg = '" . strtr($this->_jsPrefix, $js_escape) . "' + _qfMsg;\n" .
+                "    _qfMsg = _qfMsg + '\\n" . strtr($this->_jsPostfix, $js_escape) . "';\n" .
+                "    alert(_qfMsg);\n" .
+                "    return false;\n" .
+                "  }\n" .
+                "  return true;\n" .
+                "}\n" .
+                "//]]>\n" .
+                "</script>";
+        }
+        return '';
+    } // end func getValidationScript
+
+    // }}}
+    // {{{ getSubmitValues()
+
+    /**
+     * Returns the values submitted by the form
+     *
+     * @since     2.0
+     * @access    public
+     * @param     bool      Whether uploaded files should be returned too
+     * @return    array
+     */
+    function getSubmitValues($mergeFiles = false)
+    {
+        return $mergeFiles? HTML_QuickForm::arrayMerge($this->_submitValues, $this->_submitFiles): $this->_submitValues;
+    } // end func getSubmitValues
+
+    // }}}
+    // {{{ toArray()
+
+    /**
+     * Returns the form's contents in an array.
+     *
+     * The description of the array structure is in HTML_QuickForm_Renderer_Array docs
+     * 
+     * @since     2.0
+     * @access    public
+     * @param     bool      Whether to collect hidden elements (passed to the Renderer's constructor)
+     * @return    array of form contents
+     */
+    function toArray($collectHidden = false)
+    {
+        include_once 'HTML/QuickForm/Renderer/Array.php';
+        $renderer =& new HTML_QuickForm_Renderer_Array($collectHidden);
+        $this->accept($renderer);
+        return $renderer->toArray();
+     } // end func toArray
+
+    // }}}
+    // {{{ exportValue()
+
+    /**
+     * Returns a 'safe' element's value
+     * 
+     * This method first tries to find a cleaned-up submitted value,
+     * it will return a value set by setValue()/setDefaults()/setConstants()
+     * if submitted value does not exist for the given element.
+     *
+     * @param  string   Name of an element
+     * @access public
+     * @return mixed
+     */
+    function exportValue($element)
+    {
+        if (!isset($this->_elementIndex[$element])) {
+            return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElementValue()", 'HTML_QuickForm_Error', true);
+        }
+        $value = $this->_elements[$this->_elementIndex[$element]]->exportValue($this->_submitValues, false);
+        if (isset($this->_duplicateIndex[$element])) {
+            foreach ($this->_duplicateIndex[$element] as $index) {
+                if (null !== ($v = $this->_elements[$index]->exportValue($this->_submitValues, false))) {
+                    if (is_array($value)) {
+                        $value[] = $v;
+                    } else {
+                        $value = (null === $value)? $v: array($value, $v);
+                    }
+                }
+            }
+        }
+        return $value;
+    }
+
+    // }}}
+    // {{{ exportValues()
+
+    /**
+     * Returns 'safe' elements' values
+     *
+     * Unlike getSubmitValues(), this will return only the values 
+     * corresponding to the elements present in the form.
+     * 
+     * @param   mixed   Array/string of element names, whose values we want. If not set then return all elements.
+     * @access  public
+     * @return  array   An assoc array of elements' values
+     * @throws  HTML_QuickForm_Error
+     */
+    function exportValues($elementList = null)
+    {
+        $values = array();
+        if (null === $elementList) {
+            // iterate over all elements, calling their exportValue() methods
+            foreach (array_keys($this->_elements) as $key) {
+                $value = $this->_elements[$key]->exportValue($this->_submitValues, true);
+                if (is_array($value)) {
+                    // This shit throws a bogus warning in PHP 4.3.x
+                    $values = HTML_QuickForm::arrayMerge($values, $value);
+                }
+            }
+        } else {
+            if (!is_array($elementList)) {
+                $elementList = array_map('trim', explode(',', $elementList));
+            }
+            foreach ($elementList as $elementName) {
+                $value = $this->exportValue($elementName);
+                if (PEAR::isError($value)) {
+                    return $value;
+                }
+                $values[$elementName] = $value;
+            }
+        }
+        return $values;
+    }
+
+    // }}}
+    // {{{ isSubmitted()
+
+   /**
+    * Tells whether the form was already submitted
+    *
+    * This is useful since the _submitFiles and _submitValues arrays
+    * may be completely empty after the trackSubmit value is removed.
+    *
+    * @access public
+    * @return bool
+    */
+    function isSubmitted()
+    {
+        return $this->_flagSubmitted;
+    }
+
+
+    // }}}
+    // {{{ isError()
+
+    /**
+     * Tell whether a result from a QuickForm method is an error (an instance of HTML_QuickForm_Error)
+     *
+     * @access public
+     * @param mixed     result code
+     * @return bool     whether $value is an error
+     */
+    function isError($value)
+    {
+        return (is_object($value) && is_a($value, 'html_quickform_error'));
+    } // end func isError
+
+    // }}}
+    // {{{ errorMessage()
+
+    /**
+     * Return a textual error message for an QuickForm error code
+     *
+     * @access  public
+     * @param   int     error code
+     * @return  string  error message
+     */
+    function errorMessage($value)
+    {
+        // make the variable static so that it only has to do the defining on the first call
+        static $errorMessages;
+
+        // define the varies error messages
+        if (!isset($errorMessages)) {
+            $errorMessages = array(
+                QUICKFORM_OK                    => 'no error',
+                QUICKFORM_ERROR                 => 'unknown error',
+                QUICKFORM_INVALID_RULE          => 'the rule does not exist as a registered rule',
+                QUICKFORM_NONEXIST_ELEMENT      => 'nonexistent html element',
+                QUICKFORM_INVALID_FILTER        => 'invalid filter',
+                QUICKFORM_UNREGISTERED_ELEMENT  => 'unregistered element',
+                QUICKFORM_INVALID_ELEMENT_NAME  => 'element already exists',
+                QUICKFORM_INVALID_PROCESS       => 'process callback does not exist',
+                QUICKFORM_DEPRECATED            => 'method is deprecated',
+                QUICKFORM_INVALID_DATASOURCE    => 'datasource is not an object'
+            );
+        }
+
+        // If this is an error object, then grab the corresponding error code
+        if (HTML_QuickForm::isError($value)) {
+            $value = $value->getCode();
+        }
+
+        // return the textual error message corresponding to the code
+        return isset($errorMessages[$value]) ? $errorMessages[$value] : $errorMessages[QUICKFORM_ERROR];
+    } // end func errorMessage
+
+    // }}}
+} // end class HTML_QuickForm
+
+class HTML_QuickForm_Error extends PEAR_Error {
+
+    // {{{ properties
+
+    /**
+    * Prefix for all error messages
+    * @var string
+    */
+    var $error_message_prefix = 'QuickForm Error: ';
+
+    // }}}
+    // {{{ constructor
+
+    /**
+    * Creates a quickform error object, extending the PEAR_Error class
+    *
+    * @param int   $code the error code
+    * @param int   $mode the reaction to the error, either return, die or trigger/callback
+    * @param int   $level intensity of the error (PHP error code)
+    * @param mixed $debuginfo any information that can inform user as to nature of the error
+    */
+    function HTML_QuickForm_Error($code = QUICKFORM_ERROR, $mode = PEAR_ERROR_RETURN,
+                         $level = E_USER_NOTICE, $debuginfo = null)
+    {
+        if (is_int($code)) {
+            $this->PEAR_Error(HTML_QuickForm::errorMessage($code), $code, $mode, $level, $debuginfo);
+        } else {
+            $this->PEAR_Error("Invalid error code: $code", QUICKFORM_ERROR, $mode, $level, $debuginfo);
+        }
+    }
+
+    // }}}
+} // end class HTML_QuickForm_Error
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/DHTMLRulesTableless.php b/lib/pear/HTML/QuickForm/DHTMLRulesTableless.php
new file mode 100644 (file)
index 0000000..c9a9126
--- /dev/null
@@ -0,0 +1,208 @@
+<?php
+/**
+ * DHTML replacement for the standard JavaScript alert window for client-side
+ * validation
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category   HTML
+ * @package    HTML_QuickForm_DHTMLRulesTableless
+ * @author     Alexey Borzov <borz_off@cs.msu.su>
+ * @author     Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author     Bertrand Mansion <bmansion@mamasam.com>
+ * @author     Justin Patrin <papercrane@gmail.com>
+ * @author     Mark Wiesemann <wiesemann@php.net>
+ * @copyright  2005-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id$
+ * @link       http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless
+ */
+
+require_once 'HTML/QuickForm.php';
+
+/**
+ * This is a DHTML replacement for the standard JavaScript alert window for
+ * client-side validation of forms built with HTML_QuickForm
+ *
+ * @category   HTML
+ * @package    HTML_QuickForm_DHTMLRulesTableless
+ * @author     Alexey Borzov <borz_off@cs.msu.su>
+ * @author     Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author     Bertrand Mansion <bmansion@mamasam.com>
+ * @author     Justin Patrin <papercrane@gmail.com>
+ * @author     Mark Wiesemann <wiesemann@php.net>
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 0.1.2
+ * @link       http://pear.php.net/package/HTML_QuickForm_DHTMLRulesTableless
+ */
+class HTML_QuickForm_DHTMLRulesTableless extends HTML_QuickForm {
+    // {{{ getValidationScript()
+
+    /**
+     * Returns the client side validation script
+     *
+     * The code here was copied from HTML_QuickForm and slightly modified to run rules per-element
+     *
+     * @access    public
+     * @return    string    Javascript to perform validation, empty string if no 'client' rules were added
+     */
+    function getValidationScript()
+    {
+        if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) {
+            return '';
+        }
+
+        include_once('HTML/QuickForm/RuleRegistry.php');
+        $registry =& HTML_QuickForm_RuleRegistry::singleton();
+        $test = array();
+        $js_escape = array(
+            "\r"    => '\r',
+            "\n"    => '\n',
+            "\t"    => '\t',
+            "'"     => "\\'",
+            '"'     => '\"',
+            '\\'    => '\\\\'
+        );
+
+        foreach ($this->_rules as $elementName => $rules) {
+            foreach ($rules as $rule) {
+                if ('client' == $rule['validation']) {
+                    unset($element);
+
+                    $dependent  = isset($rule['dependent']) && is_array($rule['dependent']);
+                    $rule['message'] = strtr($rule['message'], $js_escape);
+
+                    if (isset($rule['group'])) {
+                        $group    =& $this->getElement($rule['group']);
+                        // No JavaScript validation for frozen elements
+                        if ($group->isFrozen()) {
+                            continue 2;
+                        }
+                        $elements =& $group->getElements();
+                        foreach (array_keys($elements) as $key) {
+                            if ($elementName == $group->getElementName($key)) {
+                                $element =& $elements[$key];
+                                break;
+                            }
+                        }
+                    } elseif ($dependent) {
+                        $element   =  array();
+                        $element[] =& $this->getElement($elementName);
+                        foreach ($rule['dependent'] as $idx => $elName) {
+                            $element[] =& $this->getElement($elName);
+                        }
+                    } else {
+                        $element =& $this->getElement($elementName);
+                    }
+                    // No JavaScript validation for frozen elements
+                    if (is_object($element) && $element->isFrozen()) {
+                        continue 2;
+                    } elseif (is_array($element)) {
+                        foreach (array_keys($element) as $key) {
+                            if ($element[$key]->isFrozen()) {
+                                continue 3;
+                            }
+                        }
+                    }
+
+                    $test[$elementName][] = $registry->getValidationScript($element, $elementName, $rule);
+                }
+            }
+        }
+        $js = '
+<script type="text/javascript">
+//<![CDATA[
+function qf_errorHandler(element, _qfMsg) {
+  div = element.parentNode;
+  if (_qfMsg != \'\') {
+    span = document.createElement("span");
+    span.className = "error";
+    span.appendChild(document.createTextNode(_qfMsg.substring(3)));
+    br = document.createElement("br");
+
+    var errorDiv = document.getElementById(element.name + \'_errorDiv\');
+    if (!errorDiv) {
+      errorDiv = document.createElement("div");
+      errorDiv.id = element.name + \'_errorDiv\';
+    }
+    while (errorDiv.firstChild) {
+      errorDiv.removeChild(errorDiv.firstChild);
+    }
+    
+    errorDiv.insertBefore(br, errorDiv.firstChild);
+    errorDiv.insertBefore(span, errorDiv.firstChild);
+    element.parentNode.insertBefore(errorDiv, element.parentNode.firstChild);
+
+    if (div.className.substr(div.className.length - 6, 6) != " error"
+        && div.className != "error") {
+      div.className += " error";
+    }
+
+    return false;
+  } else {
+    var errorDiv = document.getElementById(element.name + \'_errorDiv\');
+    if (errorDiv) {
+      errorDiv.parentNode.removeChild(errorDiv);
+    }
+
+    if (div.className.substr(div.className.length - 6, 6) == " error") {
+      div.className = div.className.substr(0, div.className.length - 6);
+    } else if (div.className == "error") {
+      div.className = "";
+    }
+
+    return true;
+  }
+}';
+        $validateJS = '';
+        foreach ($test as $elementName => $jsArr) {
+            $js .= '
+function validate_' . $this->_attributes['id'] . '_' . $elementName . '(element) {
+  var value = \'\';
+  var errFlag = new Array();
+  var _qfGroups = {};
+  var _qfMsg = \'\';
+  var frm = element.parentNode;
+  while (frm && frm.nodeName != "FORM") {
+    frm = frm.parentNode;
+  }
+' . join("\n", $jsArr) . '
+  return qf_errorHandler(element, _qfMsg);
+}
+';
+            $validateJS .= '
+  ret = validate_' . $this->_attributes['id'] . '_' . $elementName.'(frm.elements[\''.$elementName.'\']) && ret;';
+            unset($element);
+            $element =& $this->getElement($elementName);
+            $valFunc = 'validate_' . $this->_attributes['id'] . '_' . $elementName . '(this)';
+            $onBlur = $element->getAttribute('onBlur');
+            $onChange = $element->getAttribute('onChange');
+            $element->updateAttributes(array('onBlur' => $onBlur . $valFunc,
+                                             'onChange' => $onChange . $valFunc));
+        }
+        $js .= '
+function validate_' . $this->_attributes['id'] . '(frm) {
+  var ret = true;
+' . $validateJS . ';
+  return ret;
+}
+//]]>
+</script>';
+        return $js;
+    } // end func getValidationScript
+
+    // }}}
+
+    function display() {
+        $this->getValidationScript();
+        return parent::display();
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/Renderer.php b/lib/pear/HTML/QuickForm/Renderer.php
new file mode 100644 (file)
index 0000000..7162c64
--- /dev/null
@@ -0,0 +1,150 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Author: Alexey Borzov <borz_off@cs.msu.su>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+/**
+ * An abstract base class for QuickForm renderers
+ * 
+ * The class implements a Visitor design pattern
+ *
+ * @abstract
+ * @author Alexey Borzov <borz_off@cs.msu.su>
+ */
+class HTML_QuickForm_Renderer
+{
+   /**
+    * Constructor
+    *
+    * @access public
+    */
+    function HTML_QuickForm_Renderer()
+    {
+    } // end constructor
+
+   /**
+    * Called when visiting a form, before processing any form elements
+    *
+    * @param    object    An HTML_QuickForm object being visited
+    * @access   public
+    * @return   void 
+    * @abstract
+    */
+    function startForm(&$form)
+    {
+        return;
+    } // end func startForm
+
+   /**
+    * Called when visiting a form, after processing all form elements
+    * 
+    * @param    object     An HTML_QuickForm object being visited
+    * @access   public
+    * @return   void 
+    * @abstract
+    */
+    function finishForm(&$form)
+    {
+        return;
+    } // end func finishForm
+
+   /**
+    * Called when visiting a header element
+    *
+    * @param    object     An HTML_QuickForm_header element being visited
+    * @access   public
+    * @return   void 
+    * @abstract
+    */
+    function renderHeader(&$header)
+    {
+        return;
+    } // end func renderHeader
+
+   /**
+    * Called when visiting an element
+    *
+    * @param    object     An HTML_QuickForm_element object being visited
+    * @param    bool       Whether an element is required
+    * @param    string     An error message associated with an element
+    * @access   public
+    * @return   void 
+    * @abstract
+    */
+    function renderElement(&$element, $required, $error)
+    {
+        return;
+    } // end func renderElement
+
+   /**
+    * Called when visiting a hidden element
+    * 
+    * @param    object     An HTML_QuickForm_hidden object being visited
+    * @access   public
+    * @return   void
+    * @abstract 
+    */
+    function renderHidden(&$element)
+    {
+        return;
+    } // end func renderHidden
+
+   /**
+    * Called when visiting a raw HTML/text pseudo-element
+    * 
+    * Seems that this should not be used when using a template-based renderer
+    *
+    * @param    object     An HTML_QuickForm_html element being visited
+    * @access   public
+    * @return   void 
+    * @abstract
+    */
+    function renderHtml(&$data)
+    {
+        return;
+    } // end func renderHtml
+
+   /**
+    * Called when visiting a group, before processing any group elements
+    *
+    * @param    object     An HTML_QuickForm_group object being visited
+    * @param    bool       Whether a group is required
+    * @param    string     An error message associated with a group
+    * @access   public
+    * @return   void 
+    * @abstract
+    */
+    function startGroup(&$group, $required, $error)
+    {
+        return;
+    } // end func startGroup
+
+   /**
+    * Called when visiting a group, after processing all group elements
+    *
+    * @param    object     An HTML_QuickForm_group object being visited
+    * @access   public
+    * @return   void 
+    * @abstract
+    */
+    function finishGroup(&$group)
+    {
+        return;
+    } // end func finishGroup
+} // end class HTML_QuickForm_Renderer
+?>
diff --git a/lib/pear/HTML/QuickForm/Renderer/Array.php b/lib/pear/HTML/QuickForm/Renderer/Array.php
new file mode 100644 (file)
index 0000000..ee0c4ce
--- /dev/null
@@ -0,0 +1,319 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Alexey Borzov <borz_off@cs.msu.su>                          |
+// |          Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// |          Thomas Schulz <ths@4bconsult.de>                            |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once 'HTML/QuickForm/Renderer.php';
+
+/**
+ * A concrete renderer for HTML_QuickForm, makes an array of form contents
+ *
+ * Based on old toArray() code.
+ *
+ * The form array structure is the following:
+ * array(
+ *   'frozen'           => 'whether the form is frozen',
+ *   'javascript'       => 'javascript for client-side validation',
+ *   'attributes'       => 'attributes for <form> tag',
+ *   'requirednote      => 'note about the required elements',
+ *   // if we set the option to collect hidden elements
+ *   'hidden'           => 'collected html of all hidden elements',
+ *   // if there were some validation errors:
+ *   'errors' => array(
+ *     '1st element name' => 'Error for the 1st element',
+ *     ...
+ *     'nth element name' => 'Error for the nth element'
+ *   ),
+ *   // if there are no headers in the form:
+ *   'elements' => array(
+ *     element_1,
+ *     ...
+ *     element_N
+ *   )
+ *   // if there are headers in the form:
+ *   'sections' => array(
+ *     array(
+ *       'header'   => 'Header text for the first header',
+ *       'name'     => 'Header name for the first header',
+ *       'elements' => array(
+ *          element_1,
+ *          ...
+ *          element_K1
+ *       )
+ *     ),
+ *     ...
+ *     array(
+ *       'header'   => 'Header text for the Mth header',
+ *       'name'     => 'Header name for the Mth header',
+ *       'elements' => array(
+ *          element_1,
+ *          ...
+ *          element_KM
+ *       )
+ *     )
+ *   )
+ * );
+ *
+ * where element_i is an array of the form:
+ * array(
+ *   'name'      => 'element name',
+ *   'value'     => 'element value',
+ *   'type'      => 'type of the element',
+ *   'frozen'    => 'whether element is frozen',
+ *   'label'     => 'label for the element',
+ *   'required'  => 'whether element is required',
+ *   'error'     => 'error associated with the element',
+ *   'style'     => 'some information about element style (e.g. for Smarty)',
+ *   // if element is not a group
+ *   'html'      => 'HTML for the element'
+ *   // if element is a group
+ *   'separator' => 'separator for group elements',
+ *   'elements'  => array(
+ *     element_1,
+ *     ...
+ *     element_N
+ *   )
+ * );
+ *
+ * @access public
+ */
+class HTML_QuickForm_Renderer_Array extends HTML_QuickForm_Renderer
+{
+   /**
+    * An array being generated
+    * @var array
+    */
+    var $_ary;
+
+   /**
+    * Number of sections in the form (i.e. number of headers in it)
+    * @var integer
+    */
+    var $_sectionCount;
+
+   /**
+    * Current section number
+    * @var integer
+    */
+    var $_currentSection;
+
+   /**
+    * Array representing current group
+    * @var array
+    */
+    var $_currentGroup = null;
+
+   /**
+    * Additional style information for different elements
+    * @var array
+    */
+    var $_elementStyles = array();
+
+   /**
+    * true: collect all hidden elements into string; false: process them as usual form elements
+    * @var bool
+    */
+    var $_collectHidden = false;
+
+   /**
+    * true:  render an array of labels to many labels, $key 0 named 'label', the rest "label_$key"
+    * false: leave labels as defined
+    * @var bool
+    */
+    var $staticLabels = false;
+
+   /**
+    * Constructor
+    *
+    * @param  bool    true: collect all hidden elements into string; false: process them as usual form elements
+    * @param  bool    true: render an array of labels to many labels, $key 0 to 'label' and the oterh to "label_$key"
+    * @access public
+    */
+    function HTML_QuickForm_Renderer_Array($collectHidden = false, $staticLabels = false)
+    {
+        $this->HTML_QuickForm_Renderer();
+        $this->_collectHidden = $collectHidden;
+        $this->_staticLabels  = $staticLabels;
+    } // end constructor
+
+
+   /**
+    * Returns the resultant array
+    *
+    * @access public
+    * @return array
+    */
+    function toArray()
+    {
+        return $this->_ary;
+    }
+
+
+    function startForm(&$form)
+    {
+        $this->_ary = array(
+            'frozen'            => $form->isFrozen(),
+            'javascript'        => $form->getValidationScript(),
+            'attributes'        => $form->getAttributes(true),
+            'requirednote'      => $form->getRequiredNote(),
+            'errors'            => array()
+        );
+        if ($this->_collectHidden) {
+            $this->_ary['hidden'] = '';
+        }
+        $this->_elementIdx     = 1;
+        $this->_currentSection = null;
+        $this->_sectionCount   = 0;
+    } // end func startForm
+
+
+    function renderHeader(&$header)
+    {
+        $this->_ary['sections'][$this->_sectionCount] = array(
+            'header' => $header->toHtml(),
+            'name'   => $header->getName()
+        );
+        $this->_currentSection = $this->_sectionCount++;
+    } // end func renderHeader
+
+
+    function renderElement(&$element, $required, $error)
+    {
+        $elAry = $this->_elementToArray($element, $required, $error);
+        if (!empty($error)) {
+            $this->_ary['errors'][$elAry['name']] = $error;
+        }
+        $this->_storeArray($elAry);
+    } // end func renderElement
+
+
+    function renderHidden(&$element)
+    {
+        if ($this->_collectHidden) {
+            $this->_ary['hidden'] .= $element->toHtml() . "\n";
+        } else {
+            $this->renderElement($element, false, null);
+        }
+    } // end func renderHidden
+
+
+    function startGroup(&$group, $required, $error)
+    {
+        $this->_currentGroup = $this->_elementToArray($group, $required, $error);
+        if (!empty($error)) {
+            $this->_ary['errors'][$this->_currentGroup['name']] = $error;
+        }
+    } // end func startGroup
+
+
+    function finishGroup(&$group)
+    {
+        $this->_storeArray($this->_currentGroup);
+        $this->_currentGroup = null;
+    } // end func finishGroup
+
+
+   /**
+    * Creates an array representing an element
+    *
+    * @access private
+    * @param  object    An HTML_QuickForm_element object
+    * @param  bool      Whether an element is required
+    * @param  string    Error associated with the element
+    * @return array
+    */
+    function _elementToArray(&$element, $required, $error)
+    {
+        $ret = array(
+            'name'      => $element->getName(),
+            'value'     => $element->getValue(),
+            'type'      => $element->getType(),
+            'frozen'    => $element->isFrozen(),
+            'required'  => $required,
+            'error'     => $error
+        );
+        // render label(s)
+        $labels = $element->getLabel();
+        if (is_array($labels) && $this->_staticLabels) {
+            foreach($labels as $key => $label) {
+                $key = is_int($key)? $key + 1: $key;
+                if (1 === $key) {
+                    $ret['label'] = $label;
+                } else {
+                    $ret['label_' . $key] = $label;
+                }
+            }
+        } else {
+            $ret['label'] = $labels;
+        }
+
+        // set the style for the element
+        if (isset($this->_elementStyles[$ret['name']])) {
+            $ret['style'] = $this->_elementStyles[$ret['name']];
+        }
+        if ('group' == $ret['type']) {
+            $ret['separator'] = $element->_separator;
+            $ret['elements']  = array();
+        } else {
+            $ret['html']      = $element->toHtml();
+        }
+        return $ret;
+    }
+
+
+   /**
+    * Stores an array representation of an element in the form array
+    *
+    * @access private
+    * @param array  Array representation of an element
+    * @return void
+    */
+    function _storeArray($elAry)
+    {
+        // where should we put this element...
+        if (is_array($this->_currentGroup) && ('group' != $elAry['type'])) {
+            $this->_currentGroup['elements'][] = $elAry;
+        } elseif (isset($this->_currentSection)) {
+            $this->_ary['sections'][$this->_currentSection]['elements'][] = $elAry;
+        } else {
+            $this->_ary['elements'][] = $elAry;
+        }
+    }
+
+
+   /**
+    * Sets a style to use for element rendering
+    *
+    * @param mixed      element name or array ('element name' => 'style name')
+    * @param string     style name if $elementName is not an array
+    * @access public
+    * @return void
+    */
+    function setElementStyle($elementName, $styleName = null)
+    {
+        if (is_array($elementName)) {
+            $this->_elementStyles = array_merge($this->_elementStyles, $elementName);
+        } else {
+            $this->_elementStyles[$elementName] = $styleName;
+        }
+    }
+}
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/Renderer/Default.php b/lib/pear/HTML/QuickForm/Renderer/Default.php
new file mode 100644 (file)
index 0000000..5eeee14
--- /dev/null
@@ -0,0 +1,474 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Alexey Borzov <borz_off@cs.msu.su>                          |
+// |          Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/Renderer.php');
+
+/**
+ * A concrete renderer for HTML_QuickForm,
+ * based on QuickForm 2.x built-in one
+ * 
+ * @access public
+ */
+class HTML_QuickForm_Renderer_Default extends HTML_QuickForm_Renderer
+{
+   /**
+    * The HTML of the form  
+    * @var      string
+    * @access   private
+    */
+    var $_html;
+
+   /**
+    * Header Template string
+    * @var      string
+    * @access   private
+    */
+    var $_headerTemplate = 
+        "\n\t<tr>\n\t\t<td style=\"white-space: nowrap; background-color: #CCCCCC;\" align=\"left\" valign=\"top\" colspan=\"2\"><b>{header}</b></td>\n\t</tr>";
+
+   /**
+    * Element template string
+    * @var      string
+    * @access   private
+    */
+    var $_elementTemplate = 
+        "\n\t<tr>\n\t\t<td align=\"right\" valign=\"top\"><!-- BEGIN required --><span style=\"color: #ff0000\">*</span><!-- END required --><b>{label}</b></td>\n\t\t<td valign=\"top\" align=\"left\"><!-- BEGIN error --><span style=\"color: #ff0000\">{error}</span><br /><!-- END error -->\t{element}</td>\n\t</tr>";
+
+   /**
+    * Form template string
+    * @var      string
+    * @access   private
+    */
+    var $_formTemplate = 
+        "\n<form{attributes}>\n<div>\n{hidden}<table border=\"0\">\n{content}\n</table>\n</div>\n</form>";
+
+   /**
+    * Required Note template string
+    * @var      string
+    * @access   private
+    */
+    var $_requiredNoteTemplate = 
+        "\n\t<tr>\n\t\t<td></td>\n\t<td align=\"left\" valign=\"top\">{requiredNote}</td>\n\t</tr>";
+
+   /**
+    * Array containing the templates for customised elements
+    * @var      array
+    * @access   private
+    */
+    var $_templates = array();
+
+   /**
+    * Array containing the templates for group wraps.
+    * 
+    * These templates are wrapped around group elements and groups' own
+    * templates wrap around them. This is set by setGroupTemplate().
+    * 
+    * @var      array
+    * @access   private
+    */
+    var $_groupWraps = array();
+
+   /**
+    * Array containing the templates for elements within groups
+    * @var      array
+    * @access   private
+    */
+    var $_groupTemplates = array();
+
+   /**
+    * True if we are inside a group 
+    * @var      bool
+    * @access   private
+    */
+    var $_inGroup = false;
+
+   /**
+    * Array with HTML generated for group elements
+    * @var      array
+    * @access   private
+    */
+    var $_groupElements = array();
+
+   /**
+    * Template for an element inside a group
+    * @var      string
+    * @access   private
+    */
+    var $_groupElementTemplate = '';
+
+   /**
+    * HTML that wraps around the group elements
+    * @var      string
+    * @access   private
+    */
+    var $_groupWrap = '';
+
+   /**
+    * HTML for the current group
+    * @var      string
+    * @access   private
+    */
+    var $_groupTemplate = '';
+    
+   /**
+    * Collected HTML of the hidden fields
+    * @var      string
+    * @access   private
+    */
+    var $_hiddenHtml = '';
+
+   /**
+    * Constructor
+    *
+    * @access public
+    */
+    function HTML_QuickForm_Renderer_Default()
+    {
+        $this->HTML_QuickForm_Renderer();
+    } // end constructor
+
+   /**
+    * returns the HTML generated for the form
+    *
+    * @access public
+    * @return string
+    */
+    function toHtml()
+    {
+        // _hiddenHtml is cleared in finishForm(), so this only matters when
+        // finishForm() was not called (e.g. group::toHtml(), bug #3511)
+        return $this->_hiddenHtml . $this->_html;
+    } // end func toHtml
+    
+   /**
+    * Called when visiting a form, before processing any form elements
+    *
+    * @param    object      An HTML_QuickForm object being visited
+    * @access   public
+    * @return   void
+    */
+    function startForm(&$form)
+    {
+        $this->_html = '';
+        $this->_hiddenHtml = '';
+    } // end func startForm
+
+   /**
+    * Called when visiting a form, after processing all form elements
+    * Adds required note, form attributes, validation javascript and form content.
+    * 
+    * @param    object      An HTML_QuickForm object being visited
+    * @access   public
+    * @return   void
+    */
+    function finishForm(&$form)
+    {
+        // add a required note, if one is needed
+        if (!empty($form->_required) && !$form->_freezeAll) {
+            $this->_html .= str_replace('{requiredNote}', $form->getRequiredNote(), $this->_requiredNoteTemplate);
+        }
+        // add form attributes and content
+        $html = str_replace('{attributes}', $form->getAttributes(true), $this->_formTemplate);
+        if (strpos($this->_formTemplate, '{hidden}')) {
+            $html = str_replace('{hidden}', $this->_hiddenHtml, $html);
+        } else {
+            $this->_html .= $this->_hiddenHtml;
+        }
+        $this->_hiddenHtml = '';
+        $this->_html = str_replace('{content}', $this->_html, $html);
+        // add a validation script
+        if ('' != ($script = $form->getValidationScript())) {
+            $this->_html = $script . "\n" . $this->_html;
+        }
+    } // end func finishForm
+      
+   /**
+    * Called when visiting a header element
+    *
+    * @param    object     An HTML_QuickForm_header element being visited
+    * @access   public
+    * @return   void
+    */
+    function renderHeader(&$header)
+    {
+        $name = $header->getName();
+        if (!empty($name) && isset($this->_templates[$name])) {
+            $this->_html .= str_replace('{header}', $header->toHtml(), $this->_templates[$name]);
+        } else {
+            $this->_html .= str_replace('{header}', $header->toHtml(), $this->_headerTemplate);
+        }
+    } // end func renderHeader
+
+   /**
+    * Helper method for renderElement
+    *
+    * @param    string      Element name
+    * @param    mixed       Element label (if using an array of labels, you should set the appropriate template)
+    * @param    bool        Whether an element is required
+    * @param    string      Error message associated with the element
+    * @access   private
+    * @see      renderElement()
+    * @return   string      Html for element
+    */
+    function _prepareTemplate($name, $label, $required, $error)
+    {
+        if (is_array($label)) {
+            $nameLabel = array_shift($label);
+        } else {
+            $nameLabel = $label;
+        }
+        if (isset($this->_templates[$name])) {
+            $html = str_replace('{label}', $nameLabel, $this->_templates[$name]);
+        } else {
+            $html = str_replace('{label}', $nameLabel, $this->_elementTemplate);
+        }
+        if ($required) {
+            $html = str_replace('<!-- BEGIN required -->', '', $html);
+            $html = str_replace('<!-- END required -->', '', $html);
+        } else {
+            $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN required -->(\s|\S)*<!-- END required -->([ \t\n\r]*)?/iU", '', $html);
+        }
+        if (isset($error)) {
+            $html = str_replace('{error}', $error, $html);
+            $html = str_replace('<!-- BEGIN error -->', '', $html);
+            $html = str_replace('<!-- END error -->', '', $html);
+        } else {
+            $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN error -->(\s|\S)*<!-- END error -->([ \t\n\r]*)?/iU", '', $html);
+        }
+        if (is_array($label)) {
+            foreach($label as $key => $text) {
+                $key  = is_int($key)? $key + 2: $key;
+                $html = str_replace("{label_{$key}}", $text, $html);
+                $html = str_replace("<!-- BEGIN label_{$key} -->", '', $html);
+                $html = str_replace("<!-- END label_{$key} -->", '', $html);
+            }
+        }
+        if (strpos($html, '{label_')) {
+            $html = preg_replace('/\s*<!-- BEGIN label_(\S+) -->.*<!-- END label_\1 -->\s*/i', '', $html);
+        }
+        return $html;
+    } // end func _prepareTemplate
+
+   /**
+    * Renders an element Html
+    * Called when visiting an element
+    *
+    * @param object     An HTML_QuickForm_element object being visited
+    * @param bool       Whether an element is required
+    * @param string     An error message associated with an element
+    * @access public
+    * @return void
+    */
+    function renderElement(&$element, $required, $error)
+    {
+        if (!$this->_inGroup) {
+            $html = $this->_prepareTemplate($element->getName(), $element->getLabel(), $required, $error);
+            $this->_html .= str_replace('{element}', $element->toHtml(), $html);
+
+        } elseif (!empty($this->_groupElementTemplate)) {
+            $html = str_replace('{label}', $element->getLabel(), $this->_groupElementTemplate);
+            if ($required) {
+                $html = str_replace('<!-- BEGIN required -->', '', $html);
+                $html = str_replace('<!-- END required -->', '', $html);
+            } else {
+                $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN required -->(\s|\S)*<!-- END required -->([ \t\n\r]*)?/iU", '', $html);
+            }
+            $this->_groupElements[] = str_replace('{element}', $element->toHtml(), $html);
+
+        } else {
+            $this->_groupElements[] = $element->toHtml();
+        }
+    } // end func renderElement
+   
+   /**
+    * Renders an hidden element
+    * Called when visiting a hidden element
+    * 
+    * @param object     An HTML_QuickForm_hidden object being visited
+    * @access public
+    * @return void
+    */
+    function renderHidden(&$element)
+    {
+        $this->_hiddenHtml .= $element->toHtml() . "\n";
+    } // end func renderHidden
+
+   /**
+    * Called when visiting a raw HTML/text pseudo-element
+    * 
+    * @param  object     An HTML_QuickForm_html element being visited
+    * @access public
+    * @return void
+    */
+    function renderHtml(&$data)
+    {
+        $this->_html .= $data->toHtml();
+    } // end func renderHtml
+
+   /**
+    * Called when visiting a group, before processing any group elements
+    *
+    * @param object     An HTML_QuickForm_group object being visited
+    * @param bool       Whether a group is required
+    * @param string     An error message associated with a group
+    * @access public
+    * @return void
+    */
+    function startGroup(&$group, $required, $error)
+    {
+        $name = $group->getName();
+        $this->_groupTemplate        = $this->_prepareTemplate($name, $group->getLabel(), $required, $error);
+        $this->_groupElementTemplate = empty($this->_groupTemplates[$name])? '': $this->_groupTemplates[$name];
+        $this->_groupWrap            = empty($this->_groupWraps[$name])? '': $this->_groupWraps[$name];
+        $this->_groupElements        = array();
+        $this->_inGroup              = true;
+    } // end func startGroup
+
+   /**
+    * Called when visiting a group, after processing all group elements
+    *
+    * @param    object      An HTML_QuickForm_group object being visited
+    * @access   public
+    * @return   void
+    */
+    function finishGroup(&$group)
+    {
+        $separator = $group->_separator;
+        if (is_array($separator)) {
+            $count = count($separator);
+            $html  = '';
+            for ($i = 0; $i < count($this->_groupElements); $i++) {
+                $html .= (0 == $i? '': $separator[($i - 1) % $count]) . $this->_groupElements[$i];
+            }
+        } else {
+            if (is_null($separator)) {
+                $separator = '&nbsp;';
+            }
+            $html = implode((string)$separator, $this->_groupElements);
+        }
+        if (!empty($this->_groupWrap)) {
+            $html = str_replace('{content}', $html, $this->_groupWrap);
+        }
+        $this->_html   .= str_replace('{element}', $html, $this->_groupTemplate);
+        $this->_inGroup = false;
+    } // end func finishGroup
+
+    /**
+     * Sets element template 
+     *
+     * @param       string      The HTML surrounding an element 
+     * @param       string      (optional) Name of the element to apply template for
+     * @access      public
+     * @return      void
+     */
+    function setElementTemplate($html, $element = null)
+    {
+        if (is_null($element)) {
+            $this->_elementTemplate = $html;
+        } else {
+            $this->_templates[$element] = $html;
+        }
+    } // end func setElementTemplate
+
+
+    /**
+     * Sets template for a group wrapper 
+     * 
+     * This template is contained within a group-as-element template 
+     * set via setTemplate() and contains group's element templates, set
+     * via setGroupElementTemplate()
+     *
+     * @param       string      The HTML surrounding group elements
+     * @param       string      Name of the group to apply template for
+     * @access      public
+     * @return      void
+     */
+    function setGroupTemplate($html, $group)
+    {
+        $this->_groupWraps[$group] = $html;
+    } // end func setGroupTemplate
+
+    /**
+     * Sets element template for elements within a group
+     *
+     * @param       string      The HTML surrounding an element 
+     * @param       string      Name of the group to apply template for
+     * @access      public
+     * @return      void
+     */
+    function setGroupElementTemplate($html, $group)
+    {
+        $this->_groupTemplates[$group] = $html;
+    } // end func setGroupElementTemplate
+
+    /**
+     * Sets header template
+     *
+     * @param       string      The HTML surrounding the header 
+     * @access      public
+     * @return      void
+     */
+    function setHeaderTemplate($html)
+    {
+        $this->_headerTemplate = $html;
+    } // end func setHeaderTemplate
+
+    /**
+     * Sets form template 
+     *
+     * @param     string    The HTML surrounding the form tags 
+     * @access    public
+     * @return    void
+     */
+    function setFormTemplate($html)
+    {
+        $this->_formTemplate = $html;
+    } // end func setFormTemplate
+
+    /**
+     * Sets the note indicating required fields template
+     *
+     * @param       string      The HTML surrounding the required note 
+     * @access      public
+     * @return      void
+     */
+    function setRequiredNoteTemplate($html)
+    {
+        $this->_requiredNoteTemplate = $html;
+    } // end func setRequiredNoteTemplate
+
+    /**
+     * Clears all the HTML out of the templates that surround notes, elements, etc.
+     * Useful when you want to use addData() to create a completely custom form look
+     *
+     * @access  public
+     * @return  void
+     */
+    function clearAllTemplates()
+    {
+        $this->setElementTemplate('{element}');
+        $this->setFormTemplate("\n\t<form{attributes}>{content}\n\t</form>\n");
+        $this->setRequiredNoteTemplate('');
+        $this->_templates = array();
+    } // end func clearAllTemplates
+} // end class HTML_QuickForm_Renderer_Default
+?>
diff --git a/lib/pear/HTML/QuickForm/Renderer/Object.php b/lib/pear/HTML/QuickForm/Renderer/Object.php
new file mode 100644 (file)
index 0000000..9ed495c
--- /dev/null
@@ -0,0 +1,432 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Author: Ron McClain <ron@humaniq.com>                                |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/Renderer.php');
+
+/**
+ * A concrete renderer for HTML_QuickForm, makes an object from form contents
+ *
+ * Based on HTML_Quickform_Renderer_Array code
+ *
+ * @access public
+ */
+class HTML_QuickForm_Renderer_Object extends HTML_QuickForm_Renderer
+{
+    /**
+     * The object being generated
+     * @var object $_obj
+     */
+    var $_obj= null;
+
+    /**
+     * Number of sections in the form (i.e. number of headers in it)
+     * @var integer $_sectionCount
+     */
+    var $_sectionCount;
+
+    /**
+    * Current section number
+    * @var integer $_currentSection
+    */
+    var $_currentSection;
+
+    /**
+    * Object representing current group
+    * @var object $_currentGroup
+    */
+    var $_currentGroup = null;
+
+    /**
+     * Class of Element Objects
+     * @var object $_elementType
+     */
+    var $_elementType = 'QuickFormElement';
+
+    /**
+    * Additional style information for different elements  
+    * @var array $_elementStyles
+    */
+    var $_elementStyles = array();
+
+    /**
+    * true: collect all hidden elements into string; false: process them as usual form elements
+    * @var bool $_collectHidden
+    */
+    var $_collectHidden = false;
+
+
+    /**
+     * Constructor
+     *
+     * @param collecthidden bool    true: collect all hidden elements
+     * @access public
+     */
+    function HTML_QuickForm_Renderer_Object($collecthidden = false) 
+    {
+        $this->HTML_QuickForm_Renderer();
+        $this->_collectHidden = $collecthidden;
+        $this->_obj = new QuickformForm;
+    }
+
+    /**
+     * Return the rendered Object
+     * @access public
+     */
+    function toObject() 
+    {
+        return $this->_obj;
+    }
+
+    /**
+     * Set the class of the form elements.  Defaults to QuickformElement.
+     * @param type string   Name of element class
+     * @access public
+     */
+    function setElementType($type)
+    {
+        $this->_elementType = $type;
+    }
+
+    function startForm(&$form) 
+    {
+        $this->_obj->frozen = $form->isFrozen();
+        $this->_obj->javascript = $form->getValidationScript();
+        $this->_obj->attributes = $form->getAttributes(true);
+        $this->_obj->requirednote = $form->getRequiredNote();
+        $this->_obj->errors = new StdClass;
+
+        if($this->_collectHidden) {
+            $this->_obj->hidden = '';
+        }
+        $this->_elementIdx = 1;
+        $this->_currentSection = null;
+        $this->_sectionCount = 0;
+    } // end func startForm
+
+    function renderHeader(&$header) 
+    {
+        $hobj = new StdClass;
+        $hobj->header = $header->toHtml();
+        $this->_obj->sections[$this->_sectionCount] = $hobj;
+        $this->_currentSection = $this->_sectionCount++;
+    }
+
+    function renderElement(&$element, $required, $error) 
+    {
+        $elObj = $this->_elementToObject($element, $required, $error);
+        if(!empty($error)) {
+            $name = $elObj->name;
+            $this->_obj->errors->$name = $error;
+        }
+        $this->_storeObject($elObj);
+    } // end func renderElement
+
+    function renderHidden(&$element)
+    {
+        if($this->_collectHidden) {
+            $this->_obj->hidden .= $element->toHtml() . "\n";
+        } else {
+            $this->renderElement($element, false, null);
+        }
+    } //end func renderHidden
+
+    function startGroup(&$group, $required, $error) 
+    {
+        $this->_currentGroup = $this->_elementToObject($group, $required, $error);
+        if(!empty($error)) {
+            $name = $this->_currentGroup->name;
+            $this->_obj->errors->$name = $error;
+        }
+    } // end func startGroup
+
+    function finishGroup(&$group) 
+    {
+        $this->_storeObject($this->_currentGroup);
+        $this->_currentGroup = null;
+    } // end func finishGroup
+
+    /**
+     * Creates an object representing an element
+     *
+     * @access private
+     * @param element object    An HTML_QuickForm_element object
+     * @param required bool         Whether an element is required
+     * @param error string    Error associated with the element
+     * @return object
+     */
+    function _elementToObject(&$element, $required, $error) 
+    {
+        if($this->_elementType) {
+            $ret = new $this->_elementType;
+        }
+        $ret->name = $element->getName();
+        $ret->value = $element->getValue();
+        $ret->type = $element->getType();
+        $ret->frozen = $element->isFrozen();
+        $labels = $element->getLabel();
+        if (is_array($labels)) {
+            $ret->label = array_shift($labels);
+            foreach ($labels as $key => $label) {
+                $key = is_int($key)? $key + 2: $key;
+                $ret->{'label_' . $key} = $label;
+            }
+        } else {
+            $ret->label = $labels;
+        }
+        $ret->required = $required;
+        $ret->error = $error;
+
+        if(isset($this->_elementStyles[$ret->name])) {
+            $ret->style = $this->_elementStyles[$ret->name];
+            $ret->styleTemplate = "styles/". $ret->style .".html";
+        }
+        if($ret->type == 'group') {
+            $ret->separator = $element->_separator;
+            $ret->elements = array();
+        } else {
+            $ret->html = $element->toHtml();
+        }
+        return $ret;
+    }
+
+    /** 
+     * Stores an object representation of an element in the form array
+     *
+     * @access private
+     * @param elObj object     Object representation of an element
+     * @return void
+     */
+    function _storeObject($elObj) 
+    {
+        $name = $elObj->name;
+        if(is_object($this->_currentGroup) && $elObj->type != 'group') {
+            $this->_currentGroup->elements[] = $elObj;
+        } elseif (isset($this->_currentSection)) {
+            $this->_obj->sections[$this->_currentSection]->elements[] = $elObj;
+        } else {
+            $this->_obj->elements[] = $elObj;
+        }
+    }
+
+    function setElementStyle($elementName, $styleName = null)
+    {
+        if(is_array($elementName)) {
+            $this->_elementStyles = array_merge($this->_elementStyles, $elementName);
+        } else {
+            $this->_elementStyles[$elementName] = $styleName;
+        }
+    }
+
+} // end class HTML_QuickForm_Renderer_Object
+
+
+
+/**
+ * Convenience class for the form object passed to outputObject()
+ * 
+ * Eg.  
+ * {form.outputJavaScript():h}
+ * {form.outputHeader():h}
+ *   <table>
+ *     <tr>
+ *       <td>{form.name.label:h}</td><td>{form.name.html:h}</td>
+ *     </tr>
+ *   </table>
+ * </form>
+ */
+class QuickformForm
+{
+   /**
+    * Whether the form has been frozen
+    * @var boolean $frozen
+    */
+    var $frozen;
+
+   /**
+    * Javascript for client-side validation
+    * @var string $javascript
+    */
+    var $javascript;
+
+   /**
+    * Attributes for form tag
+    * @var string $attributes
+    */
+    var $attributes;
+
+   /**
+    * Note about required elements
+    * @var string $requirednote
+    */
+    var $requirednote;
+
+   /**
+    * Collected html of all hidden variables
+    * @var string $hidden
+    */
+    var $hidden;
+
+   /**
+    * Set if there were validation errors.  
+    * StdClass object with element names for keys and their
+    * error messages as values
+    * @var object $errors
+    */
+    var $errors;
+
+   /**
+    * Array of QuickformElementObject elements.  If there are headers in the form
+    * this will be empty and the elements will be in the 
+    * separate sections
+    * @var array $elements
+    */
+    var $elements;
+
+   /**
+    * Array of sections contained in the document
+    * @var array $sections
+    */
+    var $sections;
+
+   /**
+    * Output &lt;form&gt; header
+    * {form.outputHeader():h} 
+    * @return string    &lt;form attributes&gt;
+    */
+    function outputHeader()
+    {
+        return "<form " . $this->attributes . ">\n";
+    }
+
+   /**
+    * Output form javascript
+    * {form.outputJavaScript():h}
+    * @return string    Javascript
+    */
+    function outputJavaScript()
+    {
+        return $this->javascript;
+    }
+} // end class QuickformForm
+
+
+/**
+ * Convenience class describing a form element.
+ * The properties defined here will be available from 
+ * your flexy templates by referencing
+ * {form.zip.label:h}, {form.zip.html:h}, etc.
+ */
+class QuickformElement
+{
+    /**
+     * Element name
+     * @var string $name
+     */
+    var $name;
+
+    /**
+     * Element value
+     * @var mixed $value
+     */
+    var $value;
+
+    /**
+     * Type of element
+     * @var string $type
+     */
+    var $type;
+
+    /**
+     * Whether the element is frozen
+     * @var boolean $frozen
+     */
+    var $frozen;
+
+    /**
+     * Label for the element
+     * @var string $label
+     */
+    var $label;
+
+    /**
+     * Whether element is required
+     * @var boolean $required
+     */
+    var $required;
+
+    /**
+     * Error associated with the element
+     * @var string $error
+     */
+    var $error;
+
+    /**
+     * Some information about element style
+     * @var string $style
+     */
+    var $style;
+
+    /**
+     * HTML for the element
+     * @var string $html
+     */
+    var $html;
+
+    /**
+     * If element is a group, the group separator
+     * @var mixed $separator
+     */
+    var $separator;
+
+    /**
+     * If element is a group, an array of subelements
+     * @var array $elements
+     */
+    var $elements;
+
+    function isType($type)
+    {
+        return ($this->type == $type);
+    }
+
+    function notFrozen()
+    {
+        return !$this->frozen;
+    }
+
+    function isButton()
+    {
+        return ($this->type == "submit" || $this->type == "reset");
+    }
+
+
+   /**
+    * XXX: why does it use Flexy when all other stuff here does not depend on it?
+    */
+    function outputStyle()
+    {
+        ob_start();
+        HTML_Template_Flexy::staticQuickTemplate('styles/' . $this->style . '.html', $this);
+        $ret = ob_get_contents();
+        ob_end_clean();
+        return $ret;
+    }
+} // end class QuickformElement
+?>
diff --git a/lib/pear/HTML/QuickForm/Renderer/Tableless.php b/lib/pear/HTML/QuickForm/Renderer/Tableless.php
new file mode 100644 (file)
index 0000000..a631b71
--- /dev/null
@@ -0,0 +1,313 @@
+<?php
+/**
+ * A renderer for HTML_QuickForm that only uses XHTML and CSS but no
+ * table tags
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.01 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category   HTML
+ * @package    HTML_QuickForm_Renderer_Tableless
+ * @author     Alexey Borzov <borz_off@cs.msu.su>
+ * @author     Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author     Bertrand Mansion <bmansion@mamasam.com>
+ * @author     Mark Wiesemann <wiesemann@php.net>
+ * @copyright  2005-2006 The PHP Group
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    CVS: $Id$
+ * @link       http://pear.php.net/package/HTML_QuickForm_Renderer_Tableless
+ */
+
+require_once 'HTML/QuickForm/Renderer/Default.php';
+
+/**
+ * A renderer for HTML_QuickForm that only uses XHTML and CSS but no
+ * table tags
+ * 
+ * You need to specify a stylesheet like the one that you find in
+ * data/stylesheet.css to make this work.
+ *
+ * @category   HTML
+ * @package    HTML_QuickForm_Renderer_Tableless
+ * @author     Alexey Borzov <borz_off@cs.msu.su>
+ * @author     Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author     Bertrand Mansion <bmansion@mamasam.com>
+ * @author     Mark Wiesemann <wiesemann@php.net>
+ * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
+ * @version    Release: 0.3.3
+ * @link       http://pear.php.net/package/HTML_QuickForm_Renderer_Tableless
+ */
+class HTML_QuickForm_Renderer_Tableless extends HTML_QuickForm_Renderer_Default
+{
+   /**
+    * Header Template string
+    * @var      string
+    * @access   private
+    */
+    var $_headerTemplate = 
+        "\n\t\t<legend>{header}</legend>";
+
+   /**
+    * Element template string
+    * @var      string
+    * @access   private
+    */
+    var $_elementTemplate = 
+        "\n\t\t<div class=\"qfrow\"><label class=\"qflabel\"><!-- BEGIN required --><span class=\"required\">*</span><!-- END required -->{label}</label>{help}<div class=\"qfelement<!-- BEGIN error --> error<!-- END error -->\"><!-- BEGIN error --><span class=\"error\">{error}</span><br /><!-- END error -->{element}</div></div><br />";
+
+   /**
+    * Form template string
+    * @var      string
+    * @access   private
+    */
+    var $_formTemplate = 
+        "\n<form{attributes}>\n\t<div style=\"display: none;\">{hidden}</div>\n{content}\n</form>";
+
+   /**
+    * Template used when opening a fieldset
+    * @var      string
+    * @access   private
+    */
+    var $_openFieldsetTemplate = "\n\t<fieldset{id}>";
+
+   /**
+    * Template used when opening a hidden fieldset
+    * (i.e. a fieldset that is opened when there is no header element)
+    * @var      string
+    * @access   private
+    */
+    var $_openHiddenFieldsetTemplate = "\n\t<fieldset class=\"hidden\">";
+
+   /**
+    * Template used when closing a fieldset
+    * @var      string
+    * @access   private
+    */
+    var $_closeFieldsetTemplate = "\n\t</fieldset>";
+
+   /**
+    * Required Note template string
+    * @var      string
+    * @access   private
+    */
+    var $_requiredNoteTemplate = 
+        "\n\t\t{requiredNote}";
+
+   /**
+    * How many fieldsets are open
+    * @var      integer
+    * @access   private
+    */
+   var $_fieldsetsOpen = 0;
+
+   /**
+    * Array of element names that indicate the end of a fieldset
+    * (a new one will be opened when a the next header element occurs)
+    * @var      array
+    * @access   private
+    */
+    var $_stopFieldsetElements = array();
+
+   /**
+    * Constructor
+    *
+    * @access public
+    */
+    function HTML_QuickForm_Renderer_Tableless()
+    {
+        $this->HTML_QuickForm_Renderer_Default();
+    } // end constructor
+
+   /**
+    * Called when visiting a header element
+    *
+    * @param    object     An HTML_QuickForm_header element being visited
+    * @access   public
+    * @return   void
+    */
+    function renderHeader(&$header)
+    {
+        $name = $header->getName();
+        $id = empty($name) ? '' : ' id="' . $name . '"';
+        if (is_null($header->_text)) {
+            $header_html = '';
+        }
+        elseif (!empty($name) && isset($this->_templates[$name])) {
+            $header_html = str_replace('{header}', $header->toHtml(), $this->_templates[$name]);
+        } else {
+            $header_html = str_replace('{header}', $header->toHtml(), $this->_headerTemplate);
+        }
+        if ($this->_fieldsetsOpen > 0) {
+            $this->_html .= $this->_closeFieldsetTemplate;
+            $this->_fieldsetsOpen--;
+        }
+        $openFieldsetTemplate = str_replace('{id}', $id, $this->_openFieldsetTemplate);
+        $this->_html .= $openFieldsetTemplate . $header_html;
+        $this->_fieldsetsOpen++;
+    } // end func renderHeader
+
+   /**
+    * Renders an element Html
+    * Called when visiting an element
+    *
+    * @param object     An HTML_QuickForm_element object being visited
+    * @param bool       Whether an element is required
+    * @param string     An error message associated with an element
+    * @access public
+    * @return void
+    */
+    function renderElement(&$element, $required, $error)
+    {
+        // if the element name indicates the end of a fieldset, close the fieldset
+        if (   in_array($element->getName(), $this->_stopFieldsetElements)
+            && $this->_fieldsetsOpen > 0
+           ) {
+            $this->_html .= $this->_closeFieldsetTemplate;
+            $this->_fieldsetsOpen--;
+        }
+        // if no fieldset was opened, we need to open a hidden one here to get
+        // XHTML validity
+        if ($this->_fieldsetsOpen === 0) {
+            $this->_html .= $this->_openHiddenFieldsetTemplate;
+            $this->_fieldsetsOpen++;
+        }
+        if (!$this->_inGroup) {
+            $html = $this->_prepareTemplate($element->getName(), $element->getLabel(), $required, $error);
+            // the following lines (until the "elseif") were changed / added
+            // compared to the default renderer
+            $element_html = $element->toHtml();
+            if (!is_null($element->getAttribute('id'))) {
+                $id = $element->getAttribute('id');
+            } else {
+                $id = $element->getName();
+            }
+            $html = str_replace('<label', '<label for="' . $id . '"', $html);
+            $element_html = str_replace('name="' . $id . '"',
+                                        'id="' . $id . '" name="' . $id . '"',
+                                        $element_html);
+            $this->_html .= str_replace('{element}', $element_html, $html);
+        } elseif (!empty($this->_groupElementTemplate)) {
+            $html = str_replace('{label}', $element->getLabel(), $this->_groupElementTemplate);
+            if ($required) {
+                $html = str_replace('<!-- BEGIN required -->', '', $html);
+                $html = str_replace('<!-- END required -->', '', $html);
+            } else {
+                $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN required -->(\s|\S)*<!-- END required -->([ \t\n\r]*)?/i", '', $html);
+            }
+            $this->_groupElements[] = str_replace('{element}', $element->toHtml(), $html);
+
+        } else {
+            $this->_groupElements[] = $element->toHtml();
+        }
+    } // end func renderElement
+
+   /**
+    * Called when visiting a form, before processing any form elements
+    *
+    * @param    object      An HTML_QuickForm object being visited
+    * @access   public
+    * @return   void
+    */
+    function startForm(&$form)
+    {
+        $this->_fieldsetsOpen = 0;
+        parent::startForm($form);
+    } // end func startForm
+
+   /**
+    * Called when visiting a form, after processing all form elements
+    * Adds required note, form attributes, validation javascript and form content.
+    * 
+    * @param    object      An HTML_QuickForm object being visited
+    * @access   public
+    * @return   void
+    */
+    function finishForm(&$form)
+    {
+        // add a required note, if one is needed
+        if (!empty($form->_required) && !$form->_freezeAll) {
+            $this->_html .= str_replace('{requiredNote}', $form->getRequiredNote(), $this->_requiredNoteTemplate);
+        }
+        // close the open fieldset
+        if ($this->_fieldsetsOpen > 0) {
+            $this->_html .= $this->_closeFieldsetTemplate;
+            $this->_fieldsetsOpen--;
+        }
+        // add form attributes and content
+        $html = str_replace('{attributes}', $form->getAttributes(true), $this->_formTemplate);
+        if (strpos($this->_formTemplate, '{hidden}')) {
+            $html = str_replace('{hidden}', $this->_hiddenHtml, $html);
+        } else {
+            $this->_html .= $this->_hiddenHtml;
+        }
+        $this->_hiddenHtml = '';
+        $this->_html = str_replace('{content}', $this->_html, $html);
+        $this->_html = str_replace('></label>', '>&nbsp;</label>', $this->_html);
+        // add a validation script
+        if ('' != ($script = $form->getValidationScript())) {
+            $this->_html = $script . "\n" . $this->_html;
+        }
+    } // end func finishForm
+
+    /**
+     * Sets the template used when opening a fieldset
+     *
+     * @param       string      The HTML used when opening a fieldset
+     * @access      public
+     * @return      void
+     */
+    function setOpenFieldsetTemplate($html)
+    {
+        $this->_openFieldsetTemplate = $html;
+    } // end func setOpenFieldsetTemplate
+
+    /**
+     * Sets the template used when opening a hidden fieldset
+     * (i.e. a fieldset that is opened when there is no header element)
+     *
+     * @param       string      The HTML used when opening a hidden fieldset
+     * @access      public
+     * @return      void
+     */
+    function setOpenHiddenFieldsetTemplate($html)
+    {
+        $this->_openHiddenFieldsetTemplate = $html;
+    } // end func setOpenHiddenFieldsetTemplate
+
+    /**
+     * Sets the template used when closing a fieldset
+     *
+     * @param       string      The HTML used when closing a fieldset
+     * @access      public
+     * @return      void
+     */
+    function setCloseFieldsetTemplate($html)
+    {
+        $this->_closeFieldsetTemplate = $html;
+    } // end func setCloseFieldsetTemplate
+
+    /**
+     * Adds one or more element names that indicate the end of a fieldset
+     * (a new one will be opened when a the next header element occurs)
+     *
+     * @param       mixed      Element name(s) (as array or string)
+     * @access      public
+     * @return      void
+     */
+    function addStopFieldsetElements($element)
+    {
+        if (is_array($element)) {
+            $this->_stopFieldsetElements = array_merge($this->_stopFieldsetElements,
+                                                       $element);
+        } else {
+            $this->_stopFieldsetElements[] = $element;
+        }
+    } // end func addStopFieldsetElements
+
+} // end class HTML_QuickForm_Renderer_Default
+?>
diff --git a/lib/pear/HTML/QuickForm/Rule.php b/lib/pear/HTML/QuickForm/Rule.php
new file mode 100644 (file)
index 0000000..74e2a00
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+class HTML_QuickForm_Rule
+{
+   /**
+    * Name of the rule to use in validate method
+    *
+    * This property is used in more global rules like Callback and Regex
+    * to determine which callback and which regex is to be used for validation
+    *
+    * @var  string
+    * @access   public
+    */
+    var $name;
+
+   /**
+    * Validates a value
+    * 
+    * @access public
+    * @abstract
+    */
+    function validate($value)
+    {
+        return true;
+    }
+
+   /**
+    * Sets the rule name
+    * 
+    * @access public
+    */
+    function setName($ruleName)
+    {
+        $this->name = $ruleName;
+    }
+
+    /**
+     * Returns the javascript test (the test should return true if the value is INVALID)
+     *
+     * @param     mixed     Options for the rule
+     * @access    public
+     * @return    array     first element is code to setup validation, second is the check itself
+     */
+    function getValidationScript($options = null)
+    {
+        return array('', '');
+    }
+}
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/Rule/Callback.php b/lib/pear/HTML/QuickForm/Rule/Callback.php
new file mode 100644 (file)
index 0000000..cba44f4
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/Rule.php');
+
+/**
+* Validates values using callback functions or methods
+* @version     1.0
+*/
+class HTML_QuickForm_Rule_Callback extends HTML_QuickForm_Rule
+{
+    /**
+     * Array of callbacks
+     *
+     * Array is in the format:
+     * $_data['rulename'] = array('functionname', 'classname');
+     * If the callback is not a method, then the class name is not set.
+     *
+     * @var     array
+     * @access  private
+     */
+    var $_data = array();
+
+   /**
+    * Whether to use BC mode for specific rules
+    * 
+    * Previous versions of QF passed element's name as a first parameter
+    * to validation functions, but not to validation methods. This behaviour
+    * is emulated if you are using 'function' as rule type when registering.
+    * 
+    * @var array
+    * @access private
+    */
+    var $_BCMode = array();
+
+    /**
+     * Validates a value using a callback
+     *
+     * @param     string    $value      Value to be checked
+     * @param     mixed     $options    Options for callback
+     * @access    public
+     * @return    boolean   true if value is valid
+     */
+    function validate($value, $options = null)
+    {
+        if (isset($this->_data[$this->name])) {
+            $callback = $this->_data[$this->name];
+            if (isset($callback[1])) {
+                return call_user_func(array($callback[1], $callback[0]), $value, $options);
+            } elseif ($this->_BCMode[$this->name]) {
+                return $callback[0]('', $value, $options);
+            } else {
+                return $callback[0]($value, $options);
+            }
+        } elseif (is_callable($options)) {
+            return call_user_func($options, $value);
+        } else {
+            return true;
+        }
+    } // end func validate
+
+    /**
+     * Adds new callbacks to the callbacks list
+     *
+     * @param     string    $name       Name of rule
+     * @param     string    $callback   Name of function or method
+     * @param     string    $class      Name of class containing the method
+     * @param     bool      $BCMode     Backwards compatibility mode 
+     * @access    public
+     */
+    function addData($name, $callback, $class = null, $BCMode = false)
+    {
+        if (!empty($class)) {
+            $this->_data[$name] = array($callback, $class);
+        } else {
+            $this->_data[$name] = array($callback);
+        }
+        $this->_BCMode[$name] = $BCMode;
+    } // end func addData
+
+
+    function getValidationScript($options = null)
+    {
+        if (isset($this->_data[$this->name])) {
+            $callback = $this->_data[$this->name][0];
+            $params   = ($this->_BCMode[$this->name]? "'', {jsVar}": '{jsVar}') .
+                        (isset($options)? ", '{$options}'": '');
+        } else {
+            $callback = is_array($options)? $options[1]: $options;
+            $params   = '{jsVar}';
+        }
+        return array('', "{jsVar} != '' && !{$callback}({$params})");
+    } // end func getValidationScript
+
+} // end class HTML_QuickForm_Rule_Callback
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/Rule/Compare.php b/lib/pear/HTML/QuickForm/Rule/Compare.php
new file mode 100644 (file)
index 0000000..594e51c
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Author: Alexey Borzov <avb@php.net>                                  |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once 'HTML/QuickForm/Rule.php';
+
+/**
+ * Rule to compare two form fields
+ * 
+ * The most common usage for this is to ensure that the password 
+ * confirmation field matches the password field
+ * 
+ * @access public
+ * @package HTML_QuickForm
+ * @version $Revision$
+ */
+class HTML_QuickForm_Rule_Compare extends HTML_QuickForm_Rule
+{
+   /**
+    * Possible operators to use
+    * @var array
+    * @access private
+    */
+    var $_operators = array(
+        'eq'  => '==',
+        'neq' => '!=',
+        'gt'  => '>',
+        'gte' => '>=',
+        'lt'  => '<',
+        'lte' => '<='
+    );
+
+
+   /**
+    * Returns the operator to use for comparing the values
+    * 
+    * @access private
+    * @param  string     operator name
+    * @return string     operator to use for validation
+    */
+    function _findOperator($name)
+    {
+        if (empty($name)) {
+            return '==';
+        } elseif (isset($this->_operators[$name])) {
+            return $this->_operators[$name];
+        } elseif (in_array($name, $this->_operators)) {
+            return $name;
+        } else {
+            return '==';
+        }
+    }
+
+
+    function validate($values, $operator = null)
+    {
+        $operator = $this->_findOperator($operator);
+        if ('==' != $operator && '!=' != $operator) {
+            $compareFn = create_function('$a, $b', 'return floatval($a) ' . $operator . ' floatval($b);');
+        } else {
+            $compareFn = create_function('$a, $b', 'return $a ' . $operator . ' $b;');
+        }
+        
+        return $compareFn($values[0], $values[1]);
+    }
+
+
+    function getValidationScript($operator = null)
+    {
+        $operator = $this->_findOperator($operator);
+        if ('==' != $operator && '!=' != $operator) {
+            $check = "!(Number({jsVar}[0]) {$operator} Number({jsVar}[1]))";
+        } else {
+            $check = "!({jsVar}[0] {$operator} {jsVar}[1])";
+        }
+        return array('', "'' != {jsVar}[0] && {$check}");
+    }
+}
+?>
diff --git a/lib/pear/HTML/QuickForm/Rule/Email.php b/lib/pear/HTML/QuickForm/Rule/Email.php
new file mode 100644 (file)
index 0000000..8a887f6
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/Rule.php');
+
+/**
+* Email validation rule
+* @version     1.0
+*/
+class HTML_QuickForm_Rule_Email extends HTML_QuickForm_Rule
+{
+    var $regex = '/^((\"[^\"\f\n\r\t\v\b]+\")|([\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+(\.[\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+)*))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\-])+\.)+[A-Za-z\-]+))$/';
+
+    /**
+     * Validates an email address
+     *
+     * @param     string    $email          Email address
+     * @param     boolean   $checkDomain    True if dns check should be performed
+     * @access    public
+     * @return    boolean   true if email is valid
+     */
+    function validate($email, $checkDomain = false)
+    {
+        if (preg_match($this->regex, $email)) {
+            if ($checkDomain && function_exists('checkdnsrr')) {
+                $tokens = explode('@', $email);
+                if (checkdnsrr($tokens[1], 'MX') || checkdnsrr($tokens[1], 'A')) {
+                    return true;
+                }
+                return false;
+            }
+            return true;
+        }
+        return false;
+    } // end func validate
+
+
+    function getValidationScript($options = null)
+    {
+        return array("  var regex = " . $this->regex . ";\n", "{jsVar} != '' && !regex.test({jsVar})");
+    } // end func getValidationScript
+
+} // end class HTML_QuickForm_Rule_Email
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/Rule/Range.php b/lib/pear/HTML/QuickForm/Rule/Range.php
new file mode 100644 (file)
index 0000000..6f83a8e
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/Rule.php');
+
+/**
+* Validates values using range comparison
+* @version     1.0
+*/
+class HTML_QuickForm_Rule_Range extends HTML_QuickForm_Rule
+{
+    /**
+     * Validates a value using a range comparison
+     *
+     * @param     string    $value      Value to be checked
+     * @param     mixed     $options    Int for length, array for range
+     * @access    public
+     * @return    boolean   true if value is valid
+     */
+    function validate($value, $options)
+    {
+        $length = strlen($value);
+        switch ($this->name) {
+            case 'minlength': return ($length >= $options);
+            case 'maxlength': return ($length <= $options);
+            default:          return ($length >= $options[0] && $length <= $options[1]);
+        }
+    } // end func validate
+
+
+    function getValidationScript($options = null)
+    {
+        switch ($this->name) {
+            case 'minlength': 
+                $test = '{jsVar}.length < '.$options;
+                break;
+            case 'maxlength': 
+                $test = '{jsVar}.length > '.$options;
+                break;
+            default: 
+                $test = '({jsVar}.length < '.$options[0].' || {jsVar}.length > '.$options[1].')';
+        }
+        return array('', "{jsVar} != '' && {$test}");
+    } // end func getValidationScript
+
+} // end class HTML_QuickForm_Rule_Range
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/Rule/Regex.php b/lib/pear/HTML/QuickForm/Rule/Regex.php
new file mode 100644 (file)
index 0000000..787a957
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/Rule.php');
+
+/**
+* Validates values using regular expressions
+* @version     1.0
+*/
+class HTML_QuickForm_Rule_Regex extends HTML_QuickForm_Rule
+{
+    /**
+     * Array of regular expressions
+     *
+     * Array is in the format:
+     * $_data['rulename'] = 'pattern';
+     *
+     * @var     array
+     * @access  private
+     */
+    var $_data = array(
+                    'lettersonly'   => '/^[a-zA-Z]+$/',
+                    'alphanumeric'  => '/^[a-zA-Z0-9]+$/',
+                    'numeric'       => '/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/',
+                    'nopunctuation' => '/^[^().\/\*\^\?#!@$%+=,\"\'><~\[\]{}]+$/',
+                    'nonzero'       => '/^-?[1-9][0-9]*/'
+                    );
+
+    /**
+     * Validates a value using a regular expression
+     *
+     * @param     string    $value      Value to be checked
+     * @param     string    $regex      Regular expression
+     * @access    public
+     * @return    boolean   true if value is valid
+     */
+    function validate($value, $regex = null)
+    {
+        if (isset($this->_data[$this->name])) {
+            if (!preg_match($this->_data[$this->name], $value)) {
+                return false;
+            }
+        } else {
+            if (!preg_match($regex, $value)) {
+                return false;
+            }
+        }
+        return true;
+    } // end func validate
+
+    /**
+     * Adds new regular expressions to the list
+     *
+     * @param     string    $name       Name of rule
+     * @param     string    $pattern    Regular expression pattern
+     * @access    public
+     */
+    function addData($name, $pattern)
+    {
+        $this->_data[$name] = $pattern;
+    } // end func addData
+
+
+    function getValidationScript($options = null)
+    {
+        $regex = isset($this->_data[$this->name]) ? $this->_data[$this->name] : $options;
+
+        return array("  var regex = " . $regex . ";\n", "{jsVar} != '' && !regex.test({jsVar})");
+    } // end func getValidationScript
+
+} // end class HTML_QuickForm_Rule_Regex
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/Rule/Required.php b/lib/pear/HTML/QuickForm/Rule/Required.php
new file mode 100644 (file)
index 0000000..d7f8274
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/Rule.php');
+
+/**
+* Required elements validation
+* @version     1.0
+*/
+class HTML_QuickForm_Rule_Required extends HTML_QuickForm_Rule
+{
+    /**
+     * Checks if an element is empty
+     *
+     * @param     string    $value      Value to check
+     * @param     mixed     $options    Not used yet
+     * @access    public
+     * @return    boolean   true if value is not empty
+     */
+    function validate($value, $options = null)
+    {
+        if ((string)$value == '') {
+            return false;
+        }
+        return true;
+    } // end func validate
+
+
+    function getValidationScript($options = null)
+    {
+        return array('', "{jsVar} == ''");
+    } // end func getValidationScript
+
+} // end class HTML_QuickForm_Rule_Required
+?>
diff --git a/lib/pear/HTML/QuickForm/RuleRegistry.php b/lib/pear/HTML/QuickForm/RuleRegistry.php
new file mode 100644 (file)
index 0000000..9bb849e
--- /dev/null
@@ -0,0 +1,336 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Alexey Borzov <borz_off@cs.msu.su>                          |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+/**
+* Registers rule objects and uses them for validation
+*
+*/
+class HTML_QuickForm_RuleRegistry
+{
+    /**
+     * Array containing references to used rules
+     * @var     array
+     * @access  private
+     */
+    var $_rules = array();
+
+
+    /**
+     * Returns a singleton of HTML_QuickForm_RuleRegistry
+     *
+     * Usually, only one RuleRegistry object is needed, this is the reason
+     * why it is recommended to use this method to get the validation object. 
+     *
+     * @access    public
+     * @static
+     * @return    object    Reference to the HTML_QuickForm_RuleRegistry singleton
+     */
+    function &singleton()
+    {
+        static $obj;
+        if (!isset($obj)) {
+            $obj = new HTML_QuickForm_RuleRegistry();
+        }
+        return $obj;
+    } // end func singleton
+
+    /**
+     * Registers a new validation rule
+     *
+     * In order to use a custom rule in your form, you need to register it
+     * first. For regular expressions, one can directly use the 'regex' type
+     * rule in addRule(), this is faster than registering the rule.
+     *
+     * Functions and methods can be registered. Use the 'function' type.
+     * When registering a method, specify the class name as second parameter.
+     *
+     * You can also register an HTML_QuickForm_Rule subclass with its own
+     * validate() method.
+     *
+     * @param     string    $ruleName   Name of validation rule
+     * @param     string    $type       Either: 'regex', 'function' or null
+     * @param     string    $data1      Name of function, regular expression or
+     *                                  HTML_QuickForm_Rule object class name
+     * @param     string    $data2      Object parent of above function or HTML_QuickForm_Rule file path
+     * @access    public
+     * @return    void
+     */
+    function registerRule($ruleName, $type, $data1, $data2 = null)
+    {
+        $type = strtolower($type);
+        if ($type == 'regex') {
+            // Regular expression
+            $rule =& $this->getRule('regex');
+            $rule->addData($ruleName, $data1);
+            $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = $GLOBALS['_HTML_QuickForm_registered_rules']['regex'];
+
+        } elseif ($type == 'function' || $type == 'callback') {
+            // Callback function
+            $rule =& $this->getRule('callback');
+            $rule->addData($ruleName, $data1, $data2, 'function' == $type);
+            $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = $GLOBALS['_HTML_QuickForm_registered_rules']['callback'];
+
+        } elseif (is_object($data1)) {
+            // An instance of HTML_QuickForm_Rule
+            $this->_rules[strtolower(get_class($data1))] = $data1;
+            $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = array(strtolower(get_class($data1)), null);
+
+        } else {
+            // Rule class name
+            $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = array(strtolower($data1), $data2);
+        }
+    } // end func registerRule
+
+    /**
+     * Returns a reference to the requested rule object
+     *
+     * @param     string   $ruleName        Name of the requested rule
+     * @access    public
+     * @return    object
+     */
+    function &getRule($ruleName)
+    {
+        list($class, $path) = $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName];
+
+        if (!isset($this->_rules[$class])) {
+            if (!empty($path)) {
+                include_once($path);
+            }
+            $this->_rules[$class] =& new $class();
+        }
+        $this->_rules[$class]->setName($ruleName);
+        return $this->_rules[$class];
+    } // end func getRule
+
+    /**
+     * Performs validation on the given values
+     *
+     * @param     string   $ruleName        Name of the rule to be used
+     * @param     mixed    $values          Can be a scalar or an array of values 
+     *                                      to be validated
+     * @param     mixed    $options         Options used by the rule
+     * @param     mixed    $multiple        Whether to validate an array of values altogether
+     * @access    public
+     * @return    mixed    true if no error found, int of valid values (when an array of values is given) or false if error
+     */
+    function validate($ruleName, $values, $options = null, $multiple = false)
+    {
+        $rule =& $this->getRule($ruleName);
+
+        if (is_array($values) && !$multiple) {
+            $result = 0;
+            foreach ($values as $value) {
+                if ($rule->validate($value, $options) === true) {
+                    $result++;
+                }
+            }
+            return ($result == 0) ? false : $result;
+        } else {
+            return $rule->validate($values, $options);
+        }
+    } // end func validate
+
+    /**
+     * Returns the validation test in javascript code
+     *
+     * @param     mixed     Element(s) the rule applies to
+     * @param     string    Element name, in case $element is not array
+     * @param     array     Rule data
+     * @access    public
+     * @return    string    JavaScript for the rule
+     */
+    function getValidationScript(&$element, $elementName, $ruleData)
+    {
+        $reset =  (isset($ruleData['reset'])) ? $ruleData['reset'] : false;
+        $rule  =& $this->getRule($ruleData['type']);
+        if (!is_array($element)) {
+            list($jsValue, $jsReset) = $this->_getJsValue($element, $elementName, $reset, null);
+        } else {
+            $jsValue = "  value = new Array();\n";
+            $jsReset = '';
+            for ($i = 0; $i < count($element); $i++) {
+                list($tmp_value, $tmp_reset) = $this->_getJsValue($element[$i], $element[$i]->getName(), $reset, $i);
+                $jsValue .= "\n" . $tmp_value;
+                $jsReset .= $tmp_reset;
+            }
+        }
+        $jsField = isset($ruleData['group'])? $ruleData['group']: $elementName;
+        list ($jsPrefix, $jsCheck) = $rule->getValidationScript($ruleData['format']);
+        if (!isset($ruleData['howmany'])) {
+            $js = $jsValue . "\n" . $jsPrefix . 
+                  "  if (" . str_replace('{jsVar}', 'value', $jsCheck) . " && !errFlag['{$jsField}']) {\n" .
+                  "    errFlag['{$jsField}'] = true;\n" .
+                  "    _qfMsg = _qfMsg + '\\n - {$ruleData['message']}';\n" .
+                  $jsReset .
+                  "  }\n";
+        } else {
+            $js = $jsValue . "\n" . $jsPrefix . 
+                  "  var res = 0;\n" .
+                  "  for (var i = 0; i < value.length; i++) {\n" .
+                  "    if (!(" . str_replace('{jsVar}', 'value[i]', $jsCheck) . ")) {\n" .
+                  "      res++;\n" .
+                  "    }\n" .
+                  "  }\n" . 
+                  "  if (res < {$ruleData['howmany']} && !errFlag['{$jsField}']) {\n" . 
+                  "    errFlag['{$jsField}'] = true;\n" .
+                  "    _qfMsg = _qfMsg + '\\n - {$ruleData['message']}';\n" .
+                  $jsReset .
+                  "  }\n";
+        }
+        return $js;
+    } // end func getValidationScript
+
+
+   /**
+    * Returns JavaScript to get and to reset the element's value 
+    * 
+    * @access private
+    * @param  object HTML_QuickForm_element     element being processed
+    * @param  string    element's name
+    * @param  bool      whether to generate JavaScript to reset the value
+    * @param  integer   value's index in the array (only used for multielement rules)
+    * @return array     first item is value javascript, second is reset
+    */
+    function _getJsValue(&$element, $elementName, $reset = false, $index = null)
+    {
+        $jsIndex = isset($index)? '[' . $index . ']': '';
+        $tmp_reset = $reset? "    var field = frm.elements['$elementName'];\n": '';
+        if (is_a($element, 'html_quickform_group')) {
+            $value = "  _qfGroups['{$elementName}'] = {";
+            $elements =& $element->getElements();
+            for ($i = 0, $count = count($elements); $i < $count; $i++) {
+                $append = ($elements[$i]->getType() == 'select' && $elements[$i]->getMultiple())? '[]': '';
+                $value .= "'" . $element->getElementName($i) . $append . "': true" .
+                          ($i < $count - 1? ', ': '');
+            }
+            $value .=
+                "};\n" .
+                "  value{$jsIndex} = new Array();\n" .
+                "  var valueIdx = 0;\n" .
+                "  for (var i = 0; i < frm.elements.length; i++) {\n" .
+                "    var _element = frm.elements[i];\n" .
+                "    if (_element.name in _qfGroups['{$elementName}']) {\n" . 
+                "      switch (_element.type) {\n" .
+                "        case 'checkbox':\n" .
+                "        case 'radio':\n" .
+                "          if (_element.checked) {\n" .
+                "            value{$jsIndex}[valueIdx++] = _element.value;\n" .
+                "          }\n" .
+                "          break;\n" .
+                "        case 'select-one':\n" .
+                "          if (-1 != _element.selectedIndex) {\n" .
+                "            value{$jsIndex}[valueIdx++] = _element.options[_element.selectedIndex].value;\n" .
+                "          }\n" .
+                "          break;\n" .
+                "        case 'select-multiple':\n" .
+                "          var tmpVal = new Array();\n" .
+                "          var tmpIdx = 0;\n" .
+                "          for (var j = 0; j < _element.options.length; j++) {\n" .
+                "            if (_element.options[j].selected) {\n" .
+                "              tmpVal[tmpIdx++] = _element.options[j].value;\n" .
+                "            }\n" .
+                "          }\n" .
+                "          if (tmpIdx > 0) {\n" .
+                "            value{$jsIndex}[valueIdx++] = tmpVal;\n" .
+                "          }\n" .
+                "          break;\n" .
+                "        default:\n" .
+                "          value{$jsIndex}[valueIdx++] = _element.value;\n" .
+                "      }\n" .
+                "    }\n" .
+                "  }\n";
+            if ($reset) {
+                $tmp_reset =
+                    "    for (var i = 0; i < frm.elements.length; i++) {\n" .
+                    "      var _element = frm.elements[i];\n" .
+                    "      if (_element.name in _qfGroups['{$elementName}']) {\n" . 
+                    "        switch (_element.type) {\n" .
+                    "          case 'checkbox':\n" .
+                    "          case 'radio':\n" .
+                    "            _element.checked = _element.defaultChecked;\n" .
+                    "            break;\n" .
+                    "          case 'select-one':\n" .
+                    "          case 'select-multiple':\n" .
+                    "            for (var j = 0; j < _element.options.length; j++) {\n" .
+                    "              _element.options[j].selected = _element.options[j].defaultSelected;\n" .
+                    "            }\n" .
+                    "            break;\n" .
+                    "          default:\n" .
+                    "            _element.value = _element.defaultValue;\n" .
+                    "        }\n" .
+                    "      }\n" .
+                    "    }\n";
+            }
+
+        } elseif ($element->getType() == 'select') {
+            if ($element->getMultiple()) {
+                $elementName .= '[]';
+                $value =
+                    "  value{$jsIndex} = new Array();\n" .
+                    "  var valueIdx = 0;\n" .
+                    "  for (var i = 0; i < frm.elements['{$elementName}'].options.length; i++) {\n" . 
+                    "    if (frm.elements['{$elementName}'].options[i].selected) {\n" .
+                    "      value{$jsIndex}[valueIdx++] = frm.elements['{$elementName}'].options[i].value;\n" .
+                    "    }\n" .
+                    "  }\n";
+            } else {
+                $value = "  value{$jsIndex} = frm.elements['{$elementName}'].selectedIndex == -1? '': frm.elements['{$elementName}'].options[frm.elements['{$elementName}'].selectedIndex].value;\n";
+            }
+            if ($reset) {
+                $tmp_reset .= 
+                    "    for (var i = 0; i < field.options.length; i++) {\n" .
+                    "      field.options[i].selected = field.options[i].defaultSelected;\n" .
+                    "    }\n";
+            }
+
+        } elseif ($element->getType() == 'checkbox') {
+            if (is_a($element, 'html_quickform_advcheckbox')) {
+                $value = "  value{$jsIndex} = frm.elements['$elementName'][1].checked? frm.elements['$elementName'][1].value: frm.elements['$elementName'][0].value;\n";
+                $tmp_reset .= $reset ? "    field[1].checked = field[1].defaultChecked;\n" : '';
+            } else {
+                $value = "  value{$jsIndex} = frm.elements['$elementName'].checked? '1': '';\n";
+                $tmp_reset .= $reset ? "    field.checked = field.defaultChecked;\n" : '';
+            }
+
+        } elseif ($element->getType() == 'radio') {
+            $value = "  value{$jsIndex} = '';\n" .
+                     // Fix for bug #5644
+                     "  var els = 'length' in frm.elements['$elementName']? frm.elements['$elementName']: [ frm.elements['$elementName'] ];\n" .
+                     "  for (var i = 0; i < els.length; i++) {\n" .
+                     "    if (els[i].checked) {\n" .
+                     "      value{$jsIndex} = els[i].value;\n" .
+                     "    }\n" .
+                     "  }";
+            if ($reset) {
+                $tmp_reset .= "    for (var i = 0; i < field.length; i++) {\n" .
+                              "      field[i].checked = field[i].defaultChecked;\n" .
+                              "    }";
+            }
+
+        } else {
+            $value = "  value{$jsIndex} = frm.elements['$elementName'].value;";
+            $tmp_reset .= ($reset) ? "    field.value = field.defaultValue;\n" : '';
+        }
+        return array($value, $tmp_reset);
+    }
+} // end class HTML_QuickForm_RuleRegistry
+?>
diff --git a/lib/pear/HTML/QuickForm/advcheckbox.php b/lib/pear/HTML/QuickForm/advcheckbox.php
new file mode 100644 (file)
index 0000000..0a9089f
--- /dev/null
@@ -0,0 +1,277 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/checkbox.php');
+
+/**
+ * HTML class for an advanced checkbox type field
+ *
+ * Basically this fixes a problem that HTML has had
+ * where checkboxes can only pass a single value (the
+ * value of the checkbox when checked).  A value for when
+ * the checkbox is not checked cannot be passed, and 
+ * furthermore the checkbox variable doesn't even exist if
+ * the checkbox was submitted unchecked.
+ *
+ * It works by prepending a hidden field with the same name and
+ * another "unchecked" value to the checbox. If the checkbox is
+ * checked, PHP overwrites the value of the hidden field with
+ * its value. 
+ * 
+ * @author       Jason Rust <jrust@php.net>
+ * @since        2.0
+ * @access       public
+ */
+class HTML_QuickForm_advcheckbox extends HTML_QuickForm_checkbox
+{
+    // {{{ properties
+
+    /**
+     * The values passed by the hidden elment
+     *
+     * @var array
+     * @access private
+     */
+    var $_values = null;
+
+    /**
+     * The default value
+     *
+     * @var boolean
+     * @access private
+     */
+    var $_currentValue = null;
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementName    (optional)Input field name attribute
+     * @param     string    $elementLabel   (optional)Input field label 
+     * @param     string    $text           (optional)Text to put after the checkbox
+     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
+     *                                      or an associative array
+     * @param     mixed     $values         (optional)Values to pass if checked or not checked 
+     *
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_advcheckbox($elementName=null, $elementLabel=null, $text=null, $attributes=null, $values=null)
+    {
+        $this->HTML_QuickForm_checkbox($elementName, $elementLabel, $text, $attributes);
+        $this->setValues($values);
+    } //end constructor
+    
+    // }}}
+    // {{{ getPrivateName()
+
+    /**
+     * Gets the private name for the element
+     *
+     * @param   string  $elementName The element name to make private
+     *
+     * @access public
+     * @return string
+     *
+     * @deprecated          Deprecated since 3.2.6, both generated elements have the same name
+     */
+    function getPrivateName($elementName)
+    {
+        return '__'.$elementName;
+    }
+
+    // }}}
+    // {{{ getOnclickJs()
+
+    /**
+     * Create the javascript for the onclick event which will
+     * set the value of the hidden field
+     *
+     * @param     string    $elementName    The element name
+     *
+     * @access public
+     * @return string
+     *
+     * @deprecated          Deprecated since 3.2.6, this element no longer uses any javascript
+     */
+    function getOnclickJs($elementName)
+    {
+        $onclickJs = 'if (this.checked) { this.form[\''.$elementName.'\'].value=\''.addcslashes($this->_values[1], '\'').'\'; }';
+        $onclickJs .= 'else { this.form[\''.$elementName.'\'].value=\''.addcslashes($this->_values[0], '\'').'\'; }';
+        return $onclickJs;
+    }
+
+    // }}}
+    // {{{ setValues()
+
+    /**
+     * Sets the values used by the hidden element
+     *
+     * @param   mixed   $values The values, either a string or an array
+     *
+     * @access public
+     * @return void
+     */
+    function setValues($values)
+    {
+        if (empty($values)) {
+            // give it default checkbox behavior
+            $this->_values = array('', 1);
+        } elseif (is_scalar($values)) {
+            // if it's string, then assume the value to 
+            // be passed is for when the element is checked
+            $this->_values = array('', $values);
+        } else {
+            $this->_values = $values;
+        }
+        $this->updateAttributes(array('value' => $this->_values[1]));
+        $this->setChecked($this->_currentValue == $this->_values[1]);
+    }
+
+    // }}}
+    // {{{ setValue()
+
+   /**
+    * Sets the element's value
+    * 
+    * @param    mixed   Element's value
+    * @access   public
+    */
+    function setValue($value)
+    {
+        $this->setChecked(isset($this->_values[1]) && $value == $this->_values[1]);
+        $this->_currentValue = $value;
+    }
+
+    // }}}
+    // {{{ getValue()
+
+   /**
+    * Returns the element's value
+    *
+    * @access   public
+    * @return   mixed
+    */
+    function getValue()
+    {
+        if (is_array($this->_values)) {
+            return $this->_values[$this->getChecked()? 1: 0];
+        } else {
+            return null;
+        }
+    }
+
+    // }}}
+    // {{{ toHtml()
+
+    /**
+     * Returns the checkbox element in HTML
+     * and the additional hidden element in HTML
+     * 
+     * @access    public
+     * @return    string
+     */
+    function toHtml()
+    {
+        if ($this->_flagFrozen) {
+            return parent::toHtml();
+        } else {
+            return '<input' . $this->_getAttrString(array(
+                        'type'  => 'hidden', 
+                        'name'  => $this->getName(), 
+                        'value' => $this->_values[0]
+                   )) . ' />' . parent::toHtml();
+            
+        }
+    } //end func toHtml
+    
+    // }}}
+    // {{{ getFrozenHtml()
+
+   /**
+    * Unlike checkbox, this has to append a hidden input in both
+    * checked and non-checked states
+    */
+    function getFrozenHtml()
+    {
+        return ($this->getChecked()? '<tt>[x]</tt>': '<tt>[ ]</tt>') .
+               $this->_getPersistantData();
+    }
+
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    /**
+     * Called by HTML_QuickForm whenever form event is made on this element
+     *
+     * @param     string    $event  Name of event
+     * @param     mixed     $arg    event arguments
+     * @param     object    $caller calling object
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        switch ($event) {
+            case 'updateValue':
+                // constant values override both default and submitted ones
+                // default values are overriden by submitted
+                $value = $this->_findValue($caller->_constantValues);
+                if (null === $value) {
+                    $value = $this->_findValue($caller->_submitValues);
+                    if (null === $value) {
+                        $value = $this->_findValue($caller->_defaultValues);
+                    }
+                }
+                if (null !== $value) {
+                    $this->setValue($value);
+                }
+                break;
+            default:
+                parent::onQuickFormEvent($event, $arg, $caller);
+        }
+        return true;
+    } // end func onQuickFormLoad
+
+    // }}}
+    // {{{ exportValue()
+
+   /**
+    * This element has a value even if it is not checked, thus we override
+    * checkbox's behaviour here
+    */
+    function exportValue(&$submitValues, $assoc)
+    {
+        $value = $this->_findValue($submitValues);
+        if (null === $value) {
+            $value = $this->getValue();
+        } elseif (is_array($this->_values) && ($value != $this->_values[0]) && ($value != $this->_values[1])) {
+            $value = null;
+        }
+        return $this->_prepareValue($value, $assoc);
+    }
+    // }}}
+} //end class HTML_QuickForm_advcheckbox
+?>
diff --git a/lib/pear/HTML/QuickForm/autocomplete.php b/lib/pear/HTML/QuickForm/autocomplete.php
new file mode 100644 (file)
index 0000000..c39bd8d
--- /dev/null
@@ -0,0 +1,249 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Author:  Matteo Di Giovinazzo <matteodg@infinito.it>                 |
+// |                                                                      |
+// | For the JavaScript code thanks to Martin Honnen and                  |
+// | Nicholas C. Zakas                                                    |
+// | See:                                                                 |
+// |      http://www.faqts.com/knowledge_base/view.phtml/aid/13562        |
+// | and                                                                  |
+// |      http://www.sitepoint.com/article/1220                           |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+
+require_once("HTML/QuickForm/text.php");
+
+
+/**
+ * Class to dynamically create an HTML input text element that
+ * at every keypressed javascript event, check in an array of options
+ * if there's a match and autocomplete the text in case of match.
+ *
+ * Ex:
+ * $autocomplete =& $form->addElement('autocomplete', 'fruit', 'Favourite fruit:');
+ * $options = array("Apple", "Orange", "Pear", "Strawberry");
+ * $autocomplete->setOptions($options);
+ *
+ * @author       Matteo Di Giovinazzo <matteodg@infinito.it>
+ */
+class HTML_QuickForm_autocomplete extends HTML_QuickForm_text
+{
+    // {{{ properties
+
+    /**
+     * Options for the autocomplete input text element
+     *
+     * @var       array
+     * @access    private
+     */
+    var $_options = array();
+
+    /**
+     * "One-time" javascript (containing functions), see bug #4611
+     *
+     * @var     string
+     * @access  private
+     */
+    var $_js = '';
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     *
+     * @param     string    $elementName    (optional)Input field name attribute
+     * @param     string    $elementLabel   (optional)Input field label in form
+     * @param     array     $options        (optional)Autocomplete options
+     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string
+     *                                      or an associative array. Date format is passed along the attributes.
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_autocomplete($elementName = null, $elementLabel = null, $options = null, $attributes = null)
+    {
+        $this->HTML_QuickForm_text($elementName, $elementLabel, $attributes);
+        $this->_persistantFreeze = true;
+        $this->_type = 'autocomplete';
+        if (isset($options)) {
+            $this->setOptions($options);
+        }
+    } //end constructor
+
+    // }}}
+    // {{{ setOptions()
+
+    /**
+     * Sets the options for the autocomplete input text element
+     *
+     * @param     array    $options    Array of options for the autocomplete input text element
+     * @access    public
+     * @return    void
+     */
+    function setOptions($options)
+    {
+        $this->_options = array_values($options);
+    } // end func setOptions
+
+    // }}}
+    // {{{ toHtml()
+
+    /**
+     * Returns Html for the autocomplete input text element
+     *
+     * @access      public
+     * @return      string
+     */
+    function toHtml()
+    {
+        // prevent problems with grouped elements
+        $arrayName = str_replace(array('[', ']'), array('__', ''), $this->getName()) . '_values';
+
+        $this->updateAttributes(array(
+            'onkeypress' => 'return autocomplete(this, event, ' . $arrayName . ');'
+        ));
+        if ($this->_flagFrozen) {
+            $js = '';
+        } else {
+            $js = "<script type=\"text/javascript\">\n//<![CDATA[\n";
+            if (!defined('HTML_QUICKFORM_AUTOCOMPLETE_EXISTS')) {
+                $this->_js .= <<<EOS
+
+/* begin javascript for autocomplete */
+function setSelectionRange(input, selectionStart, selectionEnd) {
+    if (input.setSelectionRange) {
+        input.setSelectionRange(selectionStart, selectionEnd);
+    }
+    else if (input.createTextRange) {
+        var range = input.createTextRange();
+        range.collapse(true);
+        range.moveEnd("character", selectionEnd);
+        range.moveStart("character", selectionStart);
+        range.select();
+    }
+    input.focus();
+}
+
+function setCaretToPosition(input, position) {
+    setSelectionRange(input, position, position);
+}
+
+function replaceSelection (input, replaceString) {
+       var len = replaceString.length;
+    if (input.setSelectionRange) {
+        var selectionStart = input.selectionStart;
+        var selectionEnd = input.selectionEnd;
+
+        input.value = input.value.substring(0, selectionStart) + replaceString + input.value.substring(selectionEnd);
+               input.selectionStart  = selectionStart + len;
+               input.selectionEnd  = selectionStart + len;
+    }
+    else if (document.selection) {
+        var range = document.selection.createRange();
+               var saved_range = range.duplicate();
+
+        if (range.parentElement() == input) {
+            range.text = replaceString;
+                       range.moveEnd("character", saved_range.selectionStart + len);
+                       range.moveStart("character", saved_range.selectionStart + len);
+                       range.select();
+        }
+    }
+    input.focus();
+}
+
+
+function autocompleteMatch (text, values) {
+    for (var i = 0; i < values.length; i++) {
+        if (values[i].toUpperCase().indexOf(text.toUpperCase()) == 0) {
+            return values[i];
+        }
+    }
+
+    return null;
+}
+
+function autocomplete(textbox, event, values) {
+    if (textbox.setSelectionRange || textbox.createTextRange) {
+        switch (event.keyCode) {
+            case 38:    // up arrow
+            case 40:    // down arrow
+            case 37:    // left arrow
+            case 39:    // right arrow
+            case 33:    // page up
+            case 34:    // page down
+            case 36:    // home
+            case 35:    // end
+            case 13:    // enter
+            case 9:     // tab
+            case 27:    // esc
+            case 16:    // shift
+            case 17:    // ctrl
+            case 18:    // alt
+            case 20:    // caps lock
+            case 8:     // backspace
+            case 46:    // delete
+                return true;
+                break;
+
+            default:
+                var c = String.fromCharCode(
+                    (event.charCode == undefined) ? event.keyCode : event.charCode
+                );
+                replaceSelection(textbox, c);
+                sMatch = autocompleteMatch(textbox.value, values);
+                var len = textbox.value.length;
+                               
+                if (sMatch != null) {
+                    textbox.value = sMatch;
+                    setSelectionRange(textbox, len, textbox.value.length);
+                }
+                return false;
+        }
+    }
+    else {
+        return true;
+    }
+}
+/* end javascript for autocomplete */
+
+EOS;
+                define('HTML_QUICKFORM_AUTOCOMPLETE_EXISTS', true);
+            }
+            $jsEscape = array(
+                "\r"    => '\r',
+                "\n"    => '\n',
+                "\t"    => '\t',
+                "'"     => "\\'",
+                '"'     => '\"',
+                '\\'    => '\\\\'
+            );
+
+            $js .= $this->_js;
+            $js .= 'var ' . $arrayName . " = new Array();\n";
+            for ($i = 0; $i < count($this->_options); $i++) {
+                $js .= $arrayName . '[' . $i . "] = '" . strtr($this->_options[$i], $jsEscape) . "';\n";
+            }
+            $js .= "//]]>\n</script>";
+        }
+        return $js . parent::toHtml();
+    }// end func toHtml
+
+    // }}}
+} // end class HTML_QuickForm_autocomplete
+?>
diff --git a/lib/pear/HTML/QuickForm/button.php b/lib/pear/HTML/QuickForm/button.php
new file mode 100644 (file)
index 0000000..bf6f10e
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/input.php");
+
+/**
+ * HTML class for a button type element
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.1
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_button extends HTML_QuickForm_input
+{
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementName    (optional)Input field name attribute
+     * @param     string    $value          (optional)Input field value
+     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
+     *                                      or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_button($elementName=null, $value=null, $attributes=null)
+    {
+        HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes);
+        $this->_persistantFreeze = false;
+        $this->setValue($value);
+        $this->setType('button');
+    } //end constructor
+    
+    // }}}
+    // {{{ freeze()
+
+    /**
+     * Freeze the element so that only its value is returned
+     * 
+     * @access    public
+     * @return    void
+     */
+    function freeze()
+    {
+        return false;
+    } //end func freeze
+
+    // }}}
+} //end class HTML_QuickForm_button
+?>
diff --git a/lib/pear/HTML/QuickForm/checkbox.php b/lib/pear/HTML/QuickForm/checkbox.php
new file mode 100644 (file)
index 0000000..55c7574
--- /dev/null
@@ -0,0 +1,268 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/input.php");
+
+/**
+ * HTML class for a checkbox type field
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.1
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_checkbox extends HTML_QuickForm_input
+{
+    // {{{ properties
+
+    /**
+     * Checkbox display text
+     * @var       string
+     * @since     1.1
+     * @access    private
+     */
+    var $_text = '';
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementName    (optional)Input field name attribute
+     * @param     string    $elementLabel   (optional)Input field value
+     * @param     string    $text           (optional)Checkbox display text
+     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
+     *                                      or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_checkbox($elementName=null, $elementLabel=null, $text='', $attributes=null)
+    {
+        HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
+        $this->_persistantFreeze = true;
+        $this->_text = $text;
+        $this->setType('checkbox');
+        $this->updateAttributes(array('value'=>1));
+        $this->_generateId();
+    } //end constructor
+    
+    // }}}
+    // {{{ setChecked()
+
+    /**
+     * Sets whether a checkbox is checked
+     * 
+     * @param     bool    $checked  Whether the field is checked or not
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setChecked($checked)
+    {
+        if (!$checked) {
+            $this->removeAttribute('checked');
+        } else {
+            $this->updateAttributes(array('checked'=>'checked'));
+        }
+    } //end func setChecked
+
+    // }}}
+    // {{{ getChecked()
+
+    /**
+     * Returns whether a checkbox is checked
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    bool
+     */
+    function getChecked()
+    {
+        return (bool)$this->getAttribute('checked');
+    } //end func getChecked
+    
+    // }}}
+    // {{{ toHtml()
+
+    /**
+     * Returns the checkbox element in HTML
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function toHtml()
+    {
+        if (0 == strlen($this->_text)) {
+            $label = '';
+        } elseif ($this->_flagFrozen) {
+            $label = $this->_text;
+        } else {
+            $label = '<label for="' . $this->getAttribute('id') . '">' . $this->_text . '</label>';
+        }
+        return HTML_QuickForm_input::toHtml() . $label;
+    } //end func toHtml
+    
+    // }}}
+    // {{{ getFrozenHtml()
+
+    /**
+     * Returns the value of field without HTML tags
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getFrozenHtml()
+    {
+        if ($this->getChecked()) {
+            return '<tt>[x]</tt>' .
+                   $this->_getPersistantData();
+        } else {
+            return '<tt>[ ]</tt>';
+        }
+    } //end func getFrozenHtml
+
+    // }}}
+    // {{{ setText()
+
+    /**
+     * Sets the checkbox text
+     * 
+     * @param     string    $text  
+     * @since     1.1
+     * @access    public
+     * @return    void
+     */
+    function setText($text)
+    {
+        $this->_text = $text;
+    } //end func setText
+
+    // }}}
+    // {{{ getText()
+
+    /**
+     * Returns the checkbox text 
+     * 
+     * @since     1.1
+     * @access    public
+     * @return    string
+     */
+    function getText()
+    {
+        return $this->_text;
+    } //end func getText
+
+    // }}}
+    // {{{ setValue()
+
+    /**
+     * Sets the value of the form element
+     *
+     * @param     string    $value      Default value of the form element
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setValue($value)
+    {
+        return $this->setChecked($value);
+    } // end func setValue
+
+    // }}}
+    // {{{ getValue()
+
+    /**
+     * Returns the value of the form element
+     *
+     * @since     1.0
+     * @access    public
+     * @return    bool
+     */
+    function getValue()
+    {
+        return $this->getChecked();
+    } // end func getValue
+
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    /**
+     * Called by HTML_QuickForm whenever form event is made on this element
+     *
+     * @param     string    $event  Name of event
+     * @param     mixed     $arg    event arguments
+     * @param     object    $caller calling object
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        switch ($event) {
+            case 'updateValue':
+                // constant values override both default and submitted ones
+                // default values are overriden by submitted
+                $value = $this->_findValue($caller->_constantValues);
+                if (null === $value) {
+                    // if no boxes were checked, then there is no value in the array
+                    // yet we don't want to display default value in this case
+                    if ($caller->isSubmitted()) {
+                        $value = $this->_findValue($caller->_submitValues);
+                    } else {
+                        $value = $this->_findValue($caller->_defaultValues);
+                    }
+                }
+                if (null !== $value) {
+                    $this->setChecked($value);
+                }
+                break;
+            case 'setGroupValue':
+                $this->setChecked($arg);
+                break;
+            default:
+                parent::onQuickFormEvent($event, $arg, $caller);
+        }
+        return true;
+    } // end func onQuickFormEvent
+
+    // }}}
+    // {{{ exportValue()
+
+   /**
+    * Return true if the checkbox is checked, null if it is not checked (getValue() returns false)
+    */
+    function exportValue(&$submitValues, $assoc = false)
+    {
+        $value = $this->_findValue($submitValues);
+        if (null === $value) {
+            $value = $this->getChecked()? true: null;
+        }
+        return $this->_prepareValue($value, $assoc);
+    }
+    
+    // }}}
+} //end class HTML_QuickForm_checkbox
+?>
diff --git a/lib/pear/HTML/QuickForm/date.php b/lib/pear/HTML/QuickForm/date.php
new file mode 100644 (file)
index 0000000..9ece169
--- /dev/null
@@ -0,0 +1,496 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Alexey Borzov <avb@php.net>                                 |
+// |          Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once 'HTML/QuickForm/group.php';
+require_once 'HTML/QuickForm/select.php';
+
+/**
+ * Class for a group of elements used to input dates (and times).
+ * 
+ * Inspired by original 'date' element but reimplemented as a subclass
+ * of HTML_QuickForm_group
+ * 
+ * @author Alexey Borzov <avb@php.net>
+ * @access public
+ */
+class HTML_QuickForm_date extends HTML_QuickForm_group
+{
+    // {{{ properties
+
+   /**
+    * Various options to control the element's display.
+    * 
+    * Currently known options are
+    * 'language': date language
+    * 'format': Format of the date, based on PHP's date() function.
+    *     The following characters are recognised in format string:
+    *       D => Short names of days
+    *       l => Long names of days
+    *       d => Day numbers
+    *       M => Short names of months
+    *       F => Long names of months
+    *       m => Month numbers
+    *       Y => Four digit year
+    *       y => Two digit year
+    *       h => 12 hour format
+    *       H => 23 hour  format
+    *       i => Minutes
+    *       s => Seconds
+    *       a => am/pm
+    *       A => AM/PM
+    * 'minYear': Minimum year in year select
+    * 'maxYear': Maximum year in year select
+    * 'addEmptyOption': Should an empty option be added to the top of
+    *     each select box?
+    * 'emptyOptionValue': The value passed by the empty option.
+    * 'emptyOptionText': The text displayed for the empty option.
+    * 'optionIncrement': Step to increase the option values by (works for 'i' and 's')
+    * 
+    * @access   private
+    * @var      array
+    */
+    var $_options = array(
+        'language'         => 'en',
+        'format'           => 'dMY',
+        'minYear'          => 2001,
+        'maxYear'          => 2010,
+        'addEmptyOption'   => false,
+        'emptyOptionValue' => '',
+        'emptyOptionText'  => '&nbsp;',
+        'optionIncrement'  => array('i' => 1, 's' => 1)
+    );
+
+   /**
+    * These complement separators, they are appended to the resultant HTML
+    * @access   private
+    * @var      array
+    */
+    var $_wrap = array('', '');
+
+   /**
+    * Options in different languages
+    * 
+    * Note to potential translators: to avoid encoding problems please send
+    * your translations with "weird" letters encoded as HTML Unicode entities
+    * 
+    * @access   private
+    * @var      array
+    */
+    var $_locale = array(
+        'en'    => array (
+            'weekdays_short'=> array ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'),
+            'weekdays_long' => array ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
+            'months_short'  => array ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
+            'months_long'   => array ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
+        ),
+        'de'    => array (
+            'weekdays_short'=> array ('So', 'Mon', 'Di', 'Mi', 'Do', 'Fr', 'Sa'),
+            'weekdays_long' => array ('Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'),
+            'months_short'  => array ('Jan', 'Feb', 'M&#xe4;rz', 'April', 'Mai', 'Juni', 'Juli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dez'),
+            'months_long'   => array ('Januar', 'Februar', 'M&#xe4;rz', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember')
+        ),
+        'fr'    => array (
+            'weekdays_short'=> array ('Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'),
+            'weekdays_long' => array ('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'),
+            'months_short'  => array ('Jan', 'F&#xe9;v', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Ao&#xfb;t', 'Sep', 'Oct', 'Nov', 'D&#xe9;c'),
+            'months_long'   => array ('Janvier', 'F&#xe9;vrier', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Ao&#xfb;t', 'Septembre', 'Octobre', 'Novembre', 'D&#xe9;cembre')
+        ),
+        'hu'    => array (
+            'weekdays_short'=> array ('V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'),
+            'weekdays_long' => array ('vas&#xe1;rnap', 'h&#xe9;tf&#x151;', 'kedd', 'szerda', 'cs&#xfc;t&#xf6;rt&#xf6;k', 'p&#xe9;ntek', 'szombat'),
+            'months_short'  => array ('jan', 'feb', 'm&#xe1;rc', '&#xe1;pr', 'm&#xe1;j', 'j&#xfa;n', 'j&#xfa;l', 'aug', 'szept', 'okt', 'nov', 'dec'),
+            'months_long'   => array ('janu&#xe1;r', 'febru&#xe1;r', 'm&#xe1;rcius', '&#xe1;prilis', 'm&#xe1;jus', 'j&#xfa;nius', 'j&#xfa;lius', 'augusztus', 'szeptember', 'okt&#xf3;ber', 'november', 'december')
+        ),
+        'pl'    => array (
+            'weekdays_short'=> array ('Nie', 'Pn', 'Wt', '&#x15a;r', 'Czw', 'Pt', 'Sob'),
+            'weekdays_long' => array ('Niedziela', 'Poniedzia&#x142;ek', 'Wtorek', '&#x15a;roda', 'Czwartek', 'Pi&#x105;tek', 'Sobota'),
+            'months_short'  => array ('Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze', 'Lip', 'Sie', 'Wrz', 'Pa&#x17a;', 'Lis', 'Gru'),
+            'months_long'   => array ('Stycze&#x144;', 'Luty', 'Marzec', 'Kwiecie&#x144;', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpie&#x144;', 'Wrzesie&#x144;', 'Pa&#x17a;dziernik', 'Listopad', 'Grudzie&#x144;')
+        ),
+        'sl'    => array (
+            'weekdays_short'=> array ('Ned', 'Pon', 'Tor', 'Sre', 'Cet', 'Pet', 'Sob'),
+            'weekdays_long' => array ('Nedelja', 'Ponedeljek', 'Torek', 'Sreda', 'Cetrtek', 'Petek', 'Sobota'),
+            'months_short'  => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Avg', 'Sep', 'Okt', 'Nov', 'Dec'),
+            'months_long'   => array ('Januar', 'Februar', 'Marec', 'April', 'Maj', 'Junij', 'Julij', 'Avgust', 'September', 'Oktober', 'November', 'December')
+        ),
+        'ru'    => array (
+            'weekdays_short'=> array ('&#x412;&#x441;', '&#x41f;&#x43d;', '&#x412;&#x442;', '&#x421;&#x440;', '&#x427;&#x442;', '&#x41f;&#x442;', '&#x421;&#x431;'),
+            'weekdays_long' => array ('&#x412;&#x43e;&#x441;&#x43a;&#x440;&#x435;&#x441;&#x435;&#x43d;&#x44c;&#x435;', '&#x41f;&#x43e;&#x43d;&#x435;&#x434;&#x435;&#x43b;&#x44c;&#x43d;&#x438;&#x43a;', '&#x412;&#x442;&#x43e;&#x440;&#x43d;&#x438;&#x43a;', '&#x421;&#x440;&#x435;&#x434;&#x430;', '&#x427;&#x435;&#x442;&#x432;&#x435;&#x440;&#x433;', '&#x41f;&#x44f;&#x442;&#x43d;&#x438;&#x446;&#x430;', '&#x421;&#x443;&#x431;&#x431;&#x43e;&#x442;&#x430;'),
+            'months_short'  => array ('&#x42f;&#x43d;&#x432;', '&#x424;&#x435;&#x432;', '&#x41c;&#x430;&#x440;', '&#x410;&#x43f;&#x440;', '&#x41c;&#x430;&#x439;', '&#x418;&#x44e;&#x43d;', '&#x418;&#x44e;&#x43b;', '&#x410;&#x432;&#x433;', '&#x421;&#x435;&#x43d;', '&#x41e;&#x43a;&#x442;', '&#x41d;&#x43e;&#x44f;', '&#x414;&#x435;&#x43a;'),
+            'months_long'   => array ('&#x42f;&#x43d;&#x432;&#x430;&#x440;&#x44c;', '&#x424;&#x435;&#x432;&#x440;&#x430;&#x43b;&#x44c;', '&#x41c;&#x430;&#x440;&#x442;', '&#x410;&#x43f;&#x440;&#x435;&#x43b;&#x44c;', '&#x41c;&#x430;&#x439;', '&#x418;&#x44e;&#x43d;&#x44c;', '&#x418;&#x44e;&#x43b;&#x44c;', '&#x410;&#x432;&#x433;&#x443;&#x441;&#x442;', '&#x421;&#x435;&#x43d;&#x442;&#x44f;&#x431;&#x440;&#x44c;', '&#x41e;&#x43a;&#x442;&#x44f;&#x431;&#x440;&#x44c;', '&#x41d;&#x43e;&#x44f;&#x431;&#x440;&#x44c;', '&#x414;&#x435;&#x43a;&#x430;&#x431;&#x440;&#x44c;')
+        ),
+        'es'    => array (
+            'weekdays_short'=> array ('Dom', 'Lun', 'Mar', 'Mi&#xe9;', 'Jue', 'Vie', 'S&#xe1;b'),
+            'weekdays_long' => array ('Domingo', 'Lunes', 'Martes', 'Mi&#xe9;rcoles', 'Jueves', 'Viernes', 'S&#xe1;bado'),
+            'months_short'  => array ('Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'),
+            'months_long'   => array ('Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre')
+        ),
+        'da'    => array (
+            'weekdays_short'=> array ('S&#xf8;n', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'L&#xf8;r'),
+            'weekdays_long' => array ('S&#xf8;ndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'L&#xf8;rdag'),
+            'months_short'  => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'),
+            'months_long'   => array ('Januar', 'Februar', 'Marts', 'April', 'Maj', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'December')
+        ),
+        'is'    => array (
+            'weekdays_short'=> array ('Sun', 'M&#xe1;n', '&#xde;ri', 'Mi&#xf0;', 'Fim', 'F&#xf6;s', 'Lau'),
+            'weekdays_long' => array ('Sunnudagur', 'M&#xe1;nudagur', '&#xde;ri&#xf0;judagur', 'Mi&#xf0;vikudagur', 'Fimmtudagur', 'F&#xf6;studagur', 'Laugardagur'),
+            'months_short'  => array ('Jan', 'Feb', 'Mar', 'Apr', 'Ma&#xed;', 'J&#xfa;n', 'J&#xfa;l', '&#xc1;g&#xfa;', 'Sep', 'Okt', 'N&#xf3;v', 'Des'),
+            'months_long'   => array ('Jan&#xfa;ar', 'Febr&#xfa;ar', 'Mars', 'Apr&#xed;l', 'Ma&#xed;', 'J&#xfa;n&#xed;', 'J&#xfa;l&#xed;', '&#xc1;g&#xfa;st', 'September', 'Okt&#xf3;ber', 'N&#xf3;vember', 'Desember')
+        ),
+        'it'    => array (
+            'weekdays_short'=> array ('Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab'),
+            'weekdays_long' => array ('Domenica', 'Luned&#xec;', 'Marted&#xec;', 'Mercoled&#xec;', 'Gioved&#xec;', 'Venerd&#xec;', 'Sabato'),
+            'months_short'  => array ('Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic'),
+            'months_long'   => array ('Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre')
+        ),
+        'sk'    => array (
+            'weekdays_short'=> array ('Ned', 'Pon', 'Uto', 'Str', '&#x8a;tv', 'Pia', 'Sob'),
+            'weekdays_long' => array ('Nede&#x17e;a', 'Pondelok', 'Utorok', 'Streda', '&#x8a;tvrtok', 'Piatok', 'Sobota'),
+            'months_short'  => array ('Jan', 'Feb', 'Mar', 'Apr', 'M&#xe1;j', 'J&#xfa;n', 'J&#xfa;l', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'),
+            'months_long'   => array ('Janu&#xe1;r', 'Febru&#xe1;r', 'Marec', 'Apr&#xed;l', 'M&#xe1;j', 'J&#xfa;n', 'J&#xfa;l', 'August', 'September', 'Okt&#xf3;ber', 'November', 'December')
+        ),
+        'cs'    => array (
+            'weekdays_short'=> array ('Ne', 'Po', '&#xda;t', 'St', '&#x10c;t', 'P&#xe1;', 'So'),
+            'weekdays_long' => array ('Ned&#x11b;le', 'Pond&#x11b;l&#xed;', '&#xda;ter&#xfd;', 'St&#x159;eda', '&#x10c;tvrtek', 'P&#xe1;tek', 'Sobota'),
+            'months_short'  => array ('Led', '&#xda;no', 'B&#x159;e', 'Dub', 'Kv&#x11b;', '&#x10c;en', '&#x10c;ec', 'Srp', 'Z&#xe1;&#x159;', '&#x158;&#xed;j', 'Lis', 'Pro'),
+            'months_long'   => array ('Leden', '&#xda;nor', 'B&#x159;ezen', 'Duben', 'Kv&#x11b;ten', '&#x10c;erven', '&#x10c;ervenec', 'Srpen', 'Z&#xe1;&#x159;&#xed;', '&#x158;&#xed;jen', 'Listopad', 'Prosinec')
+        ),
+        'hy'    => array (
+            'weekdays_short'=> array ('&#x53f;&#x580;&#x56f;', '&#x535;&#x580;&#x56f;', '&#x535;&#x580;&#x584;', '&#x549;&#x580;&#x584;', '&#x540;&#x576;&#x563;', '&#x548;&#x582;&#x580;', '&#x547;&#x562;&#x569;'),
+            'weekdays_long' => array ('&#x53f;&#x56b;&#x580;&#x561;&#x56f;&#x56b;', '&#x535;&#x580;&#x56f;&#x578;&#x582;&#x577;&#x561;&#x562;&#x569;&#x56b;', '&#x535;&#x580;&#x565;&#x584;&#x577;&#x561;&#x562;&#x569;&#x56b;', '&#x549;&#x578;&#x580;&#x565;&#x584;&#x577;&#x561;&#x562;&#x569;&#x56b;', '&#x540;&#x56b;&#x576;&#x563;&#x577;&#x561;&#x562;&#x569;&#x56b;', '&#x548;&#x582;&#x580;&#x562;&#x561;&#x569;', '&#x547;&#x561;&#x562;&#x561;&#x569;'),
+            'months_short'  => array ('&#x540;&#x576;&#x57e;', '&#x553;&#x57f;&#x580;', '&#x544;&#x580;&#x57f;', '&#x531;&#x57a;&#x580;', '&#x544;&#x575;&#x57d;', '&#x540;&#x576;&#x57d;', '&#x540;&#x56c;&#x57d;', '&#x555;&#x563;&#x57d;', '&#x54d;&#x57a;&#x57f;', '&#x540;&#x56f;&#x57f;', '&#x546;&#x575;&#x574;', '&#x534;&#x56f;&#x57f;'),
+            'months_long'   => array ('&#x540;&#x578;&#x582;&#x576;&#x57e;&#x561;&#x580;', '&#x553;&#x565;&#x57f;&#x580;&#x57e;&#x561;&#x580;', '&#x544;&#x561;&#x580;&#x57f;', '&#x531;&#x57a;&#x580;&#x56b;&#x56c;', '&#x544;&#x561;&#x575;&#x56b;&#x57d;', '&#x540;&#x578;&#x582;&#x576;&#x56b;&#x57d;', '&#x540;&#x578;&#x582;&#x56c;&#x56b;&#x57d;', '&#x555;&#x563;&#x578;&#x57d;&#x57f;&#x578;&#x57d;', '&#x54d;&#x565;&#x57a;&#x57f;&#x565;&#x574;&#x562;&#x565;&#x580;', '&#x540;&#x578;&#x56f;&#x57f;&#x565;&#x574;&#x562;&#x565;&#x580;', '&#x546;&#x578;&#x575;&#x565;&#x574;&#x562;&#x565;&#x580;', '&#x534;&#x565;&#x56f;&#x57f;&#x565;&#x574;&#x562;&#x565;&#x580;')
+        ),
+        'nl'    => array (
+            'weekdays_short'=> array ('Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'),
+            'weekdays_long' => array ('Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag'),
+            'months_short'  => array ('Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'),
+            'months_long'   => array ('Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December')
+        ),
+        'et'    => array (
+            'weekdays_short'=> array ('P', 'E', 'T', 'K', 'N', 'R', 'L'),
+            'weekdays_long' => array ('P&#xfc;hap&#xe4;ev', 'Esmasp&#xe4;ev', 'Teisip&#xe4;ev', 'Kolmap&#xe4;ev', 'Neljap&#xe4;ev', 'Reede', 'Laup&#xe4;ev'),
+            'months_short'  => array ('Jaan', 'Veebr', 'M&#xe4;rts', 'Aprill', 'Mai', 'Juuni', 'Juuli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dets'),
+            'months_long'   => array ('Jaanuar', 'Veebruar', 'M&#xe4;rts', 'Aprill', 'Mai', 'Juuni', 'Juuli', 'August', 'September', 'Oktoober', 'November', 'Detsember')
+        ),
+        'tr'    => array (
+            'weekdays_short'=> array ('Paz', 'Pzt', 'Sal', '&#xc7;ar', 'Per', 'Cum', 'Cts'),
+            'weekdays_long' => array ('Pazar', 'Pazartesi', 'Sal&#x131;', '&#xc7;ar&#x15f;amba', 'Per&#x15f;embe', 'Cuma', 'Cumartesi'),
+            'months_short'  => array ('Ock', '&#x15e;bt', 'Mrt', 'Nsn', 'Mys', 'Hzrn', 'Tmmz', 'A&#x11f;st', 'Eyl', 'Ekm', 'Ksm', 'Arlk'),
+            'months_long'   => array ('Ocak', '&#x15e;ubat', 'Mart', 'Nisan', 'May&#x131;s', 'Haziran', 'Temmuz', 'A&#x11f;ustos', 'Eyl&#xfc;l', 'Ekim', 'Kas&#x131;m', 'Aral&#x131;k')
+        ),
+        'no'    => array (
+            'weekdays_short'=> array ('S&#xf8;n', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'L&#xf8;r'),
+            'weekdays_long' => array ('S&#xf8;ndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'L&#xf8;rdag'),
+            'months_short'  => array ('Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'),
+            'months_long'   => array ('Januar', 'Februar', 'Mars', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Desember')
+        ),
+        'eo'    => array (
+            'weekdays_short'=> array ('Dim', 'Lun', 'Mar', 'Mer', '&#x134;a&#x16D;', 'Ven', 'Sab'),
+            'weekdays_long' => array ('Diman&#x109;o', 'Lundo', 'Mardo', 'Merkredo', '&#x134;a&#x16D;do', 'Vendredo', 'Sabato'),
+            'months_short'  => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'A&#x16D;g', 'Sep', 'Okt', 'Nov', 'Dec'),
+            'months_long'   => array ('Januaro', 'Februaro', 'Marto', 'Aprilo', 'Majo', 'Junio', 'Julio', 'A&#x16D;gusto', 'Septembro', 'Oktobro', 'Novembro', 'Decembro')
+        ),
+        'ua'    => array (
+            'weekdays_short'=> array('&#x41d;&#x434;&#x43b;', '&#x41f;&#x43d;&#x434;', '&#x412;&#x442;&#x440;', '&#x421;&#x440;&#x434;', '&#x427;&#x442;&#x432;', '&#x41f;&#x442;&#x43d;', '&#x421;&#x431;&#x442;'),
+            'weekdays_long' => array('&#x41d;&#x435;&#x434;&#x456;&#x43b;&#x44f;', '&#x41f;&#x43e;&#x43d;&#x435;&#x434;&#x456;&#x43b;&#x43e;&#x43a;', '&#x412;&#x456;&#x432;&#x442;&#x43e;&#x440;&#x43e;&#x43a;', '&#x421;&#x435;&#x440;&#x435;&#x434;&#x430;', '&#x427;&#x435;&#x442;&#x432;&#x435;&#x440;', '&#x41f;\'&#x44f;&#x442;&#x43d;&#x438;&#x446;&#x44f;', '&#x421;&#x443;&#x431;&#x43e;&#x442;&#x430;'),
+            'months_short'  => array('&#x421;&#x456;&#x447;', '&#x41b;&#x44e;&#x442;', '&#x411;&#x435;&#x440;', '&#x41a;&#x432;&#x456;', '&#x422;&#x440;&#x430;', '&#x427;&#x435;&#x440;', '&#x41b;&#x438;&#x43f;', '&#x421;&#x435;&#x440;', '&#x412;&#x435;&#x440;', '&#x416;&#x43e;&#x432;', '&#x41b;&#x438;&#x441;', '&#x413;&#x440;&#x443;'),
+            'months_long'   => array('&#x421;&#x456;&#x447;&#x435;&#x43d;&#x44c;', '&#x41b;&#x44e;&#x442;&#x438;&#x439;', '&#x411;&#x435;&#x440;&#x435;&#x437;&#x435;&#x43d;&#x44c;', '&#x41a;&#x432;&#x456;&#x442;&#x435;&#x43d;&#x44c;', '&#x422;&#x440;&#x430;&#x432;&#x435;&#x43d;&#x44c;', '&#x427;&#x435;&#x440;&#x432;&#x435;&#x43d;&#x44c;', '&#x41b;&#x438;&#x43f;&#x435;&#x43d;&#x44c;', '&#x421;&#x435;&#x440;&#x43f;&#x435;&#x43d;&#x44c;', '&#x412;&#x435;&#x440;&#x435;&#x441;&#x435;&#x43d;&#x44c;', '&#x416;&#x43e;&#x432;&#x442;&#x435;&#x43d;&#x44c;', '&#x41b;&#x438;&#x441;&#x442;&#x43e;&#x43f;&#x430;&#x434;', '&#x413;&#x440;&#x443;&#x434;&#x435;&#x43d;&#x44c;')
+        ),
+        'ro'    => array (
+            'weekdays_short'=> array ('Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sam'),
+            'weekdays_long' => array ('Duminica', 'Luni', 'Marti', 'Miercuri', 'Joi', 'Vineri', 'Sambata'),
+            'months_short'  => array ('Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun', 'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
+            'months_long'   => array ('Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai', 'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie', 'Decembrie')
+        ),
+        'he'    => array (
+            'weekdays_short'=> array ('&#1512;&#1488;&#1513;&#1493;&#1503;', '&#1513;&#1504;&#1497;', '&#1513;&#1500;&#1497;&#1513;&#1497;', '&#1512;&#1489;&#1497;&#1506;&#1497;', '&#1495;&#1502;&#1497;&#1513;&#1497;', '&#1513;&#1497;&#1513;&#1497;', '&#1513;&#1489;&#1514;'),
+            'weekdays_long' => array ('&#1497;&#1493;&#1501; &#1512;&#1488;&#1513;&#1493;&#1503;', '&#1497;&#1493;&#1501; &#1513;&#1504;&#1497;', '&#1497;&#1493;&#1501; &#1513;&#1500;&#1497;&#1513;&#1497;', '&#1497;&#1493;&#1501; &#1512;&#1489;&#1497;&#1506;&#1497;', '&#1497;&#1493;&#1501; &#1495;&#1502;&#1497;&#1513;&#1497;', '&#1497;&#1493;&#1501; &#1513;&#1497;&#1513;&#1497;', '&#1513;&#1489;&#1514;'),
+            'months_short'  => array ('&#1497;&#1504;&#1493;&#1488;&#1512;', '&#1508;&#1489;&#1512;&#1493;&#1488;&#1512;', '&#1502;&#1512;&#1509;', '&#1488;&#1508;&#1512;&#1497;&#1500;', '&#1502;&#1488;&#1497;', '&#1497;&#1493;&#1504;&#1497;', '&#1497;&#1493;&#1500;&#1497;', '&#1488;&#1493;&#1490;&#1493;&#1505;&#1496;', '&#1505;&#1508;&#1496;&#1502;&#1489;&#1512;', '&#1488;&#1493;&#1511;&#1496;&#1493;&#1489;&#1512;', '&#1504;&#1493;&#1489;&#1502;&#1489;&#1512;', '&#1491;&#1510;&#1502;&#1489;&#1512;'),
+            'months_long'   => array ('&#1497;&#1504;&#1493;&#1488;&#1512;', '&#1508;&#1489;&#1512;&#1493;&#1488;&#1512;', '&#1502;&#1512;&#1509;', '&#1488;&#1508;&#1512;&#1497;&#1500;', '&#1502;&#1488;&#1497;', '&#1497;&#1493;&#1504;&#1497;', '&#1497;&#1493;&#1500;&#1497;', '&#1488;&#1493;&#1490;&#1493;&#1505;&#1496;', '&#1505;&#1508;&#1496;&#1502;&#1489;&#1512;', '&#1488;&#1493;&#1511;&#1496;&#1493;&#1489;&#1512;', '&#1504;&#1493;&#1489;&#1502;&#1489;&#1512;', '&#1491;&#1510;&#1502;&#1489;&#1512;')
+        ),
+        'sv'    => array (
+            'weekdays_short'=> array ('S&#xf6;n', 'M&#xe5;n', 'Tis', 'Ons', 'Tor', 'Fre', 'L&#xf6;r'),
+            'weekdays_long' => array ('S&#xf6;ndag', 'M&#xe5;ndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag', 'L&#xf6;rdag'),
+            'months_short'  => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'),
+            'months_long'   => array ('Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni', 'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December')
+        ),
+        'pt'    => array (
+            'weekdays_short'=> array ('Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'S&aacute;b'),
+            'weekdays_long' => array ('Domingo', 'Segunda-feira', 'Ter&ccedil;a-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'S&aacute;bado'),
+            'months_short'  => array ('Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'),
+            'months_long'   => array ('Janeiro', 'Fevereiro', 'Mar&ccedil;o', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro')
+        ),
+        'tw'    => array (
+            'weekdays_short'=> array ('&#36913;&#26085;','&#36913;&#19968;', '&#36913;&#20108;','&#36913;&#19977;', '&#36913;&#22235;','&#36913;&#20116;', '&#36913;&#20845;'),
+            'weekdays_long' => array ('&#26143;&#26399;&#26085;', '&#26143;&#26399;&#19968;', '&#26143;&#26399;&#20108;', '&#26143;&#26399;&#19977;', '&#26143;&#26399;&#22235;', '&#26143;&#26399;&#20116;', '&#26143;&#26399;&#20845;'),
+            'months_short'  => array ('&#19968;&#26376;', '&#20108;&#26376;', '&#19977;&#26376;', '&#22235;&#26376;', '&#20116;&#26376;', '&#20845;&#26376;', '&#19971;&#26376;', '&#20843;&#26376;', '&#20061;&#26376;', '&#21313;&#26376;', '&#21313;&#19968;&#26376;', '&#21313;&#20108;&#26376;'),
+            'months_long'   => array ('&#19968;&#26376;', '&#20108;&#26376;', '&#19977;&#26376;', '&#22235;&#26376;', '&#20116;&#26376;', '&#20845;&#26376;', '&#19971;&#26376;', '&#20843;&#26376;', '&#20061;&#26376;', '&#21313;&#26376;', '&#21313;&#19968;&#26376;', '&#21313;&#20108;&#26376;')
+        ),
+        'pt-br' => array (
+            'weekdays_short'=> array ('Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'S&aacute;b'),
+            'weekdays_long' => array ('Domingo', 'Segunda', 'Ter&ccedil;a', 'Quarta', 'Quinta', 'Sexta', 'S&aacute;bado'),
+            'months_short'  => array ('Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'),
+            'months_long'   => array ('Janeiro', 'Fevereiro', 'Mar&ccedil;o', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro')
+        )
+    );
+
+    // }}}
+    // {{{ constructor
+
+   /**
+    * Class constructor
+    * 
+    * @access   public
+    * @param    string  Element's name
+    * @param    mixed   Label(s) for an element
+    * @param    array   Options to control the element's display
+    * @param    mixed   Either a typical HTML attribute string or an associative array
+    */
+    function HTML_QuickForm_date($elementName = null, $elementLabel = null, $options = array(), $attributes = null)
+    {
+        $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
+        $this->_persistantFreeze = true;
+        $this->_appendName = true;
+        $this->_type = 'date';
+        // set the options, do not bother setting bogus ones
+        if (is_array($options)) {
+            foreach ($options as $name => $value) {
+                if ('language' == $name) {
+                    $this->_options['language'] = isset($this->_locale[$value])? $value: 'en';
+                } elseif (isset($this->_options[$name])) {
+                    if (is_array($value) && is_array($this->_options[$name])) {
+                        $this->_options[$name] = @array_merge($this->_options[$name], $value);
+                    } else {
+                        $this->_options[$name] = $value;
+                    }
+                }
+            }
+        }
+    }
+
+    // }}}
+    // {{{ _createElements()
+
+    function _createElements()
+    {
+        $this->_separator = $this->_elements = array();
+        $separator =  '';
+        $locale    =& $this->_locale[$this->_options['language']];
+        $backslash =  false;
+        for ($i = 0, $length = strlen($this->_options['format']); $i < $length; $i++) {
+            $sign = $this->_options['format']{$i};
+            if ($backslash) {
+                $backslash  = false;
+                $separator .= $sign;
+            } else {
+                $loadSelect = true;
+                switch ($sign) {
+                    case 'D':
+                        // Sunday is 0 like with 'w' in date()
+                        $options = $locale['weekdays_short'];
+                        break;
+                    case 'l':
+                        $options = $locale['weekdays_long'];
+                        break;
+                    case 'd':
+                        $options = $this->_createOptionList(1, 31);
+                        break;
+                    case 'M':
+                        $options = $locale['months_short'];
+                        array_unshift($options , '');
+                        unset($options[0]);
+                        break;
+                    case 'm':
+                        $options = $this->_createOptionList(1, 12);
+                        break;
+                    case 'F':
+                        $options = $locale['months_long'];
+                        array_unshift($options , '');
+                        unset($options[0]);
+                        break;
+                    case 'Y':
+                        $options = $this->_createOptionList(
+                            $this->_options['minYear'],
+                            $this->_options['maxYear'], 
+                            $this->_options['minYear'] > $this->_options['maxYear']? -1: 1
+                        );
+                        break;
+                    case 'y':
+                        $options = $this->_createOptionList(
+                            $this->_options['minYear'],
+                            $this->_options['maxYear'],
+                            $this->_options['minYear'] > $this->_options['maxYear']? -1: 1
+                        );
+                        array_walk($options, create_function('&$v,$k','$v = substr($v,-2);')); 
+                        break;
+                    case 'h':
+                        $options = $this->_createOptionList(1, 12);
+                        break;
+                    case 'g':
+                        $options = $this->_createOptionList(1, 12);
+                        array_walk($options, create_function('&$v,$k', '$v = intval($v);'));
+                        break;
+                    case 'H':
+                        $options = $this->_createOptionList(0, 23);
+                        break;
+                    case 'i':
+                        $options = $this->_createOptionList(0, 59, $this->_options['optionIncrement']['i']);
+                        break;
+                    case 's':
+                        $options = $this->_createOptionList(0, 59, $this->_options['optionIncrement']['s']);
+                        break;
+                    case 'a':
+                        $options = array('am' => 'am', 'pm' => 'pm');
+                        break;
+                    case 'A':
+                        $options = array('AM' => 'AM', 'PM' => 'PM');
+                        break;
+                    case 'W':
+                        $options = $this->_createOptionList(1, 53);
+                        break;
+                    case '\\':
+                        $backslash  = true;
+                        $loadSelect = false;
+                        break;
+                    default:
+                        $separator .= (' ' == $sign? '&nbsp;': $sign);
+                        $loadSelect = false;
+                }
+    
+                if ($loadSelect) {
+                    if (0 < count($this->_elements)) {
+                        $this->_separator[] = $separator;
+                    } else {
+                        $this->_wrap[0] = $separator;
+                    }
+                    $separator = '';
+                    // Should we add an empty option to the top of the select?
+                    if (!is_array($this->_options['addEmptyOption']) && $this->_options['addEmptyOption'] || 
+                        is_array($this->_options['addEmptyOption']) && !empty($this->_options['addEmptyOption'][$sign])) {
+
+                        // Using '+' array operator to preserve the keys
+                        if (is_array($this->_options['emptyOptionText']) && !empty($this->_options['emptyOptionText'][$sign])) {
+                            $options = array($this->_options['emptyOptionValue'] => $this->_options['emptyOptionText'][$sign]) + $options;
+                        } else {
+                            $options = array($this->_options['emptyOptionValue'] => $this->_options['emptyOptionText']) + $options;
+                        }
+                    }
+                    $this->_elements[] =& new HTML_QuickForm_select($sign, null, $options, $this->getAttributes());
+                }
+            }
+        }
+        $this->_wrap[1] = $separator . ($backslash? '\\': '');
+    }
+
+    // }}}
+    // {{{ _createOptionList()
+
+   /**
+    * Creates an option list containing the numbers from the start number to the end, inclusive
+    *
+    * @param    int     The start number
+    * @param    int     The end number
+    * @param    int     Increment by this value
+    * @access   private
+    * @return   array   An array of numeric options.
+    */
+    function _createOptionList($start, $end, $step = 1)
+    {
+        for ($i = $start, $options = array(); $start > $end? $i >= $end: $i <= $end; $i += $step) {
+            $options[$i] = sprintf('%02d', $i);
+        }
+        return $options;
+    }
+
+    // }}}
+    // {{{ setValue()
+
+    function setValue($value)
+    {
+        if (empty($value)) {
+            $value = array();
+        } elseif (is_scalar($value)) {
+            if (!is_numeric($value)) {
+                $value = strtotime($value);
+            }
+            // might be a unix epoch, then we fill all possible values
+            $arr = explode('-', date('w-d-n-Y-h-H-i-s-a-A-W', (int)$value));
+            $value = array(
+                'D' => $arr[0],
+                'l' => $arr[0],
+                'd' => $arr[1],
+                'M' => $arr[2],
+                'm' => $arr[2],
+                'F' => $arr[2],
+                'Y' => $arr[3],
+                'y' => $arr[3],
+                'h' => $arr[4],
+                'g' => $arr[4],
+                'H' => $arr[5],
+                'i' => $arr[6],
+                's' => $arr[7],
+                'a' => $arr[8],
+                'A' => $arr[9],
+                'W' => $arr[10]
+            );
+        }
+        parent::setValue($value);
+    }
+
+    // }}}
+    // {{{ toHtml()
+
+    function toHtml()
+    {
+        include_once('HTML/QuickForm/Renderer/Default.php');
+        $renderer =& new HTML_QuickForm_Renderer_Default();
+        $renderer->setElementTemplate('{element}');
+        parent::accept($renderer);
+        return $this->_wrap[0] . $renderer->toHtml() . $this->_wrap[1];
+    }
+
+    // }}}
+    // {{{ accept()
+
+    function accept(&$renderer, $required = false, $error = null)
+    {
+        $renderer->renderElement($this, $required, $error);
+    }
+
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        if ('updateValue' == $event) {
+            // we need to call setValue(), 'cause the default/constant value
+            // may be in fact a timestamp, not an array
+            return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller);
+        } else {
+            return parent::onQuickFormEvent($event, $arg, $caller);
+        }
+    }
+
+    // }}}
+}
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/element.php b/lib/pear/HTML/QuickForm/element.php
new file mode 100644 (file)
index 0000000..fccad59
--- /dev/null
@@ -0,0 +1,479 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/Common.php');
+
+/**
+ * Base class for form elements
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.3
+ * @since        PHP4.04pl1
+ * @access       public
+ * @abstract
+ */
+class HTML_QuickForm_element extends HTML_Common
+{
+    // {{{ properties
+
+    /**
+     * Label of the field
+     * @var       string
+     * @since     1.3
+     * @access    private
+     */
+    var $_label = '';
+
+    /**
+     * Form element type
+     * @var       string
+     * @since     1.0
+     * @access    private
+     */
+    var $_type = '';
+
+    /**
+     * Flag to tell if element is frozen
+     * @var       boolean
+     * @since     1.0
+     * @access    private
+     */
+    var $_flagFrozen = false;
+
+    /**
+     * Does the element support persistant data when frozen
+     * @var       boolean
+     * @since     1.3
+     * @access    private
+     */
+    var $_persistantFreeze = false;
+    
+    // }}}
+    // {{{ constructor
+    
+    /**
+     * Class constructor
+     * 
+     * @param    string     Name of the element
+     * @param    mixed      Label(s) for the element
+     * @param    mixed      Associative array of tag attributes or HTML attributes name="value" pairs
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_element($elementName=null, $elementLabel=null, $attributes=null)
+    {
+        HTML_Common::HTML_Common($attributes);
+        if (isset($elementName)) {
+            $this->setName($elementName);
+        }
+        if (isset($elementLabel)) {
+            $this->setLabel($elementLabel);
+        }
+    } //end constructor
+    
+    // }}}
+    // {{{ apiVersion()
+
+    /**
+     * Returns the current API version
+     *
+     * @since     1.0
+     * @access    public
+     * @return    float
+     */
+    function apiVersion()
+    {
+        return 2.0;
+    } // end func apiVersion
+
+    // }}}
+    // {{{ getType()
+
+    /**
+     * Returns element type
+     *
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getType()
+    {
+        return $this->_type;
+    } // end func getType
+
+    // }}}
+    // {{{ setName()
+
+    /**
+     * Sets the input field name
+     * 
+     * @param     string    $name   Input field name attribute
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setName($name)
+    {
+        // interface method
+    } //end func setName
+    
+    // }}}
+    // {{{ getName()
+
+    /**
+     * Returns the element name
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getName()
+    {
+        // interface method
+    } //end func getName
+    
+    // }}}
+    // {{{ setValue()
+
+    /**
+     * Sets the value of the form element
+     *
+     * @param     string    $value      Default value of the form element
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setValue($value)
+    {
+        // interface
+    } // end func setValue
+
+    // }}}
+    // {{{ getValue()
+
+    /**
+     * Returns the value of the form element
+     *
+     * @since     1.0
+     * @access    public
+     * @return    mixed
+     */
+    function getValue()
+    {
+        // interface
+        return null;
+    } // end func getValue
+    
+    // }}}
+    // {{{ freeze()
+
+    /**
+     * Freeze the element so that only its value is returned
+     * 
+     * @access    public
+     * @return    void
+     */
+    function freeze()
+    {
+        $this->_flagFrozen = true;
+    } //end func freeze
+
+    // }}}
+    // {{{ unfreeze()
+
+   /**
+    * Unfreezes the element so that it becomes editable
+    *
+    * @access public
+    * @return void
+    * @since  3.2.4
+    */
+    function unfreeze()
+    {
+        $this->_flagFrozen = false;
+    }
+
+    // }}}
+    // {{{ getFrozenHtml()
+
+    /**
+     * Returns the value of field without HTML tags
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getFrozenHtml()
+    {
+        $value = $this->getValue();
+        return ('' != $value? htmlspecialchars($value): '&nbsp;') .
+               $this->_getPersistantData();
+    } //end func getFrozenHtml
+    
+    // }}}
+    // {{{ _getPersistantData()
+
+   /**
+    * Used by getFrozenHtml() to pass the element's value if _persistantFreeze is on
+    * 
+    * @access private
+    * @return string
+    */
+    function _getPersistantData()
+    {
+        if (!$this->_persistantFreeze) {
+            return '';
+        } else {
+            $id = $this->getAttribute('id');
+            return '<input' . $this->_getAttrString(array(
+                       'type'  => 'hidden',
+                       'name'  => $this->getName(),
+                       'value' => $this->getValue()
+                   ) + (isset($id)? array('id' => $id): array())) . ' />';
+        }
+    }
+
+    // }}}
+    // {{{ isFrozen()
+
+    /**
+     * Returns whether or not the element is frozen
+     *
+     * @since     1.3
+     * @access    public
+     * @return    bool
+     */
+    function isFrozen()
+    {
+        return $this->_flagFrozen;
+    } // end func isFrozen
+
+    // }}}
+    // {{{ setPersistantFreeze()
+
+    /**
+     * Sets wether an element value should be kept in an hidden field
+     * when the element is frozen or not
+     * 
+     * @param     bool    $persistant   True if persistant value
+     * @since     2.0
+     * @access    public
+     * @return    void
+     */
+    function setPersistantFreeze($persistant=false)
+    {
+        $this->_persistantFreeze = $persistant;
+    } //end func setPersistantFreeze
+
+    // }}}
+    // {{{ setLabel()
+
+    /**
+     * Sets display text for the element
+     * 
+     * @param     string    $label  Display text for the element
+     * @since     1.3
+     * @access    public
+     * @return    void
+     */
+    function setLabel($label)
+    {
+        $this->_label = $label;
+    } //end func setLabel
+
+    // }}}
+    // {{{ getLabel()
+
+    /**
+     * Returns display text for the element
+     * 
+     * @since     1.3
+     * @access    public
+     * @return    string
+     */
+    function getLabel()
+    {
+        return $this->_label;
+    } //end func getLabel
+
+    // }}}
+    // {{{ _findValue()
+
+    /**
+     * Tries to find the element value from the values array
+     * 
+     * @since     2.7
+     * @access    private
+     * @return    mixed
+     */
+    function _findValue(&$values)
+    {
+        if (empty($values)) {
+            return null;
+        }
+        $elementName = $this->getName();
+        if (isset($values[$elementName])) {
+            return $values[$elementName];
+        } elseif (strpos($elementName, '[')) {
+            $myVar = "['" . str_replace(array(']', '['), array('', "']['"), $elementName) . "']";
+            return eval("return (isset(\$values$myVar)) ? \$values$myVar : null;");
+        } else {
+            return null;
+        }
+    } //end func _findValue
+
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    /**
+     * Called by HTML_QuickForm whenever form event is made on this element
+     *
+     * @param     string    $event  Name of event
+     * @param     mixed     $arg    event arguments
+     * @param     object    $caller calling object
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        switch ($event) {
+            case 'createElement':
+                $className = get_class($this);
+                $this->$className($arg[0], $arg[1], $arg[2], $arg[3], $arg[4]);
+                break;
+            case 'addElement':
+                $this->onQuickFormEvent('createElement', $arg, $caller);
+                $this->onQuickFormEvent('updateValue', null, $caller);
+                break;
+            case 'updateValue':
+                // constant values override both default and submitted ones
+                // default values are overriden by submitted
+                $value = $this->_findValue($caller->_constantValues);
+                if (null === $value) {
+                    $value = $this->_findValue($caller->_submitValues);
+                    if (null === $value) {
+                        $value = $this->_findValue($caller->_defaultValues);
+                    }
+                }
+                if (null !== $value) {
+                    $this->setValue($value);
+                }
+                break;
+            case 'setGroupValue':
+                $this->setValue($arg);
+        }
+        return true;
+    } // end func onQuickFormEvent
+
+    // }}}
+    // {{{ accept()
+
+   /**
+    * Accepts a renderer
+    *
+    * @param object     An HTML_QuickForm_Renderer object
+    * @param bool       Whether an element is required
+    * @param string     An error message associated with an element
+    * @access public
+    * @return void 
+    */
+    function accept(&$renderer, $required=false, $error=null)
+    {
+        $renderer->renderElement($this, $required, $error);
+    } // end func accept
+
+    // }}}
+    // {{{ _generateId()
+
+   /**
+    * Automatically generates and assigns an 'id' attribute for the element.
+    * 
+    * Currently used to ensure that labels work on radio buttons and
+    * checkboxes. Per idea of Alexander Radivanovich.
+    *
+    * @access private
+    * @return void 
+    */
+    function _generateId()
+    {
+        static $idx = 1;
+
+        if (!$this->getAttribute('id')) {
+            $this->updateAttributes(array('id' => 'qf_' . substr(md5(microtime() . $idx++), 0, 6)));
+        }
+    } // end func _generateId
+
+    // }}}
+    // {{{ exportValue()
+
+   /**
+    * Returns a 'safe' element's value
+    *
+    * @param  array   array of submitted values to search
+    * @param  bool    whether to return the value as associative array
+    * @access public
+    * @return mixed
+    */
+    function exportValue(&$submitValues, $assoc = false)
+    {
+        $value = $this->_findValue($submitValues);
+        if (null === $value) {
+            $value = $this->getValue();
+        }
+        return $this->_prepareValue($value, $assoc);
+    }
+    
+    // }}}
+    // {{{ _prepareValue()
+
+   /**
+    * Used by exportValue() to prepare the value for returning
+    *
+    * @param  mixed   the value found in exportValue()
+    * @param  bool    whether to return the value as associative array
+    * @access private
+    * @return mixed
+    */
+    function _prepareValue($value, $assoc)
+    {
+        if (null === $value) {
+            return null;
+        } elseif (!$assoc) {
+            return $value;
+        } else {
+            $name = $this->getName();
+            if (!strpos($name, '[')) {
+                return array($name => $value);
+            } else {
+                $valueAry = array();
+                $myIndex  = "['" . str_replace(array(']', '['), array('', "']['"), $name) . "']";
+                eval("\$valueAry$myIndex = \$value;");
+                return $valueAry;
+            }
+        }
+    }
+    
+    // }}}
+} // end class HTML_QuickForm_element
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/file.php b/lib/pear/HTML/QuickForm/file.php
new file mode 100644 (file)
index 0000000..7d9000c
--- /dev/null
@@ -0,0 +1,347 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/input.php");
+
+// register file-related rules
+if (class_exists('HTML_QuickForm')) {
+    HTML_QuickForm::registerRule('uploadedfile', 'callback', '_ruleIsUploadedFile', 'HTML_QuickForm_file');
+    HTML_QuickForm::registerRule('maxfilesize', 'callback', '_ruleCheckMaxFileSize', 'HTML_QuickForm_file');
+    HTML_QuickForm::registerRule('mimetype', 'callback', '_ruleCheckMimeType', 'HTML_QuickForm_file');
+    HTML_QuickForm::registerRule('filename', 'callback', '_ruleCheckFileName', 'HTML_QuickForm_file');
+}
+
+/**
+ * HTML class for a file type element
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_file extends HTML_QuickForm_input
+{
+    // {{{ properties
+
+   /**
+    * Uploaded file data, from $_FILES
+    * @var array
+    */
+    var $_value = null;
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    Input field name attribute
+     * @param     string    Input field label
+     * @param     mixed     (optional)Either a typical HTML attribute string 
+     *                      or an associative array
+     * @since     1.0
+     * @access    public
+     */
+    function HTML_QuickForm_file($elementName=null, $elementLabel=null, $attributes=null)
+    {
+        HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
+        $this->setType('file');
+    } //end constructor
+    
+    // }}}
+    // {{{ setSize()
+
+    /**
+     * Sets size of file element
+     * 
+     * @param     int    Size of file element
+     * @since     1.0
+     * @access    public
+     */
+    function setSize($size)
+    {
+        $this->updateAttributes(array('size' => $size));
+    } //end func setSize
+    
+    // }}}
+    // {{{ getSize()
+
+    /**
+     * Returns size of file element
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    int
+     */
+    function getSize()
+    {
+        return $this->getAttribute('size');
+    } //end func getSize
+
+    // }}}
+    // {{{ freeze()
+
+    /**
+     * Freeze the element so that only its value is returned
+     * 
+     * @access    public
+     * @return    bool
+     */
+    function freeze()
+    {
+        return false;
+    } //end func freeze
+
+    // }}}
+    // {{{ setValue()
+
+    /**
+     * Sets value for file element.
+     * 
+     * Actually this does nothing. The function is defined here to override
+     * HTML_Quickform_input's behaviour of setting the 'value' attribute. As
+     * no sane user-agent uses <input type="file">'s value for anything 
+     * (because of security implications) we implement file's value as a 
+     * read-only property with a special meaning.
+     * 
+     * @param     mixed    Value for file element
+     * @since     3.0
+     * @access    public
+     */
+    function setValue($value)
+    {
+        return null;
+    } //end func setValue
+    
+    // }}}
+    // {{{ getValue()
+
+    /**
+     * Returns information about the uploaded file
+     *
+     * @since     3.0
+     * @access    public
+     * @return    array
+     */
+    function getValue()
+    {
+        return $this->_value;
+    } // end func getValue
+
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    /**
+     * Called by HTML_QuickForm whenever form event is made on this element
+     *
+     * @param     string    Name of event
+     * @param     mixed     event arguments
+     * @param     object    calling object
+     * @since     1.0
+     * @access    public
+     * @return    bool
+     */
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        switch ($event) {
+            case 'updateValue':
+                if ($caller->getAttribute('method') == 'get') {
+                    return PEAR::raiseError('Cannot add a file upload field to a GET method form');
+                }
+                $this->_value = $this->_findValue();
+                $caller->updateAttributes(array('enctype' => 'multipart/form-data'));
+                $caller->setMaxFileSize();
+                break;
+            case 'addElement':
+                $this->onQuickFormEvent('createElement', $arg, $caller);
+                return $this->onQuickFormEvent('updateValue', null, $caller);
+                break;
+            case 'createElement':
+                $className = get_class($this);
+                $this->$className($arg[0], $arg[1], $arg[2]);
+                break;
+        }
+        return true;
+    } // end func onQuickFormEvent
+
+    // }}}
+    // {{{ moveUploadedFile()
+
+    /**
+     * Moves an uploaded file into the destination 
+     * 
+     * @param    string  Destination directory path
+     * @param    string  New file name
+     * @access   public
+     * @return   bool    Whether the file was moved successfully
+     */
+    function moveUploadedFile($dest, $fileName = '')
+    {
+        if ($dest != ''  && substr($dest, -1) != '/') {
+            $dest .= '/';
+        }
+        $fileName = ($fileName != '') ? $fileName : basename($this->_value['name']);
+        if (move_uploaded_file($this->_value['tmp_name'], $dest . $fileName)) {
+            return true;
+        } else {
+            return false;
+        }
+    } // end func moveUploadedFile
+    
+    // }}}
+    // {{{ isUploadedFile()
+
+    /**
+     * Checks if the element contains an uploaded file
+     *
+     * @access    public
+     * @return    bool      true if file has been uploaded, false otherwise
+     */
+    function isUploadedFile()
+    {
+        return $this->_ruleIsUploadedFile($this->_value);
+    } // end func isUploadedFile
+
+    // }}}
+    // {{{ _ruleIsUploadedFile()
+
+    /**
+     * Checks if the given element contains an uploaded file
+     *
+     * @param     array     Uploaded file info (from $_FILES)
+     * @access    private
+     * @return    bool      true if file has been uploaded, false otherwise
+     */
+    function _ruleIsUploadedFile($elementValue)
+    {
+        if ((isset($elementValue['error']) && $elementValue['error'] == 0) ||
+            (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')) {
+            return is_uploaded_file($elementValue['tmp_name']);
+        } else {
+            return false;
+        }
+    } // end func _ruleIsUploadedFile
+    
+    // }}}
+    // {{{ _ruleCheckMaxFileSize()
+
+    /**
+     * Checks that the file does not exceed the max file size
+     *
+     * @param     array     Uploaded file info (from $_FILES)
+     * @param     int       Max file size
+     * @access    private
+     * @return    bool      true if filesize is lower than maxsize, false otherwise
+     */
+    function _ruleCheckMaxFileSize($elementValue, $maxSize)
+    {
+        if (!empty($elementValue['error']) && 
+            (UPLOAD_ERR_FORM_SIZE == $elementValue['error'] || UPLOAD_ERR_INI_SIZE == $elementValue['error'])) {
+            return false;
+        }
+        if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
+            return true;
+        }
+        return ($maxSize >= @filesize($elementValue['tmp_name']));
+    } // end func _ruleCheckMaxFileSize
+
+    // }}}
+    // {{{ _ruleCheckMimeType()
+
+    /**
+     * Checks if the given element contains an uploaded file of the right mime type
+     *
+     * @param     array     Uploaded file info (from $_FILES)
+     * @param     mixed     Mime Type (can be an array of allowed types)
+     * @access    private
+     * @return    bool      true if mimetype is correct, false otherwise
+     */
+    function _ruleCheckMimeType($elementValue, $mimeType)
+    {
+        if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
+            return true;
+        }
+        if (is_array($mimeType)) {
+            return in_array($elementValue['type'], $mimeType);
+        }
+        return $elementValue['type'] == $mimeType;
+    } // end func _ruleCheckMimeType
+
+    // }}}
+    // {{{ _ruleCheckFileName()
+
+    /**
+     * Checks if the given element contains an uploaded file of the filename regex
+     *
+     * @param     array     Uploaded file info (from $_FILES)
+     * @param     string    Regular expression
+     * @access    private
+     * @return    bool      true if name matches regex, false otherwise
+     */
+    function _ruleCheckFileName($elementValue, $regex)
+    {
+        if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
+            return true;
+        }
+        return preg_match($regex, $elementValue['name']);
+    } // end func _ruleCheckFileName
+    
+    // }}}
+    // {{{ _findValue()
+
+   /**
+    * Tries to find the element value from the values array
+    * 
+    * Needs to be redefined here as $_FILES is populated differently from 
+    * other arrays when element name is of the form foo[bar]
+    * 
+    * @access    private
+    * @return    mixed
+    */
+    function _findValue()
+    {
+        if (empty($_FILES)) {
+            return null;
+        }
+        $elementName = $this->getName();
+        if (isset($_FILES[$elementName])) {
+            return $_FILES[$elementName];
+        } elseif (false !== ($pos = strpos($elementName, '['))) {
+            $base  = substr($elementName, 0, $pos);
+            $idx   = "['" . str_replace(array(']', '['), array('', "']['"), substr($elementName, $pos + 1, -1)) . "']";
+            $props = array('name', 'type', 'size', 'tmp_name', 'error');
+            $code  = "if (!isset(\$_FILES['{$base}']['name']{$idx})) {\n" .
+                     "    return null;\n" .
+                     "} else {\n" .
+                     "    \$value = array();\n";
+            foreach ($props as $prop) {
+                $code .= "    \$value['{$prop}'] = \$_FILES['{$base}']['{$prop}']{$idx};\n";
+            }
+            return eval($code . "    return \$value;\n}\n");
+        } else {
+            return null;
+        }
+    }
+
+    // }}}
+} // end class HTML_QuickForm_file
+?>
diff --git a/lib/pear/HTML/QuickForm/group.php b/lib/pear/HTML/QuickForm/group.php
new file mode 100644 (file)
index 0000000..f24fe37
--- /dev/null
@@ -0,0 +1,579 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/element.php");
+
+/**
+ * HTML class for a form element group
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_group extends HTML_QuickForm_element
+{
+    // {{{ properties
+        
+    /**
+     * Name of the element
+     * @var       string
+     * @since     1.0
+     * @access    private
+     */
+    var $_name = '';
+
+    /**
+     * Array of grouped elements
+     * @var       array
+     * @since     1.0
+     * @access    private
+     */
+    var $_elements = array();
+
+    /**
+     * String to separate elements
+     * @var       mixed
+     * @since     2.5
+     * @access    private
+     */
+    var $_separator = null;
+
+    /**
+     * Required elements in this group
+     * @var       array
+     * @since     2.5
+     * @access    private
+     */
+    var $_required = array();
+
+   /**
+    * Whether to change elements' names to $groupName[$elementName] or leave them as is 
+    * @var      bool
+    * @since    3.0
+    * @access   private
+    */
+    var $_appendName = true;
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementName    (optional)Group name
+     * @param     array     $elementLabel   (optional)Group label
+     * @param     array     $elements       (optional)Group elements
+     * @param     mixed     $separator      (optional)Use a string for one separator,
+     *                                      use an array to alternate the separators.
+     * @param     bool      $appendName     (optional)whether to change elements' names to
+     *                                      the form $groupName[$elementName] or leave 
+     *                                      them as is.
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_group($elementName=null, $elementLabel=null, $elements=null, $separator=null, $appendName = true)
+    {
+        $this->HTML_QuickForm_element($elementName, $elementLabel);
+        $this->_type = 'group';
+        if (isset($elements) && is_array($elements)) {
+            $this->setElements($elements);
+        }
+        if (isset($separator)) {
+            $this->_separator = $separator;
+        }
+        if (isset($appendName)) {
+            $this->_appendName = $appendName;
+        }
+    } //end constructor
+    
+    // }}}
+    // {{{ setName()
+
+    /**
+     * Sets the group name
+     * 
+     * @param     string    $name   Group name
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setName($name)
+    {
+        $this->_name = $name;
+    } //end func setName
+    
+    // }}}
+    // {{{ getName()
+
+    /**
+     * Returns the group name
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getName()
+    {
+        return $this->_name;
+    } //end func getName
+
+    // }}}
+    // {{{ setValue()
+
+    /**
+     * Sets values for group's elements
+     * 
+     * @param     mixed    Values for group's elements
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setValue($value)
+    {
+        $this->_createElementsIfNotExist();
+        foreach (array_keys($this->_elements) as $key) {
+            if (!$this->_appendName) {
+                $v = $this->_elements[$key]->_findValue($value);
+                if (null !== $v) {
+                    $this->_elements[$key]->onQuickFormEvent('setGroupValue', $v, $this);
+                }
+
+            } else {
+                $elementName = $this->_elements[$key]->getName();
+                $index       = strlen($elementName) ? $elementName : $key;
+                if (is_array($value)) {
+                    if (isset($value[$index])) {
+                        $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value[$index], $this);
+                    }
+                } elseif (isset($value)) {
+                    $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value, $this);
+                }
+            }
+        }
+    } //end func setValue
+    
+    // }}}
+    // {{{ getValue()
+
+    /**
+     * Returns the value of the group
+     *
+     * @since     1.0
+     * @access    public
+     * @return    mixed
+     */
+    function getValue()
+    {
+        $value = null;
+        foreach (array_keys($this->_elements) as $key) {
+            $element =& $this->_elements[$key];
+            switch ($element->getType()) {
+                case 'radio': 
+                    $v = $element->getChecked()? $element->getValue(): null;
+                    break;
+                case 'checkbox': 
+                    $v = $element->getChecked()? true: null;
+                    break;
+                default:
+                    $v = $element->getValue();
+            }
+            if (null !== $v) {
+                $elementName = $element->getName();
+                if (is_null($elementName)) {
+                    $value = $v;
+                } else {
+                    if (!is_array($value)) {
+                        $value = is_null($value)? array(): array($value);
+                    }
+                    if ('' === $elementName) {
+                        $value[] = $v;
+                    } else {
+                        $value[$elementName] = $v;
+                    }
+                }
+            }
+        }
+        return $value;
+    } // end func getValue
+
+    // }}}
+    // {{{ setElements()
+
+    /**
+     * Sets the grouped elements
+     *
+     * @param     array     $elements   Array of elements
+     * @since     1.1
+     * @access    public
+     * @return    void
+     */
+    function setElements($elements)
+    {
+        $this->_elements = array_values($elements);
+        if ($this->_flagFrozen) {
+            $this->freeze();
+        }
+    } // end func setElements
+
+    // }}}
+    // {{{ getElements()
+
+    /**
+     * Gets the grouped elements
+     *
+     * @since     2.4
+     * @access    public
+     * @return    array
+     */
+    function &getElements()
+    {
+        $this->_createElementsIfNotExist();
+        return $this->_elements;
+    } // end func getElements
+
+    // }}}
+    // {{{ getGroupType()
+
+    /**
+     * Gets the group type based on its elements
+     * Will return 'mixed' if elements contained in the group
+     * are of different types.
+     *
+     * @access    public
+     * @return    string    group elements type
+     */
+    function getGroupType()
+    {
+        $this->_createElementsIfNotExist();
+        $prevType = '';
+        foreach (array_keys($this->_elements) as $key) {
+            $type = $this->_elements[$key]->getType();
+            if ($type != $prevType && $prevType != '') {
+                return 'mixed';
+            }
+            $prevType = $type;
+        }
+        return $type;
+    } // end func getGroupType
+
+    // }}}
+    // {{{ toHtml()
+
+    /**
+     * Returns Html for the group
+     * 
+     * @since       1.0
+     * @access      public
+     * @return      string
+     */
+    function toHtml()
+    {
+        include_once('HTML/QuickForm/Renderer/Default.php');
+        $renderer =& new HTML_QuickForm_Renderer_Default();
+        $renderer->setElementTemplate('{element}');
+        $this->accept($renderer);
+        return $renderer->toHtml();
+    } //end func toHtml
+    
+    // }}}
+    // {{{ getElementName()
+
+    /**
+     * Returns the element name inside the group such as found in the html form
+     * 
+     * @param     mixed     $index  Element name or element index in the group
+     * @since     3.0
+     * @access    public
+     * @return    mixed     string with element name, false if not found
+     */
+    function getElementName($index)
+    {
+        $this->_createElementsIfNotExist();
+        $elementName = false;
+        if (is_int($index) && isset($this->_elements[$index])) {
+            $elementName = $this->_elements[$index]->getName();
+            if (isset($elementName) && $elementName == '') {
+                $elementName = $index;
+            }
+            if ($this->_appendName) {
+                if (is_null($elementName)) {
+                    $elementName = $this->getName();
+                } else {
+                    $elementName = $this->getName().'['.$elementName.']';
+                }
+            }
+
+        } elseif (is_string($index)) {
+            foreach (array_keys($this->_elements) as $key) {
+                $elementName = $this->_elements[$key]->getName();
+                if ($index == $elementName) {
+                    if ($this->_appendName) {
+                        $elementName = $this->getName().'['.$elementName.']';
+                    }
+                    break;
+                } elseif ($this->_appendName && $this->getName().'['.$elementName.']' == $index) {
+                    break;
+                }
+            }
+        }
+        return $elementName;
+    } //end func getElementName
+
+    // }}}
+    // {{{ getFrozenHtml()
+
+    /**
+     * Returns the value of field without HTML tags
+     * 
+     * @since     1.3
+     * @access    public
+     * @return    string
+     */
+    function getFrozenHtml()
+    {
+        $flags = array();
+        $this->_createElementsIfNotExist();
+        foreach (array_keys($this->_elements) as $key) {
+            if (false === ($flags[$key] = $this->_elements[$key]->isFrozen())) {
+                $this->_elements[$key]->freeze();
+            }
+        }
+        $html = $this->toHtml();
+        foreach (array_keys($this->_elements) as $key) {
+            if (!$flags[$key]) {
+                $this->_elements[$key]->unfreeze();
+            }
+        }
+        return $html;
+    } //end func getFrozenHtml
+
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    /**
+     * Called by HTML_QuickForm whenever form event is made on this element
+     *
+     * @param     string    $event  Name of event
+     * @param     mixed     $arg    event arguments
+     * @param     object    $caller calling object
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        switch ($event) {
+            case 'updateValue':
+                $this->_createElementsIfNotExist();
+                foreach (array_keys($this->_elements) as $key) {
+                    if ($this->_appendName) {
+                        $elementName = $this->_elements[$key]->getName();
+                        if (is_null($elementName)) {
+                            $this->_elements[$key]->setName($this->getName());
+                        } elseif ('' === $elementName) {
+                            $this->_elements[$key]->setName($this->getName() . '[' . $key . ']');
+                        } else {
+                            $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']');
+                        }
+                    }
+                    $this->_elements[$key]->onQuickFormEvent('updateValue', $arg, $caller);
+                    if ($this->_appendName) {
+                        $this->_elements[$key]->setName($elementName);
+                    }
+                }
+                break;
+
+            default:
+                parent::onQuickFormEvent($event, $arg, $caller);
+        }
+        return true;
+    } // end func onQuickFormEvent
+
+    // }}}
+    // {{{ accept()
+
+   /**
+    * Accepts a renderer
+    *
+    * @param object     An HTML_QuickForm_Renderer object
+    * @param bool       Whether a group is required
+    * @param string     An error message associated with a group
+    * @access public
+    * @return void 
+    */
+    function accept(&$renderer, $required = false, $error = null)
+    {
+        $this->_createElementsIfNotExist();
+        $renderer->startGroup($this, $required, $error);
+        $name = $this->getName();
+        foreach (array_keys($this->_elements) as $key) {
+            $element =& $this->_elements[$key];
+            
+            if ($this->_appendName) {
+                $elementName = $element->getName();
+                if (isset($elementName)) {
+                    $element->setName($name . '['. (strlen($elementName)? $elementName: $key) .']');
+                } else {
+                    $element->setName($name);
+                }
+            }
+
+            $required = !$element->isFrozen() && in_array($element->getName(), $this->_required);
+
+            $element->accept($renderer, $required);
+
+            // restore the element's name
+            if ($this->_appendName) {
+                $element->setName($elementName);
+            }
+        }
+        $renderer->finishGroup($this);
+    } // end func accept
+
+    // }}}
+    // {{{ exportValue()
+
+   /**
+    * As usual, to get the group's value we access its elements and call
+    * their exportValue() methods
+    */
+    function exportValue(&$submitValues, $assoc = false)
+    {
+        $value = null;
+        foreach (array_keys($this->_elements) as $key) {
+            $elementName = $this->_elements[$key]->getName();
+            if ($this->_appendName) {
+                if (is_null($elementName)) {
+                    $this->_elements[$key]->setName($this->getName());
+                } elseif ('' === $elementName) {
+                    $this->_elements[$key]->setName($this->getName() . '[' . $key . ']');
+                } else {
+                    $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']');
+                }
+            }
+            $v = $this->_elements[$key]->exportValue($submitValues, $assoc);
+            if ($this->_appendName) {
+                $this->_elements[$key]->setName($elementName);
+            }
+            if (null !== $v) {
+                // Make $value an array, we will use it like one
+                if (null === $value) {
+                    $value = array();
+                }
+                if ($assoc) {
+                    // just like HTML_QuickForm::exportValues()
+                    $value = HTML_QuickForm::arrayMerge($value, $v);
+                } else {
+                    // just like getValue(), but should work OK every time here
+                    if (is_null($elementName)) {
+                        $value = $v;
+                    } elseif ('' === $elementName) {
+                        $value[] = $v;
+                    } else {
+                        $value[$elementName] = $v;
+                    }
+                }
+            }
+        }
+        // do not pass the value through _prepareValue, we took care of this already
+        return $value;
+    }
+
+    // }}}
+    // {{{ _createElements()
+
+   /**
+    * Creates the group's elements.
+    * 
+    * This should be overriden by child classes that need to create their 
+    * elements. The method will be called automatically when needed, calling
+    * it from the constructor is discouraged as the constructor is usually
+    * called _twice_ on element creation, first time with _no_ parameters.
+    * 
+    * @access private
+    * @abstract
+    */
+    function _createElements()
+    {
+        // abstract
+    }
+
+    // }}}
+    // {{{ _createElementsIfNotExist()
+
+   /**
+    * A wrapper around _createElements()
+    *
+    * This method calls _createElements() if the group's _elements array
+    * is empty. It also performs some updates, e.g. freezes the created
+    * elements if the group is already frozen.
+    *
+    * @access private
+    */
+    function _createElementsIfNotExist()
+    {
+        if (empty($this->_elements)) {
+            $this->_createElements();
+            if ($this->_flagFrozen) {
+                $this->freeze();
+            }
+        }
+    }
+
+    // }}}
+    // {{{ freeze()
+
+    function freeze()
+    {
+        parent::freeze();
+        foreach (array_keys($this->_elements) as $key) {
+            $this->_elements[$key]->freeze();
+        }
+    }
+
+    // }}}
+    // {{{ unfreeze()
+
+    function unfreeze()
+    {
+        parent::unfreeze();
+        foreach (array_keys($this->_elements) as $key) {
+            $this->_elements[$key]->unfreeze();
+        }
+    }
+
+    // }}}
+    // {{{ setPersistantFreeze()
+
+    function setPersistantFreeze($persistant = false)
+    {
+        parent::setPersistantFreeze($persistant);
+        foreach (array_keys($this->_elements) as $key) {
+            $this->_elements[$key]->setPersistantFreeze($persistant);
+        }
+    }
+
+    // }}}
+} //end class HTML_QuickForm_group
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/header.php b/lib/pear/HTML/QuickForm/header.php
new file mode 100644 (file)
index 0000000..b1745ab
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Author: Alexey Borzov <borz_off@cs.msu.su>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once 'HTML/QuickForm/static.php';
+
+/**
+ * A pseudo-element used for adding headers to form  
+ *
+ * @author Alexey Borzov <borz_off@cs.msu.su>
+ * @access public
+ */
+class HTML_QuickForm_header extends HTML_QuickForm_static
+{
+    // {{{ constructor
+
+   /**
+    * Class constructor
+    * 
+    * @param string $elementName    Header name
+    * @param string $text           Header text
+    * @access public
+    * @return void
+    */
+    function HTML_QuickForm_header($elementName = null, $text = null)
+    {
+        $this->HTML_QuickForm_static($elementName, null, $text);
+        $this->_type = 'header';
+    }
+
+    // }}}
+    // {{{ accept()
+
+   /**
+    * Accepts a renderer
+    *
+    * @param object     An HTML_QuickForm_Renderer object
+    * @access public
+    * @return void 
+    */
+    function accept(&$renderer)
+    {
+        $renderer->renderHeader($this);
+    } // end func accept
+
+    // }}}
+
+} //end class HTML_QuickForm_header
+?>
diff --git a/lib/pear/HTML/QuickForm/hidden.php b/lib/pear/HTML/QuickForm/hidden.php
new file mode 100644 (file)
index 0000000..acd4a48
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/input.php");
+
+/**
+ * HTML class for a hidden type element
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_hidden extends HTML_QuickForm_input
+{
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementName    (optional)Input field name attribute
+     * @param     string    $value          (optional)Input field value
+     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
+     *                                      or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_hidden($elementName=null, $value='', $attributes=null)
+    {
+        HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes);
+        $this->setType('hidden');
+        $this->setValue($value);
+    } //end constructor
+        
+    // }}}
+    // {{{ freeze()
+
+    /**
+     * Freeze the element so that only its value is returned
+     * 
+     * @access    public
+     * @return    void
+     */
+    function freeze()
+    {
+        return false;
+    } //end func freeze
+
+    // }}}
+    // {{{ accept()
+
+   /**
+    * Accepts a renderer
+    *
+    * @param object     An HTML_QuickForm_Renderer object
+    * @access public
+    * @return void 
+    */
+    function accept(&$renderer)
+    {
+        $renderer->renderHidden($this);
+    } // end func accept
+
+    // }}}
+
+} //end class HTML_QuickForm_hidden
+?>
diff --git a/lib/pear/HTML/QuickForm/hiddenselect.php b/lib/pear/HTML/QuickForm/hiddenselect.php
new file mode 100644 (file)
index 0000000..3fb26b2
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/select.php');
+
+/**
+ * This class takes the same arguments as a select element, but instead
+ * of creating a select ring it creates hidden elements for all values
+ * already selected with setDefault or setConstant.  This is useful if
+ * you have a select ring that you don't want visible, but you need all
+ * selected values to be passed.
+ *
+ * @author       Isaac Shepard <ishepard@bsiweb.com>
+ * 
+ * @version      1.0
+ * @since        2.1
+ * @access       public
+ */
+class HTML_QuickForm_hiddenselect extends HTML_QuickForm_select
+{
+    // {{{ constructor
+        
+    /**
+     * Class constructor
+     * 
+     * @param     string    Select name attribute
+     * @param     mixed     Label(s) for the select (not used)
+     * @param     mixed     Data to be used to populate options
+     * @param     mixed     Either a typical HTML attribute string or an associative array (not used)
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_hiddenselect($elementName=null, $elementLabel=null, $options=null, $attributes=null)
+    {
+        HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
+        $this->_persistantFreeze = true;
+        $this->_type = 'hiddenselect';
+        if (isset($options)) {
+            $this->load($options);
+        }
+    } //end constructor
+    
+    // }}}
+    // {{{ toHtml()
+
+    /**
+     * Returns the SELECT in HTML
+     *
+     * @since     1.0
+     * @access    public
+     * @return    string
+     * @throws    
+     */
+    function toHtml()
+    {
+        $tabs    = $this->_getTabs();
+        $name    = $this->getPrivateName();
+        $strHtml = '';
+
+        foreach ($this->_values as $key => $val) {
+            for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) {
+                if ($val == $this->_options[$i]['attr']['value']) {
+                    $strHtml .= $tabs . '<input' . $this->_getAttrString(array(
+                        'type'  => 'hidden',
+                        'name'  => $name,
+                        'value' => $val
+                    )) . " />\n" ;
+                }
+            }
+        }
+
+        return $strHtml;
+    } //end func toHtml
+    
+    // }}}
+    // {{{ accept()
+
+   /**
+    * This is essentially a hidden element and should be rendered as one  
+    */
+    function accept(&$renderer)
+    {
+        $renderer->renderHidden($this);
+    }
+
+    // }}}
+} //end class HTML_QuickForm_hiddenselect
+?>
diff --git a/lib/pear/HTML/QuickForm/hierselect.php b/lib/pear/HTML/QuickForm/hierselect.php
new file mode 100644 (file)
index 0000000..8c0f31e
--- /dev/null
@@ -0,0 +1,578 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2004 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Herim Vasquez <vasquezh@iro.umontreal.ca>                   |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// |          Alexey Borzov <avb@php.net>
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/group.php');
+require_once('HTML/QuickForm/select.php');
+
+/**
+ * Class to dynamically create two or more HTML Select elements
+ * The first select changes the content of the second select and so on.
+ * This element is considered as a group. Selects will be named
+ * groupName[0], groupName[1], groupName[2]...
+ *
+ * @author       Herim Vasquez <vasquezh@iro.umontreal.ca>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_hierselect extends HTML_QuickForm_group
+{   
+    // {{{ properties
+
+    /**
+     * Options for all the select elements
+     *
+     * Format is a bit more complex as we need to know which options
+     * are related to the ones in the previous select:
+     *
+     * Ex:
+     * // first select
+     * $select1[0] = 'Pop';
+     * $select1[1] = 'Classical';
+     * $select1[2] = 'Funeral doom';
+     *
+     * // second select
+     * $select2[0][0] = 'Red Hot Chil Peppers';
+     * $select2[0][1] = 'The Pixies';
+     * $select2[1][0] = 'Wagner';
+     * $select2[1][1] = 'Strauss';
+     * $select2[2][0] = 'Pantheist';
+     * $select2[2][1] = 'Skepticism';
+     *
+     * // If only need two selects 
+     * //     - and using the depracated functions
+     * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
+     * $sel->setMainOptions($select1);
+     * $sel->setSecOptions($select2);
+     *
+     * //     - and using the new setOptions function
+     * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
+     * $sel->setOptions(array($select1, $select2));
+     *
+     * // If you have a third select with prices for the cds
+     * $select3[0][0][0] = '15.00$';
+     * $select3[0][0][1] = '17.00$';
+     * etc
+     *
+     * // You can now use
+     * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
+     * $sel->setOptions(array($select1, $select2, $select3));
+     * 
+     * @var       array
+     * @access    private
+     */
+    var $_options = array();
+    
+    /**
+     * Number of select elements on this group
+     *
+     * @var       int
+     * @access    private
+     */
+    var $_nbElements = 0;
+
+    /**
+     * The javascript used to set and change the options
+     *
+     * @var       string
+     * @access    private
+     */
+    var $_js = '';
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementName    (optional)Input field name attribute
+     * @param     string    $elementLabel   (optional)Input field label in form
+     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
+     *                                      or an associative array. Date format is passed along the attributes.
+     * @param     mixed     $separator      (optional)Use a string for one separator,
+     *                                      use an array to alternate the separators.
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_hierselect($elementName=null, $elementLabel=null, $attributes=null, $separator=null)
+    {
+        $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
+        $this->_persistantFreeze = true;
+        if (isset($separator)) {
+            $this->_separator = $separator;
+        }
+        $this->_type = 'hierselect';
+        $this->_appendName = true;
+    } //end constructor
+
+    // }}}
+    // {{{ setOptions()
+
+    /**
+     * Initialize the array structure containing the options for each select element.
+     * Call the functions that actually do the magic.
+     *
+     * @param     array    $options    Array of options defining each element
+     *
+     * @access    public
+     * @return    void
+     */
+    function setOptions($options)
+    {
+        $this->_options = $options;
+
+        if (empty($this->_elements)) {
+            $this->_nbElements = count($this->_options);
+            $this->_createElements();
+        } else {
+            // setDefaults has probably been called before this function
+            // check if all elements have been created
+            $totalNbElements = count($this->_options);
+            for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
+                $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
+                $this->_nbElements++;
+            }
+        }
+        
+        $this->_setOptions();
+    } // end func setMainOptions
+
+    // }}}
+    // {{{ setMainOptions()
+    
+    /**
+     * Sets the options for the first select element. Deprecated. setOptions() should be used.
+     *
+     * @param     array     $array    Options for the first select element
+     *
+     * @access    public
+     * @deprecated          Deprecated since release 3.2.2
+     * @return    void
+     */
+    function setMainOptions($array)
+    {
+        $this->_options[0] = $array;
+
+        if (empty($this->_elements)) {
+            $this->_nbElements = 2;
+            $this->_createElements();
+        }
+    } // end func setMainOptions
+    
+    // }}}
+    // {{{ setSecOptions()
+    
+    /**
+     * Sets the options for the second select element. Deprecated. setOptions() should be used.
+     * The main _options array is initialized and the _setOptions function is called.
+     *
+     * @param     array     $array    Options for the second select element
+     *
+     * @access    public
+     * @deprecated          Deprecated since release 3.2.2
+     * @return    void
+     */
+    function setSecOptions($array)
+    {
+        $this->_options[1] = $array;
+
+        if (empty($this->_elements)) {
+            $this->_nbElements = 2;
+            $this->_createElements();
+        } else {
+            // setDefaults has probably been called before this function
+            // check if all elements have been created
+            $totalNbElements = 2;
+            for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
+                $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
+                $this->_nbElements++;
+            }
+        }
+        
+        $this->_setOptions();
+    } // end func setSecOptions
+    
+    // }}}
+    // {{{ _setOptions()
+    
+    /**
+     * Sets the options for each select element
+     *
+     * @access    private
+     * @return    void
+     */
+    function _setOptions()
+    {
+        $toLoad = '';
+        foreach (array_keys($this->_elements) AS $key) {
+            $array = eval("return isset(\$this->_options[{$key}]{$toLoad})? \$this->_options[{$key}]{$toLoad}: null;");
+            if (is_array($array)) {
+                $select =& $this->_elements[$key];
+                $select->_options = array();
+                $select->loadArray($array);
+
+                $value  = is_array($v = $select->getValue()) ? $v[0] : key($array);
+                $toLoad .= '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $value) . '\']';
+            }
+        }
+    } // end func _setOptions
+    
+    // }}}
+    // {{{ setValue()
+
+    /**
+     * Sets values for group's elements
+     * 
+     * @param     array     $value    An array of 2 or more values, for the first,
+     *                                the second, the third etc. select
+     *
+     * @access    public
+     * @return    void
+     */
+    function setValue($value)
+    {
+        // fix for bug #6766. Hope this doesn't break anything more 
+        // after bug #7961. Forgot that _nbElements was used in
+        // _createElements() called in several places... 
+        $this->_nbElements = max($this->_nbElements, count($value));
+        parent::setValue($value);
+        $this->_setOptions();
+    } // end func setValue
+    
+    // }}}
+    // {{{ _createElements()
+
+    /**
+     * Creates all the elements for the group
+     * 
+     * @access    private
+     * @return    void
+     */
+    function _createElements()
+    {
+        for ($i = 0; $i < $this->_nbElements; $i++) {
+            $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
+        }
+    } // end func _createElements
+
+    // }}}
+    // {{{ toHtml()
+
+    function toHtml()
+    {
+        $this->_js = '';
+        if (!$this->_flagFrozen) {
+            // set the onchange attribute for each element except last
+            $keys     = array_keys($this->_elements);
+            $onChange = array();
+            for ($i = 0; $i < count($keys) - 1; $i++) {
+                $select =& $this->_elements[$keys[$i]];
+                $onChange[$i] = $select->getAttribute('onchange');
+                $select->updateAttributes(
+                    array('onchange' => '_hs_swapOptions(this.form, \'' . $this->_escapeString($this->getName()) . '\', ' . $keys[$i] . ');' . $onChange[$i])
+                );
+            }
+            
+            // create the js function to call
+            if (!defined('HTML_QUICKFORM_HIERSELECT_EXISTS')) {
+                $this->_js .= <<<JAVASCRIPT
+function _hs_findOptions(ary, keys)
+{
+    var key = keys.shift();
+    if (!key in ary) {
+        return {};
+    } else if (0 == keys.length) {
+        return ary[key];
+    } else {
+        return _hs_findOptions(ary[key], keys);
+    }
+}
+
+function _hs_findSelect(form, groupName, selectIndex)
+{
+    if (groupName+'['+ selectIndex +']' in form) {
+        return form[groupName+'['+ selectIndex +']']; 
+    } else {
+        return form[groupName+'['+ selectIndex +'][]']; 
+    }
+}
+
+function _hs_unescapeEntities(str)
+{
+    var div = document.createElement('div');
+    div.innerHTML = str;
+    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
+}
+
+function _hs_replaceOptions(ctl, optionList)
+{
+    var j = 0;
+    ctl.options.length = 0;
+    for (i in optionList) {
+        var optionText = (-1 == optionList[i].indexOf('&'))? optionList[i]: _hs_unescapeEntities(optionList[i]);
+        ctl.options[j++] = new Option(optionText, i, false, false);
+    }
+}
+
+function _hs_setValue(ctl, value)
+{
+    var testValue = {};
+    if (value instanceof Array) {
+        for (var i = 0; i < value.length; i++) {
+            testValue[value[i]] = true;
+        }
+    } else {
+        testValue[value] = true;
+    }
+    for (var i = 0; i < ctl.options.length; i++) {
+        if (ctl.options[i].value in testValue) {
+            ctl.options[i].selected = true;
+        }
+    }
+}
+
+function _hs_swapOptions(form, groupName, selectIndex)
+{
+    var hsValue = [];
+    for (var i = 0; i <= selectIndex; i++) {
+        hsValue[i] = _hs_findSelect(form, groupName, i).value;
+    }
+
+    _hs_replaceOptions(_hs_findSelect(form, groupName, selectIndex + 1), 
+                       _hs_findOptions(_hs_options[groupName][selectIndex], hsValue));
+    if (selectIndex + 1 < _hs_options[groupName].length) {
+        _hs_swapOptions(form, groupName, selectIndex + 1);
+    }
+}
+
+function _hs_onReset(form, groupNames)
+{
+    for (var i = 0; i < groupNames.length; i++) {
+        try {
+            for (var j = 0; j <= _hs_options[groupNames[i]].length; j++) {
+                _hs_setValue(_hs_findSelect(form, groupNames[i], j), _hs_defaults[groupNames[i]][j]);
+                if (j < _hs_options[groupNames[i]].length) {
+                    _hs_replaceOptions(_hs_findSelect(form, groupNames[i], j + 1), 
+                                       _hs_findOptions(_hs_options[groupNames[i]][j], _hs_defaults[groupNames[i]].slice(0, j + 1)));
+                }
+            }
+        } catch (e) {
+            if (!(e instanceof TypeError)) {
+                throw e;
+            }
+        }
+    }
+}
+
+function _hs_setupOnReset(form, groupNames)
+{
+    setTimeout(function() { _hs_onReset(form, groupNames); }, 25);
+}
+
+function _hs_onReload()
+{
+    var ctl;
+    for (var i = 0; i < document.forms.length; i++) {
+        for (var j in _hs_defaults) {
+            if (ctl = _hs_findSelect(document.forms[i], j, 0)) {
+                for (var k = 0; k < _hs_defaults[j].length; k++) {
+                    _hs_setValue(_hs_findSelect(document.forms[i], j, k), _hs_defaults[j][k]);
+                }
+            }
+        }
+    }
+
+    if (_hs_prevOnload) {
+        _hs_prevOnload();
+    }
+}
+
+var _hs_prevOnload = null;
+if (window.onload) {
+    _hs_prevOnload = window.onload;
+}
+window.onload = _hs_onReload;
+
+var _hs_options = {};
+var _hs_defaults = {};
+
+JAVASCRIPT;
+                define('HTML_QUICKFORM_HIERSELECT_EXISTS', true);
+            }
+            // option lists
+            $jsParts = array();
+            for ($i = 1; $i < $this->_nbElements; $i++) {
+                $jsParts[] = $this->_convertArrayToJavascript($this->_options[$i]);
+            }
+            $this->_js .= "\n_hs_options['" . $this->_escapeString($this->getName()) . "'] = [\n" .
+                          implode(",\n", $jsParts) .
+                          "\n];\n";
+            // default value; if we don't actually have any values yet just use
+            // the first option (for single selects) or empty array (for multiple)
+            $values = array();
+            foreach (array_keys($this->_elements) as $key) {
+                if (is_array($v = $this->_elements[$key]->getValue())) {
+                    $values[] = count($v) > 1? $v: $v[0];
+                } else {
+                    // XXX: accessing the supposedly private _options array
+                    $values[] = $this->_elements[$key]->getMultiple() || empty($this->_elements[$key]->_options[0])?
+                                array():
+                                $this->_elements[$key]->_options[0]['attr']['value'];
+                }
+            }
+            $this->_js .= "_hs_defaults['" . $this->_escapeString($this->getName()) . "'] = " .
+                          $this->_convertArrayToJavascript($values, false) . ";\n";
+        }
+        include_once('HTML/QuickForm/Renderer/Default.php');
+        $renderer =& new HTML_QuickForm_Renderer_Default();
+        $renderer->setElementTemplate('{element}');
+        parent::accept($renderer);
+
+        if (!empty($onChange)) {
+            $keys     = array_keys($this->_elements);
+            for ($i = 0; $i < count($keys) - 1; $i++) {
+                $this->_elements[$keys[$i]]->updateAttributes(array('onchange' => $onChange[$i]));
+            }
+        }
+        return (empty($this->_js)? '': "<script type=\"text/javascript\">\n//<![CDATA[\n" . $this->_js . "//]]>\n</script>") .
+               $renderer->toHtml();
+    } // end func toHtml
+
+    // }}}
+    // {{{ accept()
+
+    function accept(&$renderer, $required = false, $error = null)
+    {
+        $renderer->renderElement($this, $required, $error);
+    } // end func accept
+
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        if ('updateValue' == $event) {
+            // we need to call setValue() so that the secondary option
+            // matches the main option
+            return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller);
+        } else {
+            $ret = parent::onQuickFormEvent($event, $arg, $caller);
+            // add onreset handler to form to properly reset hierselect (see bug #2970)
+            if ('addElement' == $event) {
+                $onReset = $caller->getAttribute('onreset');
+                if (strlen($onReset)) {
+                    if (strpos($onReset, '_hs_setupOnReset')) {
+                        $caller->updateAttributes(array('onreset' => str_replace('_hs_setupOnReset(this, [', "_hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "', ", $onReset)));
+                    } else {
+                        $caller->updateAttributes(array('onreset' => "var temp = function() { {$onReset} } ; if (!temp()) { return false; } ; if (typeof _hs_setupOnReset != 'undefined') { return _hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "']); } "));
+                    }
+                } else {
+                    $caller->updateAttributes(array('onreset' => "if (typeof _hs_setupOnReset != 'undefined') { return _hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "']); } "));
+                }
+            }
+            return $ret;
+        }
+    } // end func onQuickFormEvent
+
+    // }}}
+    // {{{ _convertArrayToJavascript()
+
+   /**
+    * Converts PHP array to its Javascript analog
+    *
+    * @access private
+    * @param  array     PHP array to convert
+    * @param  bool      Generate Javascript object literal (default, works like PHP's associative array) or array literal
+    * @return string    Javascript representation of the value
+    */
+    function _convertArrayToJavascript($array, $assoc = true)
+    {
+        if (!is_array($array)) {
+            return $this->_convertScalarToJavascript($array);
+        } else {
+            $items = array();
+            foreach ($array as $key => $val) {
+                $item = $assoc? "'" . $this->_escapeString($key) . "': ": '';
+                if (is_array($val)) {
+                    $item .= $this->_convertArrayToJavascript($val, $assoc);
+                } else {
+                    $item .= $this->_convertScalarToJavascript($val);
+                }
+                $items[] = $item;
+            }
+        }
+        $js = implode(', ', $items);
+        return $assoc? '{ ' . $js . ' }': '[' . $js . ']';
+    }
+    
+    // }}}
+    // {{{ _convertScalarToJavascript()
+
+   /**
+    * Converts PHP's scalar value to its Javascript analog
+    *
+    * @access private
+    * @param  mixed     PHP value to convert
+    * @return string    Javascript representation of the value
+    */
+    function _convertScalarToJavascript($val)
+    {
+        if (is_bool($val)) {
+            return $val ? 'true' : 'false';
+        } elseif (is_int($val) || is_double($val)) {
+            return $val;
+        } elseif (is_string($val)) {
+            return "'" . $this->_escapeString($val) . "'";
+        } elseif (is_null($val)) {
+            return 'null';
+        } else {
+            // don't bother
+            return '{}';
+        }
+    }
+
+    // }}}
+    // {{{ _escapeString()
+
+   /**
+    * Quotes the string so that it can be used in Javascript string constants   
+    *
+    * @access private
+    * @param  string
+    * @return string
+    */
+    function _escapeString($str)
+    {
+        return strtr($str,array(
+            "\r"    => '\r',
+            "\n"    => '\n',
+            "\t"    => '\t',
+            "'"     => "\\'",
+            '"'     => '\"',
+            '\\'    => '\\\\'
+        ));
+    }
+
+    // }}}
+} // end class HTML_QuickForm_hierselect
+?>
\ No newline at end of file
diff --git a/lib/pear/HTML/QuickForm/html.php b/lib/pear/HTML/QuickForm/html.php
new file mode 100644 (file)
index 0000000..6d96e4f
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Author: Alexey Borzov <borz_off@cs.msu.su>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once 'HTML/QuickForm/static.php';
+
+/**
+ * A pseudo-element used for adding raw HTML to form
+ * 
+ * Intended for use with the default renderer only, template-based
+ * ones may (and probably will) completely ignore this
+ *
+ * @author Alexey Borzov <borz_off@cs.msu.su>
+ * @access public
+ */
+class HTML_QuickForm_html extends HTML_QuickForm_static
+{
+    // {{{ constructor
+
+   /**
+    * Class constructor
+    * 
+    * @param string $text   raw HTML to add
+    * @access public
+    * @return void
+    */
+    function HTML_QuickForm_html($text = null)
+    {
+        $this->HTML_QuickForm_static(null, null, $text);
+        $this->_type = 'html';
+    }
+
+    // }}}
+    // {{{ accept()
+
+   /**
+    * Accepts a renderer
+    *
+    * @param object     An HTML_QuickForm_Renderer object
+    * @access public
+    * @return void 
+    */
+    function accept(&$renderer)
+    {
+        $renderer->renderHtml($this);
+    } // end func accept
+
+    // }}}
+
+} //end class HTML_QuickForm_header
+?>
diff --git a/lib/pear/HTML/QuickForm/image.php b/lib/pear/HTML/QuickForm/image.php
new file mode 100644 (file)
index 0000000..a3cc2e3
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+require_once("HTML/QuickForm/input.php");
+
+/**
+ * HTML class for a image type element
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_image extends HTML_QuickForm_input
+{
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementName    (optional)Element name attribute
+     * @param     string    $src            (optional)Image source
+     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
+     *                                      or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_image($elementName=null, $src='', $attributes=null)
+    {
+        HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes);
+        $this->setType('image');
+        $this->setSource($src);
+    } // end class constructor
+
+    // }}}
+    // {{{ setSource()
+
+    /**
+     * Sets source for image element
+     * 
+     * @param     string    $src  source for image element
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setSource($src)
+    {
+        $this->updateAttributes(array('src' => $src));
+    } // end func setSource
+
+    // }}}
+    // {{{ setBorder()
+
+    /**
+     * Sets border size for image element
+     * 
+     * @param     string    $border  border for image element
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setBorder($border)
+    {
+        $this->updateAttributes(array('border' => $border));
+    } // end func setBorder
+
+    // }}}
+    // {{{ setAlign()
+
+    /**
+     * Sets alignment for image element
+     * 
+     * @param     string    $align  alignment for image element
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setAlign($align)
+    {
+        $this->updateAttributes(array('align' => $align));
+    } // end func setAlign
+
+    // }}}
+    // {{{ freeze()
+
+    /**
+     * Freeze the element so that only its value is returned
+     * 
+     * @access    public
+     * @return    void
+     */
+    function freeze()
+    {
+        return false;
+    } //end func freeze
+
+    // }}}
+
+} // end class HTML_QuickForm_image
+?>
diff --git a/lib/pear/HTML/QuickForm/input.php b/lib/pear/HTML/QuickForm/input.php
new file mode 100644 (file)
index 0000000..f182e7e
--- /dev/null
@@ -0,0 +1,202 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/element.php");
+
+/**
+ * Base class for input form elements
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ * @abstract
+ */
+class HTML_QuickForm_input extends HTML_QuickForm_element
+{
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param    string     Input field name attribute
+     * @param    mixed      Label(s) for the input field
+     * @param    mixed      Either a typical HTML attribute string or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_input($elementName=null, $elementLabel=null, $attributes=null)
+    {
+        $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
+    } //end constructor
+
+    // }}}
+    // {{{ setType()
+
+    /**
+     * Sets the element type
+     *
+     * @param     string    $type   Element type
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setType($type)
+    {
+        $this->_type = $type;
+        $this->updateAttributes(array('type'=>$type));
+    } // end func setType
+    
+    // }}}
+    // {{{ setName()
+
+    /**
+     * Sets the input field name
+     * 
+     * @param     string    $name   Input field name attribute
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setName($name)
+    {
+        $this->updateAttributes(array('name'=>$name));
+    } //end func setName
+    
+    // }}}
+    // {{{ getName()
+
+    /**
+     * Returns the element name
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getName()
+    {
+        return $this->getAttribute('name');
+    } //end func getName
+    
+    // }}}
+    // {{{ setValue()
+
+    /**
+     * Sets the value of the form element
+     *
+     * @param     string    $value      Default value of the form element
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setValue($value)
+    {
+        $this->updateAttributes(array('value'=>$value));
+    } // end func setValue
+
+    // }}}
+    // {{{ getValue()
+
+    /**
+     * Returns the value of the form element
+     *
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getValue()
+    {
+        return $this->getAttribute('value');
+    } // end func getValue
+    
+    // }}}
+    // {{{ toHtml()
+
+    /**
+     * Returns the input field in HTML
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function toHtml()
+    {
+        if ($this->_flagFrozen) {
+            return $this->getFrozenHtml();
+        } else {
+            return $this->_getTabs() . '<input' . $this->_getAttrString($this->_attributes) . ' />';
+        }
+    } //end func toHtml
+
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    /**
+     * Called by HTML_QuickForm whenever form event is made on this element
+     *
+     * @param     string    $event  Name of event
+     * @param     mixed     $arg    event arguments
+     * @param     object    $caller calling object
+     * @since     1.0
+     * @access    public
+     * @return    void
+     * @throws    
+     */
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        // do not use submit values for button-type elements
+        $type = $this->getType();
+        if (('updateValue' != $event) ||
+            ('submit' != $type && 'reset' != $type && 'image' != $type && 'button' != $type)) {
+            parent::onQuickFormEvent($event, $arg, $caller);
+        } else {
+            $value = $this->_findValue($caller->_constantValues);
+            if (null === $value) {
+                $value = $this->_findValue($caller->_defaultValues);
+            }
+            if (null !== $value) {
+                $this->setValue($value);
+            }
+        }
+        return true;
+    } // end func onQuickFormEvent
+
+    // }}}
+    // {{{ exportValue()
+
+   /**
+    * We don't need values from button-type elements (except submit) and files
+    */
+    function exportValue(&$submitValues, $assoc = false)
+    {
+        $type = $this->getType();
+        if ('reset' == $type || 'image' == $type || 'button' == $type || 'file' == $type) {
+            return null;
+        } else {
+            return parent::exportValue($submitValues, $assoc);
+        }
+    }
+    
+    // }}}
+} // end class HTML_QuickForm_element
+?>
diff --git a/lib/pear/HTML/QuickForm/link.php b/lib/pear/HTML/QuickForm/link.php
new file mode 100644 (file)
index 0000000..947f76c
--- /dev/null
@@ -0,0 +1,192 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+
+require_once 'HTML/QuickForm/static.php';
+
+/**
+ * HTML class for a link type field
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_link extends HTML_QuickForm_static
+{
+    // {{{ properties
+
+    /**
+     * Link display text
+     * @var       string
+     * @since     1.0
+     * @access    private
+     */
+    var $_text = "";
+
+    // }}}
+    // {{{ constructor
+    
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementLabel   (optional)Link label
+     * @param     string    $href           (optional)Link href
+     * @param     string    $text           (optional)Link display text
+     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
+     *                                      or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     * @throws    
+     */
+    function HTML_QuickForm_link($elementName=null, $elementLabel=null, $href=null, $text=null, $attributes=null)
+    {
+        HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
+        $this->_persistantFreeze = false;
+        $this->_type = 'link';
+        $this->setHref($href);
+        $this->_text = $text;
+    } //end constructor
+    
+    // }}}
+    // {{{ setName()
+
+    /**
+     * Sets the input field name
+     * 
+     * @param     string    $name   Input field name attribute
+     * @since     1.0
+     * @access    public
+     * @return    void
+     * @throws    
+     */
+    function setName($name)
+    {
+        $this->updateAttributes(array('name'=>$name));
+    } //end func setName
+    
+    // }}}
+    // {{{ getName()
+
+    /**
+     * Returns the element name
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     * @throws    
+     */
+    function getName()
+    {
+        return $this->getAttribute('name');
+    } //end func getName
+
+    // }}}
+    // {{{ setValue()
+
+    /**
+     * Sets value for textarea element
+     * 
+     * @param     string    $value  Value for password element
+     * @since     1.0
+     * @access    public
+     * @return    void
+     * @throws    
+     */
+    function setValue($value)
+    {
+        return;
+    } //end func setValue
+    
+    // }}}
+    // {{{ getValue()
+
+    /**
+     * Returns the value of the form element
+     *
+     * @since     1.0
+     * @access    public
+     * @return    void
+     * @throws    
+     */
+    function getValue()
+    {
+        return;
+    } // end func getValue
+
+    
+    // }}}
+    // {{{ setHref()
+
+    /**
+     * Sets the links href
+     *
+     * @param     string    $href
+     * @since     1.0
+     * @access    public
+     * @return    void
+     * @throws    
+     */
+    function setHref($href)
+    {
+        $this->updateAttributes(array('href'=>$href));
+    } // end func setHref
+
+    // }}}
+    // {{{ toHtml()
+
+    /**
+     * Returns the textarea element in HTML
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     * @throws    
+     */
+    function toHtml()
+    {
+        $tabs = $this->_getTabs();
+        $html = "$tabs<a".$this->_getAttrString($this->_attributes).">";
+        $html .= $this->_text;
+        $html .= "</a>";
+        return $html;
+    } //end func toHtml
+    
+    // }}}
+    // {{{ getFrozenHtml()
+
+    /**
+     * Returns the value of field without HTML tags (in this case, value is changed to a mask)
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     * @throws    
+     */
+    function getFrozenHtml()
+    {
+        return;
+    } //end func getFrozenHtml
+
+    // }}}
+
+} //end class HTML_QuickForm_textarea
+?>
diff --git a/lib/pear/HTML/QuickForm/password.php b/lib/pear/HTML/QuickForm/password.php
new file mode 100644 (file)
index 0000000..a83d505
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/input.php");
+
+/**
+ * HTML class for a password type field
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.1
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_password extends HTML_QuickForm_input
+{
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementName    (optional)Input field name attribute
+     * @param     string    $elementLabel   (optional)Input field label
+     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
+     *                                      or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     * @throws    
+     */
+    function HTML_QuickForm_password($elementName=null, $elementLabel=null, $attributes=null)
+    {
+        HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
+        $this->setType('password');
+    } //end constructor
+    
+    // }}}
+    // {{{ setSize()
+
+    /**
+     * Sets size of password element
+     * 
+     * @param     string    $size  Size of password field
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setSize($size)
+    {
+        $this->updateAttributes(array('size'=>$size));
+    } //end func setSize
+
+    // }}}
+    // {{{ setMaxlength()
+
+    /**
+     * Sets maxlength of password element
+     * 
+     * @param     string    $maxlength  Maximum length of password field
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setMaxlength($maxlength)
+    {
+        $this->updateAttributes(array('maxlength'=>$maxlength));
+    } //end func setMaxlength
+        
+    // }}}
+    // {{{ getFrozenHtml()
+
+    /**
+     * Returns the value of field without HTML tags (in this case, value is changed to a mask)
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     * @throws    
+     */
+    function getFrozenHtml()
+    {
+        $value = $this->getValue();
+        return ('' != $value? '**********': '&nbsp;') .
+               $this->_getPersistantData();
+    } //end func getFrozenHtml
+
+    // }}}
+
+} //end class HTML_QuickForm_password
+?>
diff --git a/lib/pear/HTML/QuickForm/radio.php b/lib/pear/HTML/QuickForm/radio.php
new file mode 100644 (file)
index 0000000..963168b
--- /dev/null
@@ -0,0 +1,244 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/input.php');
+
+/**
+ * HTML class for a radio type element
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.1
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_radio extends HTML_QuickForm_input
+{
+    // {{{ properties
+
+    /**
+     * Radio display text
+     * @var       string
+     * @since     1.1
+     * @access    private
+     */
+    var $_text = '';
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    Input field name attribute
+     * @param     mixed     Label(s) for a field
+     * @param     string    Text to display near the radio
+     * @param     string    Input field value
+     * @param     mixed     Either a typical HTML attribute string or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_radio($elementName=null, $elementLabel=null, $text=null, $value=null, $attributes=null)
+    {
+        $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
+        if (isset($value)) {
+            $this->setValue($value);
+        }
+        $this->_persistantFreeze = true;
+        $this->setType('radio');
+        $this->_text = $text;
+        $this->_generateId();
+    } //end constructor
+    
+    // }}}
+    // {{{ setChecked()
+
+    /**
+     * Sets whether radio button is checked
+     * 
+     * @param     bool    $checked  Whether the field is checked or not
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setChecked($checked)
+    {
+        if (!$checked) {
+            $this->removeAttribute('checked');
+        } else {
+            $this->updateAttributes(array('checked'=>'checked'));
+        }
+    } //end func setChecked
+
+    // }}}
+    // {{{ getChecked()
+
+    /**
+     * Returns whether radio button is checked
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getChecked()
+    {
+        return $this->getAttribute('checked');
+    } //end func getChecked
+        
+    // }}}
+    // {{{ toHtml()
+
+    /**
+     * Returns the radio element in HTML
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function toHtml()
+    {
+        if (0 == strlen($this->_text)) {
+            $label = '';
+        } elseif ($this->_flagFrozen) {
+            $label = $this->_text;
+        } else {
+            $label = '<label for="' . $this->getAttribute('id') . '">' . $this->_text . '</label>';
+        }
+        return HTML_QuickForm_input::toHtml() . $label;
+    } //end func toHtml
+    
+    // }}}
+    // {{{ getFrozenHtml()
+
+    /**
+     * Returns the value of field without HTML tags
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getFrozenHtml()
+    {
+        if ($this->getChecked()) {
+            return '<tt>(x)</tt>' .
+                   $this->_getPersistantData();
+        } else {
+            return '<tt>( )</tt>';
+        }
+    } //end func getFrozenHtml
+
+    // }}}
+    // {{{ setText()
+
+    /**
+     * Sets the radio text
+     * 
+     * @param     string    $text  Text to display near the radio button
+     * @since     1.1
+     * @access    public
+     * @return    void
+     */
+    function setText($text)
+    {
+        $this->_text = $text;
+    } //end func setText
+
+    // }}}
+    // {{{ getText()
+
+    /**
+     * Returns the radio text 
+     * 
+     * @since     1.1
+     * @access    public
+     * @return    string
+     */
+    function getText()
+    {
+        return $this->_text;
+    } //end func getText
+
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    /**
+     * Called by HTML_QuickForm whenever form event is made on this element
+     *
+     * @param     string    $event  Name of event
+     * @param     mixed     $arg    event arguments
+     * @param     object    $caller calling object
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        switch ($event) {
+            case 'updateValue':
+                // constant values override both default and submitted ones
+                // default values are overriden by submitted
+                $value = $this->_findValue($caller->_constantValues);
+                if (null === $value) {
+                    $value = $this->_findValue($caller->_submitValues);
+                    if (null === $value) {
+                        $value = $this->_findValue($caller->_defaultValues);
+                    }
+                }
+                if ($value == $this->getValue()) {
+                    $this->setChecked(true);
+                } else {
+                    $this->setChecked(false);
+                }
+                break;
+            case 'setGroupValue':
+                if ($arg == $this->getValue()) {
+                    $this->setChecked(true);
+                } else {
+                    $this->setChecked(false);
+                }
+                break;
+            default:
+                parent::onQuickFormEvent($event, $arg, $caller);
+        }
+        return true;
+    } // end func onQuickFormLoad
+
+    // }}}
+    // {{{ exportValue()
+
+   /**
+    * Returns the value attribute if the radio is checked, null if it is not
+    */
+    function exportValue(&$submitValues, $assoc = false)
+    {
+        $value = $this->_findValue($submitValues);
+        if (null === $value) {
+            $value = $this->getChecked()? $this->getValue(): null;
+        } elseif ($value != $this->getValue()) {
+            $value = null;
+        }
+        return $this->_prepareValue($value, $assoc);
+    }
+    
+    // }}}
+} //end class HTML_QuickForm_radio
+?>
diff --git a/lib/pear/HTML/QuickForm/reset.php b/lib/pear/HTML/QuickForm/reset.php
new file mode 100644 (file)
index 0000000..3533653
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/input.php");
+
+/**
+ * HTML class for a reset type element
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.1
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_reset extends HTML_QuickForm_input
+{
+    // {{{ constructor
+    
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementName    (optional)Input field name attribute
+     * @param     string    $value          (optional)Input field value
+     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
+     *                                      or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_reset($elementName=null, $value=null, $attributes=null)
+    {
+        HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes);
+        $this->setValue($value);
+        $this->setType('reset');
+    } //end constructor
+
+    // }}}
+    // {{{ freeze()
+
+    /**
+     * Freeze the element so that only its value is returned
+     * 
+     * @access    public
+     * @return    void
+     */
+    function freeze()
+    {
+        return false;
+    } //end func freeze
+
+    // }}}
+
+} //end class HTML_QuickForm_reset
+?>
diff --git a/lib/pear/HTML/QuickForm/select.php b/lib/pear/HTML/QuickForm/select.php
new file mode 100644 (file)
index 0000000..eec2b16
--- /dev/null
@@ -0,0 +1,604 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once('HTML/QuickForm/element.php');
+
+/**
+ * Class to dynamically create an HTML SELECT
+ *
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_select extends HTML_QuickForm_element {
+    
+    // {{{ properties
+
+    /**
+     * Contains the select options
+     *
+     * @var       array
+     * @since     1.0
+     * @access    private
+     */
+    var $_options = array();
+    
+    /**
+     * Default values of the SELECT
+     * 
+     * @var       string
+     * @since     1.0
+     * @access    private
+     */
+    var $_values = null;
+
+    // }}}
+    // {{{ constructor
+        
+    /**
+     * Class constructor
+     * 
+     * @param     string    Select name attribute
+     * @param     mixed     Label(s) for the select
+     * @param     mixed     Data to be used to populate options
+     * @param     mixed     Either a typical HTML attribute string or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_select($elementName=null, $elementLabel=null, $options=null, $attributes=null)
+    {
+        HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
+        $this->_persistantFreeze = true;
+        $this->_type = 'select';
+        if (isset($options)) {
+            $this->load($options);
+        }
+    } //end constructor
+    
+    // }}}
+    // {{{ apiVersion()
+
+    /**
+     * Returns the current API version 
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    double
+     */
+    function apiVersion()
+    {
+        return 2.3;
+    } //end func apiVersion
+
+    // }}}
+    // {{{ setSelected()
+
+    /**
+     * Sets the default values of the select box
+     * 
+     * @param     mixed    $values  Array or comma delimited string of selected values
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setSelected($values)
+    {
+        if (is_string($values) && $this->getMultiple()) {
+            $values = split("[ ]?,[ ]?", $values);
+        }
+        if (is_array($values)) {
+            $this->_values = array_values($values);
+        } else {
+            $this->_values = array($values);
+        }
+    } //end func setSelected
+    
+    // }}}
+    // {{{ getSelected()
+
+    /**
+     * Returns an array of the selected values
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    array of selected values
+     */
+    function getSelected()
+    {
+        return $this->_values;
+    } // end func getSelected
+
+    // }}}
+    // {{{ setName()
+
+    /**
+     * Sets the input field name
+     * 
+     * @param     string    $name   Input field name attribute
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setName($name)
+    {
+        $this->updateAttributes(array('name' => $name));
+    } //end func setName
+    
+    // }}}
+    // {{{ getName()
+
+    /**
+     * Returns the element name
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getName()
+    {
+        return $this->getAttribute('name');
+    } //end func getName
+
+    // }}}
+    // {{{ getPrivateName()
+
+    /**
+     * Returns the element name (possibly with brackets appended)
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getPrivateName()
+    {
+        if ($this->getAttribute('multiple')) {
+            return $this->getName() . '[]';
+        } else {
+            return $this->getName();
+        }
+    } //end func getPrivateName
+
+    // }}}
+    // {{{ setValue()
+
+    /**
+     * Sets the value of the form element
+     *
+     * @param     mixed    $values  Array or comma delimited string of selected values
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setValue($value)
+    {
+        $this->setSelected($value);
+    } // end func setValue
+
+    // }}}
+    // {{{ getValue()
+
+    /**
+     * Returns an array of the selected values
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    array of selected values
+     */
+    function getValue()
+    {
+        return $this->_values;
+    } // end func getValue
+
+    // }}}
+    // {{{ setSize()
+
+    /**
+     * Sets the select field size, only applies to 'multiple' selects
+     * 
+     * @param     int    $size  Size of select  field
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setSize($size)
+    {
+        $this->updateAttributes(array('size' => $size));
+    } //end func setSize
+    
+    // }}}
+    // {{{ getSize()
+
+    /**
+     * Returns the select field size
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    int
+     */
+    function getSize()
+    {
+        return $this->getAttribute('size');
+    } //end func getSize
+
+    // }}}
+    // {{{ setMultiple()
+
+    /**
+     * Sets the select mutiple attribute
+     * 
+     * @param     bool    $multiple  Whether the select supports multi-selections
+     * @since     1.2
+     * @access    public
+     * @return    void
+     */
+    function setMultiple($multiple)
+    {
+        if ($multiple) {
+            $this->updateAttributes(array('multiple' => 'multiple'));
+        } else {
+            $this->removeAttribute('multiple');
+        }
+    } //end func setMultiple
+    
+    // }}}
+    // {{{ getMultiple()
+
+    /**
+     * Returns the select mutiple attribute
+     * 
+     * @since     1.2
+     * @access    public
+     * @return    bool    true if multiple select, false otherwise
+     */
+    function getMultiple()
+    {
+        return (bool)$this->getAttribute('multiple');
+    } //end func getMultiple
+
+    // }}}
+    // {{{ addOption()
+
+    /**
+     * Adds a new OPTION to the SELECT
+     *
+     * @param     string    $text       Display text for the OPTION
+     * @param     string    $value      Value for the OPTION
+     * @param     mixed     $attributes Either a typical HTML attribute string 
+     *                                  or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function addOption($text, $value, $attributes=null)
+    {
+        if (null === $attributes) {
+            $attributes = array('value' => $value);
+        } else {
+            $attributes = $this->_parseAttributes($attributes);
+            if (isset($attributes['selected'])) {
+                // the 'selected' attribute will be set in toHtml()
+                $this->_removeAttr('selected', $attributes);
+                if (is_null($this->_values)) {
+                    $this->_values = array($value);
+                } elseif (!in_array($value, $this->_values)) {
+                    $this->_values[] = $value;
+                }
+            }
+            $this->_updateAttrArray($attributes, array('value' => $value));
+        }
+        $this->_options[] = array('text' => $text, 'attr' => $attributes);
+    } // end func addOption
+    
+    // }}}
+    // {{{ loadArray()
+
+    /**
+     * Loads the options from an associative array
+     * 
+     * @param     array    $arr     Associative array of options
+     * @param     mixed    $values  (optional) Array or comma delimited string of selected values
+     * @since     1.0
+     * @access    public
+     * @return    PEAR_Error on error or true
+     * @throws    PEAR_Error
+     */
+    function loadArray($arr, $values=null)
+    {
+        if (!is_array($arr)) {
+            return PEAR::raiseError('Argument 1 of HTML_Select::loadArray is not a valid array');
+        }
+        if (isset($values)) {
+            $this->setSelected($values);
+        }
+        foreach ($arr as $key => $val) {
+            // Warning: new API since release 2.3
+            $this->addOption($val, $key);
+        }
+        return true;
+    } // end func loadArray
+
+    // }}}
+    // {{{ loadDbResult()
+
+    /**
+     * Loads the options from DB_result object
+     * 
+     * If no column names are specified the first two columns of the result are
+     * used as the text and value columns respectively
+     * @param     object    $result     DB_result object 
+     * @param     string    $textCol    (optional) Name of column to display as the OPTION text 
+     * @param     string    $valueCol   (optional) Name of column to use as the OPTION value 
+     * @param     mixed     $values     (optional) Array or comma delimited string of selected values
+     * @since     1.0
+     * @access    public
+     * @return    PEAR_Error on error or true
+     * @throws    PEAR_Error
+     */
+    function loadDbResult(&$result, $textCol=null, $valueCol=null, $values=null)
+    {
+        if (!is_object($result) || !is_a($result, 'db_result')) {
+            return PEAR::raiseError('Argument 1 of HTML_Select::loadDbResult is not a valid DB_result');
+        }
+        if (isset($values)) {
+            $this->setValue($values);
+        }
+        $fetchMode = ($textCol && $valueCol) ? DB_FETCHMODE_ASSOC : DB_FETCHMODE_ORDERED;
+        while (is_array($row = $result->fetchRow($fetchMode)) ) {
+            if ($fetchMode == DB_FETCHMODE_ASSOC) {
+                $this->addOption($row[$textCol], $row[$valueCol]);
+            } else {
+                $this->addOption($row[0], $row[1]);
+            }
+        }
+        return true;
+    } // end func loadDbResult
+    
+    // }}}
+    // {{{ loadQuery()
+
+    /**
+     * Queries a database and loads the options from the results
+     *
+     * @param     mixed     $conn       Either an existing DB connection or a valid dsn 
+     * @param     string    $sql        SQL query string
+     * @param     string    $textCol    (optional) Name of column to display as the OPTION text 
+     * @param     string    $valueCol   (optional) Name of column to use as the OPTION value 
+     * @param     mixed     $values     (optional) Array or comma delimited string of selected values
+     * @since     1.1
+     * @access    public
+     * @return    void
+     * @throws    PEAR_Error
+     */
+    function loadQuery(&$conn, $sql, $textCol=null, $valueCol=null, $values=null)
+    {
+        if (is_string($conn)) {
+            require_once('DB.php');
+            $dbConn = &DB::connect($conn, true);
+            if (DB::isError($dbConn)) {
+                return $dbConn;
+            }
+        } elseif (is_subclass_of($conn, "db_common")) {
+            $dbConn = &$conn;
+        } else {
+            return PEAR::raiseError('Argument 1 of HTML_Select::loadQuery is not a valid type');
+        }
+        $result = $dbConn->query($sql);
+        if (DB::isError($result)) {
+            return $result;
+        }
+        $this->loadDbResult($result, $textCol, $valueCol, $values);
+        $result->free();
+        if (is_string($conn)) {
+            $dbConn->disconnect();
+        }
+        return true;
+    } // end func loadQuery
+
+    // }}}
+    // {{{ load()
+
+    /**
+     * Loads options from different types of data sources
+     *
+     * This method is a simulated overloaded method.  The arguments, other than the
+     * first are optional and only mean something depending on the type of the first argument.
+     * If the first argument is an array then all arguments are passed in order to loadArray.
+     * If the first argument is a db_result then all arguments are passed in order to loadDbResult.
+     * If the first argument is a string or a DB connection then all arguments are 
+     * passed in order to loadQuery.
+     * @param     mixed     $options     Options source currently supports assoc array or DB_result
+     * @param     mixed     $param1     (optional) See function detail
+     * @param     mixed     $param2     (optional) See function detail
+     * @param     mixed     $param3     (optional) See function detail
+     * @param     mixed     $param4     (optional) See function detail
+     * @since     1.1
+     * @access    public
+     * @return    PEAR_Error on error or true
+     * @throws    PEAR_Error
+     */
+    function load(&$options, $param1=null, $param2=null, $param3=null, $param4=null)
+    {
+        switch (true) {
+            case is_array($options):
+                return $this->loadArray($options, $param1);
+                break;
+            case (is_a($options, 'db_result')):
+                return $this->loadDbResult($options, $param1, $param2, $param3);
+                break;
+            case (is_string($options) && !empty($options) || is_subclass_of($options, "db_common")):
+                return $this->loadQuery($options, $param1, $param2, $param3, $param4);
+                break;
+        }
+    } // end func load
+    
+    // }}}
+    // {{{ toHtml()
+
+    /**
+     * Returns the SELECT in HTML
+     *
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function toHtml()
+    {
+        if ($this->_flagFrozen) {
+            return $this->getFrozenHtml();
+        } else {
+            $tabs    = $this->_getTabs();
+            $strHtml = '';
+
+            if ($this->getComment() != '') {
+                $strHtml .= $tabs . '<!-- ' . $this->getComment() . " //-->\n";
+            }
+
+            if (!$this->getMultiple()) {
+                $attrString = $this->_getAttrString($this->_attributes);
+            } else {
+                $myName = $this->getName();
+                $this->setName($myName . '[]');
+                $attrString = $this->_getAttrString($this->_attributes);
+                $this->setName($myName);
+            }
+            $strHtml .= $tabs . '<select' . $attrString . ">\n";
+
+            foreach ($this->_options as $option) {
+                if (is_array($this->_values) && in_array((string)$option['attr']['value'], $this->_values)) {
+                    $this->_updateAttrArray($option['attr'], array('selected' => 'selected'));
+                }
+                $strHtml .= $tabs . "\t<option" . $this->_getAttrString($option['attr']) . '>' .
+                            $option['text'] . "</option>\n";
+            }
+
+            return $strHtml . $tabs . '</select>';
+        }
+    } //end func toHtml
+    
+    // }}}
+    // {{{ getFrozenHtml()
+
+    /**
+     * Returns the value of field without HTML tags
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getFrozenHtml()
+    {
+        $value = array();
+        if (is_array($this->_values)) {
+            foreach ($this->_values as $key => $val) {
+                for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) {
+                    if ((string)$val == (string)$this->_options[$i]['attr']['value']) {
+                        $value[$key] = $this->_options[$i]['text'];
+                        break;
+                    }
+                }
+            }
+        }
+        $html = empty($value)? '&nbsp;': join('<br />', $value);
+        if ($this->_persistantFreeze) {
+            $name = $this->getPrivateName();
+            // Only use id attribute if doing single hidden input
+            if (1 == count($value)) {
+                $id     = $this->getAttribute('id');
+                $idAttr = isset($id)? array('id' => $id): array();
+            } else {
+                $idAttr = array();
+            }
+            foreach ($value as $key => $item) {
+                $html .= '<input' . $this->_getAttrString(array(
+                             'type'  => 'hidden',
+                             'name'  => $name,
+                             'value' => $this->_values[$key]
+                         ) + $idAttr) . ' />';
+            }
+        }
+        return $html;
+    } //end func getFrozenHtml
+
+    // }}}
+    // {{{ exportValue()
+
+   /**
+    * We check the options and return only the values that _could_ have been
+    * selected. We also return a scalar value if select is not "multiple"
+    */
+    function exportValue(&$submitValues, $assoc = false)
+    {
+        $value = $this->_findValue($submitValues);
+        if (is_null($value)) {
+            $value = $this->getValue();
+        } elseif(!is_array($value)) {
+            $value = array($value);
+        }
+        if (is_array($value) && !empty($this->_options)) {
+            $cleanValue = null;
+            foreach ($value as $v) {
+                for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) {
+                    if ($v == $this->_options[$i]['attr']['value']) {
+                        $cleanValue[] = $v;
+                        break;
+                    }
+                }
+            }
+        } else {
+            $cleanValue = $value;
+        }
+        if (is_array($cleanValue) && !$this->getMultiple()) {
+            return $this->_prepareValue($cleanValue[0], $assoc);
+        } else {
+            return $this->_prepareValue($cleanValue, $assoc);
+        }
+    }
+    
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        if ('updateValue' == $event) {
+            $value = $this->_findValue($caller->_constantValues);
+            if (null === $value) {
+                $value = $this->_findValue($caller->_submitValues);
+                // Fix for bug #4465 & #5269
+                // XXX: should we push this to element::onQuickFormEvent()?
+                if (null === $value && (!$caller->isSubmitted() || !$this->getMultiple())) {
+                    $value = $this->_findValue($caller->_defaultValues);
+                }
+            }
+            if (null !== $value) {
+                $this->setValue($value);
+            }
+            return true;
+        } else {
+            return parent::onQuickFormEvent($event, $arg, $caller);
+        }
+    }
+
+    // }}}
+} //end class HTML_QuickForm_select
+?>
diff --git a/lib/pear/HTML/QuickForm/static.php b/lib/pear/HTML/QuickForm/static.php
new file mode 100644 (file)
index 0000000..6987931
--- /dev/null
@@ -0,0 +1,193 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/element.php");
+
+/**
+ * HTML class for static data
+ * 
+ * @author       Wojciech Gdela <eltehaem@poczta.onet.pl>
+ * @access       public
+ */
+class HTML_QuickForm_static extends HTML_QuickForm_element {
+    
+    // {{{ properties
+
+    /**
+     * Display text
+     * @var       string
+     * @access    private
+     */
+    var $_text = null;
+
+    // }}}
+    // {{{ constructor
+    
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementLabel   (optional)Label
+     * @param     string    $text           (optional)Display text
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_static($elementName=null, $elementLabel=null, $text=null)
+    {
+        HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel);
+        $this->_persistantFreeze = false;
+        $this->_type = 'static';
+        $this->_text = $text;
+    } //end constructor
+    
+    // }}}
+    // {{{ setName()
+
+    /**
+     * Sets the element name
+     * 
+     * @param     string    $name   Element name
+     * @access    public
+     * @return    void
+     */
+    function setName($name)
+    {
+        $this->updateAttributes(array('name'=>$name));
+    } //end func setName
+    
+    // }}}
+    // {{{ getName()
+
+    /**
+     * Returns the element name
+     * 
+     * @access    public
+     * @return    string
+     */
+    function getName()
+    {
+        return $this->getAttribute('name');
+    } //end func getName
+
+    // }}}
+    // {{{ setText()
+
+    /**
+     * Sets the text
+     *
+     * @param     string    $text
+     * @access    public
+     * @return    void
+     */
+    function setText($text)
+    {
+        $this->_text = $text;
+    } // end func setText
+
+    // }}}
+    // {{{ setValue()
+
+    /**
+     * Sets the text (uses the standard setValue call to emulate a form element.
+     *
+     * @param     string    $text
+     * @access    public
+     * @return    void
+     */
+    function setValue($text)
+    {
+        $this->setText($text);
+    } // end func setValue
+
+    // }}}    
+    // {{{ toHtml()
+
+    /**
+     * Returns the static text element in HTML
+     * 
+     * @access    public
+     * @return    string
+     */
+    function toHtml()
+    {
+        return $this->_getTabs() . $this->_text;
+    } //end func toHtml
+    
+    // }}}
+    // {{{ getFrozenHtml()
+
+    /**
+     * Returns the value of field without HTML tags
+     * 
+     * @access    public
+     * @return    string
+     */
+    function getFrozenHtml()
+    {
+        return $this->toHtml();
+    } //end func getFrozenHtml
+
+    // }}}
+    // {{{ onQuickFormEvent()
+
+    /**
+     * Called by HTML_QuickForm whenever form event is made on this element
+     *
+     * @param     string    $event  Name of event
+     * @param     mixed     $arg    event arguments
+     * @param     object    $caller calling object
+     * @since     1.0
+     * @access    public
+     * @return    void
+     * @throws    
+     */
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        switch ($event) {
+            case 'updateValue':
+                // do NOT use submitted values for static elements
+                $value = $this->_findValue($caller->_constantValues);
+                if (null === $value) {
+                    $value = $this->_findValue($caller->_defaultValues);
+                }
+                if (null !== $value) {
+                    $this->setValue($value);
+                }
+                break;
+            default:
+                parent::onQuickFormEvent($event, $arg, $caller);
+        }
+        return true;
+    } // end func onQuickFormEvent
+
+    // }}}
+    // {{{ exportValue()
+
+   /**
+    * We override this here because we don't want any values from static elements
+    */
+    function exportValue(&$submitValues, $assoc = false)
+    {
+        return null;
+    }
+    
+    // }}}
+} //end class HTML_QuickForm_static
+?>
diff --git a/lib/pear/HTML/QuickForm/submit.php b/lib/pear/HTML/QuickForm/submit.php
new file mode 100644 (file)
index 0000000..e1d3e7d
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/input.php");
+
+/**
+ * HTML class for a submit type element
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_submit extends HTML_QuickForm_input
+{
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    Input field name attribute
+     * @param     string    Input field value
+     * @param     mixed     Either a typical HTML attribute string or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_submit($elementName=null, $value=null, $attributes=null)
+    {
+        HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes);
+        $this->setValue($value);
+        $this->setType('submit');
+    } //end constructor
+    
+    // }}}
+    // {{{ freeze()
+
+    /**
+     * Freeze the element so that only its value is returned
+     * 
+     * @access    public
+     * @return    void
+     */
+    function freeze()
+    {
+        return false;
+    } //end func freeze
+
+    // }}}
+    // {{{ exportValue()
+
+   /**
+    * Only return the value if it is found within $submitValues (i.e. if
+    * this particular submit button was clicked)
+    */
+    function exportValue(&$submitValues, $assoc = false)
+    {
+        return $this->_prepareValue($this->_findValue($submitValues), $assoc);
+    }
+
+    // }}}
+} //end class HTML_QuickForm_submit
+?>
diff --git a/lib/pear/HTML/QuickForm/text.php b/lib/pear/HTML/QuickForm/text.php
new file mode 100644 (file)
index 0000000..9d6d9de
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/input.php");
+
+/**
+ * HTML class for a text field
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_text extends HTML_QuickForm_input
+{
+                
+    // {{{ constructor
+
+    /**
+     * Class constructor
+     * 
+     * @param     string    $elementName    (optional)Input field name attribute
+     * @param     string    $elementLabel   (optional)Input field label
+     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
+     *                                      or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_text($elementName=null, $elementLabel=null, $attributes=null)
+    {
+        HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
+        $this->_persistantFreeze = true;
+        $this->setType('text');
+    } //end constructor
+        
+    // }}}
+    // {{{ setSize()
+
+    /**
+     * Sets size of text field
+     * 
+     * @param     string    $size  Size of text field
+     * @since     1.3
+     * @access    public
+     * @return    void
+     */
+    function setSize($size)
+    {
+        $this->updateAttributes(array('size'=>$size));
+    } //end func setSize
+
+    // }}}
+    // {{{ setMaxlength()
+
+    /**
+     * Sets maxlength of text field
+     * 
+     * @param     string    $maxlength  Maximum length of text field
+     * @since     1.3
+     * @access    public
+     * @return    void
+     */
+    function setMaxlength($maxlength)
+    {
+        $this->updateAttributes(array('maxlength'=>$maxlength));
+    } //end func setMaxlength
+
+    // }}}
+    
+} //end class HTML_QuickForm_text
+?>
diff --git a/lib/pear/HTML/QuickForm/textarea.php b/lib/pear/HTML/QuickForm/textarea.php
new file mode 100644 (file)
index 0000000..7aa0af2
--- /dev/null
@@ -0,0 +1,222 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Adam Daniel <adaniel1@eesus.jnj.com>                        |
+// |          Bertrand Mansion <bmansion@mamasam.com>                     |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once("HTML/QuickForm/element.php");
+
+/**
+ * HTML class for a textarea type field
+ * 
+ * @author       Adam Daniel <adaniel1@eesus.jnj.com>
+ * @author       Bertrand Mansion <bmansion@mamasam.com>
+ * @version      1.0
+ * @since        PHP4.04pl1
+ * @access       public
+ */
+class HTML_QuickForm_textarea extends HTML_QuickForm_element
+{
+    // {{{ properties
+
+    /**
+     * Field value
+     * @var       string
+     * @since     1.0
+     * @access    private
+     */
+    var $_value = null;
+
+    // }}}
+    // {{{ constructor
+        
+    /**
+     * Class constructor
+     * 
+     * @param     string    Input field name attribute
+     * @param     mixed     Label(s) for a field
+     * @param     mixed     Either a typical HTML attribute string or an associative array
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function HTML_QuickForm_textarea($elementName=null, $elementLabel=null, $attributes=null)
+    {
+        HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
+        $this->_persistantFreeze = true;
+        $this->_type = 'textarea';
+    } //end constructor
+    
+    // }}}
+    // {{{ setName()
+
+    /**
+     * Sets the input field name
+     * 
+     * @param     string    $name   Input field name attribute
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setName($name)
+    {
+        $this->updateAttributes(array('name'=>$name));
+    } //end func setName
+    
+    // }}}
+    // {{{ getName()
+
+    /**
+     * Returns the element name
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getName()
+    {
+        return $this->getAttribute('name');
+    } //end func getName
+
+    // }}}
+    // {{{ setValue()
+
+    /**
+     * Sets value for textarea element
+     * 
+     * @param     string    $value  Value for textarea element
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setValue($value)
+    {
+        $this->_value = $value;
+    } //end func setValue
+    
+    // }}}
+    // {{{ getValue()
+
+    /**
+     * Returns the value of the form element
+     *
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getValue()
+    {
+        return $this->_value;
+    } // end func getValue
+
+    // }}}
+    // {{{ setWrap()
+
+    /**
+     * Sets wrap type for textarea element
+     * 
+     * @param     string    $wrap  Wrap type
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setWrap($wrap)
+    {
+        $this->updateAttributes(array('wrap' => $wrap));
+    } //end func setWrap
+    
+    // }}}
+    // {{{ setRows()
+
+    /**
+     * Sets height in rows for textarea element
+     * 
+     * @param     string    $rows  Height expressed in rows
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */
+    function setRows($rows)
+    {
+        $this->updateAttributes(array('rows' => $rows));
+    } //end func setRows
+
+    // }}}
+    // {{{ setCols()
+
+    /**
+     * Sets width in cols for textarea element
+     * 
+     * @param     string    $cols  Width expressed in cols
+     * @since     1.0
+     * @access    public
+     * @return    void
+     */ 
+    function setCols($cols)
+    {
+        $this->updateAttributes(array('cols' => $cols));
+    } //end func setCols
+
+    // }}}
+    // {{{ toHtml()
+
+    /**
+     * Returns the textarea element in HTML
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function toHtml()
+    {
+        if ($this->_flagFrozen) {
+            return $this->getFrozenHtml();
+        } else {
+            return $this->_getTabs() .
+                   '<textarea' . $this->_getAttrString($this->_attributes) . '>' .
+                   // because we wrap the form later we don't want the text indented
+                   preg_replace("/(\r\n|\n|\r)/", '&#010;', htmlspecialchars($this->_value)) .
+                   '</textarea>';
+        }
+    } //end func toHtml
+    
+    // }}}
+    // {{{ getFrozenHtml()
+
+    /**
+     * Returns the value of field without HTML tags (in this case, value is changed to a mask)
+     * 
+     * @since     1.0
+     * @access    public
+     * @return    string
+     */
+    function getFrozenHtml()
+    {
+        $value = htmlspecialchars($this->getValue());
+        if ($this->getAttribute('wrap') == 'off') {
+            $html = $this->_getTabs() . '<pre>' . $value."</pre>\n";
+        } else {
+            $html = nl2br($value)."\n";
+        }
+        return $html . $this->_getPersistantData();
+    } //end func getFrozenHtml
+
+    // }}}
+
+} //end class HTML_QuickForm_textarea
+?>
diff --git a/lib/pear/HTML/QuickForm/xbutton.php b/lib/pear/HTML/QuickForm/xbutton.php
new file mode 100644 (file)
index 0000000..dd01995
--- /dev/null
@@ -0,0 +1,145 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Alexey Borzov <avb@php.net>                                 |
+// +----------------------------------------------------------------------+
+//
+// $Id$
+
+require_once 'HTML/QuickForm/element.php';
+
+/**
+ * Class for HTML 4.0 <button> element
+ * 
+ * @author  Alexey Borzov <avb@php.net>
+ * @since   3.2.3
+ * @access  public
+ */
+class HTML_QuickForm_xbutton extends HTML_QuickForm_element
+{
+   /**
+    * Contents of the <button> tag
+    * @var      string
+    * @access   private
+    */
+    var $_content; 
+
+   /**
+    * Class constructor
+    * 
+    * @param    string  Button name
+    * @param    string  Button content (HTML to add between <button></button> tags)
+    * @param    mixed   Either a typical HTML attribute string or an associative array
+    * @access   public
+    */
+    function HTML_QuickForm_xbutton($elementName = null, $elementContent = null, $attributes = null)
+    {
+        $this->HTML_QuickForm_element($elementName, null, $attributes);
+        $this->setContent($elementContent);
+        $this->setPersistantFreeze(false);
+        $this->_type = 'xbutton';
+    }
+
+
+    function toHtml()
+    {
+        return '<button' . $this->getAttributes(true) . '>' . $this->_content . '</button>';
+    }
+
+
+    function getFrozenHtml()
+    {
+        return $this->toHtml();
+    }
+
+
+    function freeze()
+    {
+        return false;
+    }
+
+
+    function setName($name)
+    {
+        $this->updateAttributes(array(
+            'name' => $name 
+        ));
+    }
+
+
+    function getName()
+    {
+        return $this->getAttribute('name');
+    }
+
+
+    function setValue($value)
+    {
+        $this->updateAttributes(array(
+            'value' => $value
+        ));
+    }
+
+
+    function getValue()
+    {
+        return $this->getAttribute('value');
+    }
+
+
+   /**
+    * Sets the contents of the button element
+    *
+    * @param    string  Button content (HTML to add between <button></button> tags)
+    */
+    function setContent($content)
+    {
+        $this->_content = $content;
+    }
+
+
+    function onQuickFormEvent($event, $arg, &$caller)
+    {
+        if ('updateValue' != $event) {
+            return parent::onQuickFormEvent($event, $arg, $caller);
+        } else {
+            $value = $this->_findValue($caller->_constantValues);
+            if (null === $value) {
+                $value = $this->_findValue($caller->_defaultValues);
+            }
+            if (null !== $value) {
+                $this->setValue($value);
+            }
+        }
+        return true;
+    }
+
+
+   /**
+    * Returns a 'safe' element's value
+    * 
+    * The value is only returned if the button's type is "submit" and if this
+    * particlular button was clicked
+    */
+    function exportValue(&$submitValues, $assoc = false)
+    {
+        if ('submit' == $this->getAttribute('type')) {
+            return $this->_prepareValue($this->_findValue($submitValues), $assoc);
+        } else {
+            return null;
+        }
+    }
+}
+?>
index cff6731992fd85e7af8a977ea51a9102f7f83e6b..638888890eb3d4d7761194310ce140b0b4f5299d 100644 (file)
@@ -13,7 +13,7 @@ $THEME->sheets = array('user_styles');
 ////////////////////////////////////////////////////////////////////////////////
 
 
-$THEME->standardsheets = array('styles_layout');
+$THEME->standardsheets = array('styles_layout','styles_form');
 
 /// This variable can be set to an array containing
 /// filenames from the *STANDARD* theme.  If the 
index 5360e9a4a73b1f15a084dc08faab4fc1fc00ee17..2f60222e9f7e4a6624db46a8d4f78c18844bd9e7 100644 (file)
@@ -12,7 +12,7 @@ $THEME->sheets = array('fw_layout','fw_color','fw_fonts');
 /// stylesheet files you want included in this theme, and in what order
 ////////////////////////////////////////////////////////////////////////////////
 
-$THEME->standardsheets = array('styles_layout');
+$THEME->standardsheets = array('styles_layout','styles_form');
 ///$THEME->standardsheets = true;
 
 /// This variable can be set to an array containing
index de75eb0a9ec268752778e5be08a9cd3a35134fab..50c3b70d1d046d7dfc267d95eced52314fde4055 100644 (file)
@@ -13,7 +13,7 @@ $THEME->sheets = array('gradients', 'colors', 'fonts');
 ////////////////////////////////////////////////////////////////////////////////
 
 
-$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color');  
+$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_form');  
 
 /// This variable can be set to an array containing
 /// filenames from the *STANDARD* theme.  If the 
index d133053741ed3c5fd28848d4219931513d9fdaec..486acc64f150761657f6a49cd7c60d4a5e804684 100644 (file)
@@ -13,7 +13,7 @@ $THEME->sheets = array('styles_layout', 'styles_fonts', 'styles_color', 'styles_
 ////////////////////////////////////////////////////////////////////////////////
 
 
-$THEME->standardsheets = array('styles_layout');
+$THEME->standardsheets = array('styles_layout','styles_form');
 
 /// This variable can be set to an array containing
 /// filenames from the *STANDARD* theme.  If the 
index ef3afa19f8c04076719aefb239188b40a5e46591..312d5a1f152b3e407d5182e6f59c1b3b03df4b45 100644 (file)
@@ -13,7 +13,7 @@ $THEME->sheets = array('styles_pda');
 ////////////////////////////////////////////////////////////////////////////////
 
 
-$THEME->standardsheets = array('styles_layout');
+$THEME->standardsheets = array('styles_layout','styles_form');
 
 /// This variable can be set to an array containing
 /// filenames from the *STANDARD* theme.  If the 
index 8628ae95b9fbb2a8f92748a814aa06fe6d42a8ed..473b6aa0120fd18bb08b8795ca10f82208f0ec59 100644 (file)
@@ -6,7 +6,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 
-$THEME->sheets = array('styles_layout', 'styles_fonts', 'styles_color');
+$THEME->sheets = array('styles_layout', 'styles_fonts', 'styles_color','styles_form');
 
 /// This variable is an array containing the names of all the 
 /// stylesheet files you want included in this theme, and in what order
diff --git a/theme/standard/styles_form.css b/theme/standard/styles_form.css
new file mode 100644 (file)
index 0000000..3f71189
--- /dev/null
@@ -0,0 +1,62 @@
+/*******************************************************************
+ styles_form.css
+  
+ This CSS file contains all css required for new css and xhtml only 
+ moodleforms.
+*/
+form.mform {
+    margin: 0;
+    padding: 0;
+    width: 100%;
+}
+form.mform fieldset {
+    border: 1px solid black;
+    padding: 10px 0;
+    margin: 0;
+    width:100%;
+}
+form.mform fieldset.hidden {
+    border: 0;
+}
+form.mform fieldset legend {
+    font-weight: bold;
+}
+form.mform label {
+    margin: 0 0 0 5px;
+}
+form.mform label.qflabel {
+    display: block;
+    float: left;
+    width: 40%;
+    padding: 0;
+    margin: 5px 0 0 0;
+    text-align: right;
+}
+
+form.mform input, form.mform select {
+    width: auto;
+}
+form.mform textarea {
+ }
+form.mform br {
+    clear: left;
+}
+form.mform div.qfelement {
+    display: inline;
+    float: left;
+    margin: 5px 0 0 10px;
+    padding: 0;
+}
+
+form.mform div.qfelementwide {
+    margin: 0 10% 10px 10%;
+}
+
+form.mform span.error, form.mform span.required {
+    color: red;
+}
+form.mform div.error {
+    border: 1px solid red;
+    padding: 5px;
+    color: inherit;
+}
\ No newline at end of file
index 68f9af7b47a624a8630d7d598e9ace9bedaa81e4..842e1707e1c692099c451937cace8d09b539d4d2 100644 (file)
@@ -13,7 +13,7 @@ $THEME->sheets = array('gradients');
 ////////////////////////////////////////////////////////////////////////////////
 
 
-$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_moz');  
+$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_moz','styles_form');  
 
 /// This variable can be set to an array containing
 /// filenames from the *STANDARD* theme.  If the 
index 68f9af7b47a624a8630d7d598e9ace9bedaa81e4..842e1707e1c692099c451937cace8d09b539d4d2 100644 (file)
@@ -13,7 +13,7 @@ $THEME->sheets = array('gradients');
 ////////////////////////////////////////////////////////////////////////////////
 
 
-$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_moz');  
+$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_moz','styles_form');  
 
 /// This variable can be set to an array containing
 /// filenames from the *STANDARD* theme.  If the 
index ba954c3c4bcdf4d5b36efddb2bb06b776a52fd93..54e17b2d8fd6c4d4add840eea0363e7826087c7a 100644 (file)
@@ -13,7 +13,7 @@ $THEME->sheets = array('gradients');
 ////////////////////////////////////////////////////////////////////////////////
 
 
-$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_moz');  
+$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_moz','styles_form');  
 
 /// This variable can be set to an array containing
 /// filenames from the *STANDARD* theme.  If the 
index 68f9af7b47a624a8630d7d598e9ace9bedaa81e4..842e1707e1c692099c451937cace8d09b539d4d2 100644 (file)
@@ -13,7 +13,7 @@ $THEME->sheets = array('gradients');
 ////////////////////////////////////////////////////////////////////////////////
 
 
-$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_moz');  
+$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_moz','styles_form');  
 
 /// This variable can be set to an array containing
 /// filenames from the *STANDARD* theme.  If the 
index 68f9af7b47a624a8630d7d598e9ace9bedaa81e4..842e1707e1c692099c451937cace8d09b539d4d2 100644 (file)
@@ -13,7 +13,7 @@ $THEME->sheets = array('gradients');
 ////////////////////////////////////////////////////////////////////////////////
 
 
-$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_moz');  
+$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_moz','styles_form');  
 
 /// This variable can be set to an array containing
 /// filenames from the *STANDARD* theme.  If the 
index ac4a4fa4272de638eb4ad7f3748d5d32b716491c..7fce9302110fff065d753158d71b85e04370b3f3 100644 (file)
@@ -13,7 +13,7 @@ $THEME->sheets = array('styles_color');
 ////////////////////////////////////////////////////////////////////////////////
 
 
-$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color');  
+$THEME->standardsheets = array('styles_layout','styles_fonts','styles_color','styles_form');  
 
 /// This variable can be set to an array containing
 /// filenames from the *STANDARD* theme.  If the