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

Source for file Select.php

Documentation is available at Select.php

  1. <?php
  2. /**
  3.  * Classes for <select> elements
  4.  *
  5.  * PHP version 5
  6.  *
  7.  * LICENSE:
  8.  * 
  9.  * Copyright (c) 2006, 2007, Alexey Borzov <avb@php.net>,
  10.  *                           Bertrand Mansion <golgote@mamasam.com>
  11.  * All rights reserved.
  12.  *
  13.  * Redistribution and use in source and binary forms, with or without
  14.  * modification, are permitted provided that the following conditions
  15.  * are met:
  16.  *
  17.  *    * Redistributions of source code must retain the above copyright
  18.  *      notice, this list of conditions and the following disclaimer.
  19.  *    * Redistributions in binary form must reproduce the above copyright
  20.  *      notice, this list of conditions and the following disclaimer in the
  21.  *      documentation and/or other materials provided with the distribution.
  22.  *    * The names of the authors may not be used to endorse or promote products
  23.  *      derived from this software without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  26.  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  27.  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  28.  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  29.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  30.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  31.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  32.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  33.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  34.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  35.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36.  *
  37.  * @category   HTML
  38.  * @package    HTML_QuickForm2
  39.  * @author     Alexey Borzov <avb@php.net>
  40.  * @author     Bertrand Mansion <golgote@mamasam.com>
  41.  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
  42.  * @version    CVS: $Id: Select.php,v 1.11 2007/06/30 20:36:00 avb Exp $
  43.  * @link       http://pear.php.net/package/HTML_QuickForm2
  44.  */
  45.  
  46. /**
  47.  * Base class for simple HTML_QuickForm2 elements
  48.  */
  49. require_once 'HTML/QuickForm2/Element.php';
  50.  
  51.  
  52. /**
  53.  * Collection of <option>s and <optgroup>s
  54.  *
  55.  * This class handles the output of <option> tags. The class is not intended to
  56.  * be used directly.
  57.  * 
  58.  * @category   HTML
  59.  * @package    HTML_QuickForm2
  60.  * @author     Alexey Borzov <avb@php.net>
  61.  * @author     Bertrand Mansion <golgote@mamasam.com>
  62.  * @version    Release: 0.2.0
  63.  */
  64.     implements IteratorAggregateCountable
  65. {
  66.    /**
  67.     * List of options and optgroups in this container
  68.     *
  69.     * Options are stored as arrays (for performance reasons), optgroups as
  70.     * instances of Optgroup class.
  71.     *
  72.     * @var array 
  73.     */
  74.     protected $options = array();
  75.  
  76.    /**
  77.     * Reference to parent <select>'s values
  78.     * @var array 
  79.     */
  80.     protected $values;
  81.  
  82.    /**
  83.     * Reference to parent <select>'s possible values
  84.     * @var array 
  85.     */
  86.     protected $possibleValues;
  87.  
  88.  
  89.    /**
  90.     * Class constructor
  91.     *
  92.     * @param    array   Reference to values of parent <select> element
  93.     * @param    array   Reference to possible values of parent <select> element
  94.     */
  95.     public function __construct(&$values&$possibleValues)
  96.     {
  97.         $this->values         =$values;
  98.         $this->possibleValues =$possibleValues;
  99.     }
  100.  
  101.    /**
  102.     * Adds a new option
  103.     *
  104.     * Please note that if you pass 'selected' attribute in the $attributes
  105.     * parameter then this option's value will be added to <select>'s values.
  106.     *
  107.     * @param    string  Option text
  108.     * @param    string  'value' attribute for <option> tag
  109.     * @param    mixed   Additional attributes for <option> tag (either as a
  110.     *                    string or as an associative array)
  111.     */
  112.     public function addOption($text$value$attributes = null)
  113.     {
  114.         if (null === $attributes{
  115.             $attributes = array('value' => (string)$value);
  116.         else {
  117.             $attributes = self::prepareAttributes($attributes);
  118.             if (isset($attributes['selected'])) {
  119.                 // the 'selected' attribute will be set in __toString()
  120.                 unset($attributes['selected']);
  121.                 if (!in_array($value$this->values)) {
  122.                     $this->values[$value;
  123.                 }
  124.             }
  125.             $attributes['value'= (string)$value;
  126.         }
  127.         if (!isset($attributes['disabled'])) {
  128.             $this->possibleValues[(string)$value= true;
  129.         }
  130.         $this->options[= array('text' => $text'attr' => $attributes);
  131.     }
  132.  
  133.    /**
  134.     * Adds a new optgroup
  135.     *
  136.     * @param    string  'label' attribute for optgroup tag
  137.     * @param    mixed   Additional attributes for <optgroup> tag (either as a
  138.     *                    string or as an associative array)
  139.     * @return   HTML_QuickForm2_Element_Select_Optgroup 
  140.     */
  141.     public function addOptgroup($label$attributes = null)
  142.     {
  143.         $optgroup = new HTML_QuickForm2_Element_Select_Optgroup(
  144.                             $this->values$this->possibleValues
  145.                             $label$attributes
  146.                         );
  147.         $this->options[$optgroup;
  148.         return $optgroup;
  149.     }
  150.  
  151.    /**
  152.     * Returns an array of contained options
  153.     *
  154.     * @return   array 
  155.     */
  156.     public function getOptions()
  157.     {
  158.         return $this->options;
  159.     }
  160.  
  161.     public function __toString()
  162.     {
  163.         $indentLvl $this->getIndentLevel();
  164.         $indent    $this->getIndent(. self::getOption('indent');
  165.         $linebreak = self::getOption('linebreak');
  166.         $html      '';
  167.         $strValues array_map('strval'$this->values);
  168.         foreach ($this->options as $option{
  169.             if (is_array($option)) {
  170.                 if (in_array($option['attr']['value']$strValuestrue)) {
  171.                     $option['attr']['selected''selected';
  172.                 }
  173.                 $html .= $indent '<option' 
  174.                          self::getAttributesString($option['attr'].
  175.                          '>' $option['text''</option>' $linebreak;
  176.             elseif ($option instanceof HTML_QuickForm2_Element_Select_OptionContainer{
  177.                 $option->setIndentLevel($indentLvl + 1);
  178.                 $html .= $option->__toString();
  179.             }
  180.         }
  181.         return $html;
  182.     }
  183.  
  184.    /**
  185.     * Returns an iterator over contained elements
  186.     *
  187.     * @return   HTML_QuickForm2_Element_Select_OptionIterator 
  188.     */
  189.     public function getIterator()
  190.     {
  191.         return new HTML_QuickForm2_Element_Select_OptionIterator($this->options);
  192.     }
  193.  
  194.    /**
  195.     * Returns a recursive iterator over contained elements
  196.     *
  197.     * @return   RecursiveIteratorIterator 
  198.     */
  199.     public function getRecursiveIterator()
  200.     {
  201.         return new RecursiveIteratorIterator(
  202.             new HTML_QuickForm2_Element_Select_OptionIterator($this->options),
  203.             RecursiveIteratorIterator::SELF_FIRST
  204.         );
  205.     }
  206.  
  207.    /**
  208.     * Returns the number of options in the container
  209.     *
  210.     * @return   int 
  211.     */
  212.     public function count()
  213.     {
  214.         return count($this->options);
  215.     }
  216. }
  217.  
  218.  
  219. /**
  220.  * Class representing an <optgroup> tag
  221.  *
  222.  * Do not instantiate this class yourself, use
  223.  * {@link HTML_QuickForm2_Element_Select::addOptgroup()} method
  224.  *
  225.  * @category   HTML
  226.  * @package    HTML_QuickForm2
  227.  * @author     Alexey Borzov <avb@php.net>
  228.  * @author     Bertrand Mansion <golgote@mamasam.com>
  229.  * @version    Release: 0.2.0
  230.  */
  231. {
  232.    /**
  233.     * Class constructor
  234.     *
  235.     * @param    array   Reference to values of parent <select> element
  236.     * @param    array   Reference to possible values of parent <select> element
  237.     * @param    string  'label' attribute for optgroup tag
  238.     * @param    mixed   Additional attributes for <optgroup> tag (either as a
  239.     *                    string or as an associative array)
  240.     */
  241.     public function __construct(&$values&$possibleValues$label$attributes = null)
  242.     {
  243.         parent::__construct($values$possibleValues);
  244.         $this->setAttributes($attributes);
  245.         $this->attributes['label'= (string)$label;
  246.     }
  247.  
  248.     public function __toString()
  249.     {
  250.         $indent    $this->getIndent();
  251.         $linebreak = self::getOption('linebreak');
  252.         return $indent '<optgroup' $this->getAttributes(true'>' .
  253.                $linebreak . parent::__toString($indent '</optgroup>' $linebreak;
  254.     }
  255. }
  256.  
  257. /**
  258.  * Implements a recursive iterator for options arrays
  259.  *
  260.  * @category   HTML
  261.  * @package    HTML_QuickForm2
  262.  * @author     Alexey Borzov <avb@php.net>
  263.  * @author     Bertrand Mansion <golgote@mamasam.com>
  264.  * @version    Release: 0.2.0
  265.  */
  266. class HTML_QuickForm2_Element_Select_OptionIterator extends RecursiveArrayIterator 
  267.     implements RecursiveIterator
  268. {
  269.     public function hasChildren()
  270.     {
  271.         return $this->current(instanceof HTML_QuickForm2_Element_Select_OptionContainer;
  272.     }
  273.     
  274.     public function getChildren()
  275.     {
  276.         return new HTML_QuickForm2_Element_Select_OptionIterator(
  277.             $this->current()->getOptions()
  278.         );
  279.     }
  280. }
  281.  
  282.  
  283. /**
  284.  * Class representing a <select> element
  285.  *
  286.  * @category   HTML
  287.  * @package    HTML_QuickForm2
  288.  * @author     Alexey Borzov <avb@php.net>
  289.  * @author     Bertrand Mansion <golgote@mamasam.com>
  290.  * @version    Release: 0.2.0
  291.  */
  292. {
  293.     protected $persistent = true;
  294.  
  295.    /**
  296.     * Values for the select element (i.e. values of the selected options)
  297.     * @var  array 
  298.     */
  299.     protected $values = array();
  300.  
  301.    /**
  302.     * Possible values for select elements
  303.     *
  304.     * A value is considered possible if it is present as a value attribute of
  305.     * some option and that option is not disabled.
  306.     * @var array 
  307.     */
  308.     protected $possibleValues = array();
  309.  
  310.  
  311.    /**
  312.     * Object containing options for the <select> element
  313.     * @var  HTML_QuickForm2_Element_Select_OptionContainer 
  314.     */
  315.     protected $optionContainer;
  316.  
  317.    /**
  318.     * Class constructor
  319.     *
  320.     * @param    string  Element name
  321.     * @param    mixed   Attributes (either a string or an array)
  322.     * @param    array   Data used to populate the element's options, passed to
  323.     *                    {@link loadOptions()} method. Format:
  324.     *                    <code>
  325.     *                    $data = array('options' => array('option1', 'option2'));
  326.     *                    </code>
  327.     * @throws   HTML_QuickForm2_InvalidArgumentException    if junk is given in $options
  328.     */
  329.     public function __construct($name = null$attributes = nullarray $data = array())
  330.     {
  331.         $options = isset($data['options'])$data['options']: array();
  332.         unset($data['options']);
  333.         parent::__construct($name$attributes$data);
  334.         $this->loadOptions($options);
  335.     }
  336.  
  337.     public function getType()
  338.     {
  339.         return 'select';
  340.     }
  341.  
  342.     public function __toString()
  343.     {
  344.         if ($this->frozen{
  345.             return $this->getFrozenHtml();
  346.         else {
  347.             if (empty($this->attributes['multiple'])) {
  348.                 $attrString $this->getAttributes(true);
  349.             else {
  350.                 $this->attributes['name'.= '[]';
  351.                 $attrString $this->getAttributes(true);
  352.                 $this->attributes['name']  substr($this->attributes['name']0-2);
  353.             }
  354.             $indent $this->getIndent();
  355.             return $indent '<select' $attrString '>' .
  356.                    self::getOption('linebreak'.
  357.                    $this->optionContainer->__toString(.
  358.                    $indent '</select>';
  359.         }
  360.     }
  361.  
  362.     protected function getFrozenHtml()
  363.     {
  364.         if (null === ($value $this->getValue())) {
  365.             return '&nbsp;';
  366.         }
  367.         $valueHash is_array($value)array_flip($value): array($value => true);
  368.         $options   = array();
  369.         foreach ($this->optionContainer->getRecursiveIterator(as $child{
  370.             if (is_array($child&& isset($valueHash[$child['attr']['value']]&&
  371.                 empty($child['attr']['disabled'])) 
  372.             {
  373.                 $options[$child['text'];
  374.             }
  375.         }
  376.  
  377.         $html implode('<br />'$options);
  378.         if ($this->persistent{
  379.             $name $this->attributes['name'
  380.                     (empty($this->attributes['multiple'])'''[]');
  381.             // Only use id attribute if doing single hidden input
  382.             $idAttr (1 == count($valueHash))? array('id' => $this->getId()): array()
  383.             foreach ($valueHash as $key => $item{
  384.                 $html .= '<input type="hidden"' . self::getAttributesString(array(
  385.                              'name'  => $name,
  386.                              'value' => $key
  387.                          $idAttr' />';
  388.             }
  389.         }
  390.         return $html;
  391.     }
  392.  
  393.    /**
  394.     * Returns the value of the <select> element
  395.     *
  396.     * Please note that the returned value may not necessarily be equal to that
  397.     * passed to {@link setValue()}. It passes "intrinsic validation" confirming
  398.     * that such value could possibly be submitted by this <select> element.
  399.     * Specifically, this method will return null if the elements "disabled"
  400.     * attribute is set, it will not return values if there are no options having
  401.     * such a "value" attribute or if such options' "disabled" attribute is set.
  402.     * It will also only return a scalar value for single selects, mimicking
  403.     * the common browsers' behaviour.
  404.     *
  405.     * @return   mixed   "value" attribute of selected option in case of single
  406.     *                    select, array of selected options' "value" attributes in
  407.     *                    case of multiple selects, null if no options selected
  408.     */
  409.     public function getValue()
  410.     {
  411.         if (0 == count($this->optionContainer|| 0 == count($this->values||
  412.             0 == count($this->possibleValues|| !empty($this->attributes['disabled']))
  413.         {
  414.             return null;
  415.         }
  416.  
  417.         $values = array();
  418.         foreach ($this->values as $value{
  419.             if (!empty($this->possibleValues[$value])) {
  420.                 $values[$value;
  421.             }
  422.         }
  423.         if (0 == count($values)) {
  424.             return null;
  425.         elseif (!empty($this->attributes['multiple'])) {
  426.             return $values;
  427.         elseif (1 == count($values)) {
  428.             return $values[0];
  429.         else {
  430.             // The <select> is not multiple, but several options are to be 
  431.             // selected. At least IE and Mozilla select the last selected 
  432.             // option in this case, we should do the same
  433.             foreach ($this->optionContainer->getRecursiveIterator(as $child{
  434.                 if (is_array($child&& in_array($child['attr']['value']$values)) {
  435.                     $lastValue $child['attr']['value'];
  436.                 }
  437.             }
  438.             return $lastValue;
  439.         }
  440.     }
  441.  
  442.     public function setValue($value)
  443.     {
  444.         if (is_array($value)) {
  445.             $this->values = array_values($value);
  446.         else {
  447.             $this->values = array($value);
  448.         }
  449.         return $this;
  450.     }
  451.  
  452.    /**
  453.     * Loads <option>s (and <optgroup>s) for select element
  454.     *
  455.     * The method expects a array of options and optgroups:
  456.     * <pre>
  457.     * array(
  458.     *     'option value 1' => 'option text 1',
  459.     *     ...
  460.     *     'option value N' => 'option text N',
  461.     *     'optgroup label 1' => array(
  462.     *         'option value' => 'option text',
  463.     *         ...
  464.     *     ),
  465.     *     ...
  466.     * )
  467.     * </pre>
  468.     * If value is a scalar, then array key is treated as "value" attribute of
  469.     * <option> and value as this <option>'s text. If value is an array, then
  470.     * key is treated as a "label" attribute of <optgroup> and value as an
  471.     * array of <option>s for this <optgroup>.
  472.     * 
  473.     * If you need to specify additional attributes for <option> and <optgroup>
  474.     * tags, then you need to use {@link addOption()} and {@link addOptgroup()}
  475.     * methods instead of this one.
  476.     * 
  477.     * @param    array 
  478.     * @throws   HTML_QuickForm2_InvalidArgumentException    if junk is given in $options
  479.     * @return   HTML_QuickForm2_Element_Select 
  480.     */
  481.     public function loadOptions(array $options)
  482.     {
  483.         $this->possibleValues  = array();
  484.         $this->optionContainer = new HTML_QuickForm2_Element_Select_OptionContainer(
  485.                                      $this->values$this->possibleValues
  486.                                  );
  487.         $this->loadOptionsFromArray($this->optionContainer$options);
  488.         return $this;
  489.     }
  490.  
  491.  
  492.    /**
  493.     * Adds options from given array into given container
  494.     *
  495.     * @param    HTML_QuickForm2_Element_Select_OptionContainer  options will be
  496.     *            added to this container
  497.     * @param    array   options array
  498.     */
  499.     protected function loadOptionsFromArray(
  500.         HTML_QuickForm2_Element_Select_OptionContainer $container$options
  501.     )
  502.     {
  503.         foreach ($options as $key => $value{
  504.             if (is_array($value)) {
  505.                 $optgroup $container->addOptgroup($key);
  506.                 $this->loadOptionsFromArray($optgroup$value);
  507.             else {
  508.                 $container->addOption($value$key);
  509.             }
  510.         }
  511.     }
  512.  
  513.  
  514.    /**
  515.     * Adds a new option
  516.     *
  517.     * Please note that if you pass 'selected' attribute in the $attributes
  518.     * parameter then this option's value will be added to <select>'s values.
  519.     *
  520.     * @param    string  Option text
  521.     * @param    string  'value' attribute for <option> tag
  522.     * @param    mixed   Additional attributes for <option> tag (either as a
  523.     *                    string or as an associative array)
  524.     */
  525.     public function addOption($text$value$attributes = null)
  526.     {
  527.         return $this->optionContainer->addOption($text$value$attributes);
  528.     }
  529.  
  530.    /**
  531.     * Adds a new optgroup
  532.     *
  533.     * @param    string  'label' attribute for optgroup tag
  534.     * @param    mixed   Additional attributes for <optgroup> tag (either as a
  535.     *                    string or as an associative array)
  536.     * @return   HTML_QuickForm2_Element_Select_Optgroup 
  537.     */
  538.     public function addOptgroup($label$attributes = null)
  539.     {
  540.         return $this->optionContainer->addOptgroup($label$attributes);
  541.     }
  542.  
  543.     protected function updateValue()
  544.     {
  545.         if (!$this->getAttribute('multiple')) {
  546.             parent::updateValue();
  547.         else {
  548.             $name $this->getName();
  549.             foreach ($this->getDataSources(as $ds{
  550.                 if (null !== ($value $ds->getValue($name)) ||
  551.                     $ds instanceof HTML_QuickForm2_DataSource_Submit)
  552.                 {
  553.                     $this->setValue(null === $value? array()$value);
  554.                     return;
  555.                 }
  556.             }
  557.         }
  558.     }
  559. }
  560. ?>

Documentation generated on Mon, 22 Oct 2007 12:30:24 -0400 by phpDocumentor 1.4.0. PEAR Logo Copyright © PHP Group 2004.