1<?php
2/**
3 * Collection of <option>s and <optgroup>s
4 *
5 * PHP version 5
6 *
7 * LICENSE
8 *
9 * This source file is subject to BSD 3-Clause License that is bundled
10 * with this package in the file LICENSE and available at the URL
11 * https://raw.githubusercontent.com/pear/HTML_QuickForm2/trunk/docs/LICENSE
12 *
13 * @category  HTML
14 * @package   HTML_QuickForm2
15 * @author    Alexey Borzov <avb@php.net>
16 * @author    Bertrand Mansion <golgote@mamasam.com>
17 * @copyright 2006-2021 Alexey Borzov <avb@php.net>, Bertrand Mansion <golgote@mamasam.com>
18 * @license   https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
19 * @link      https://pear.php.net/package/HTML_QuickForm2
20 */
21
22/**
23 * Implements a recursive iterator for options arrays
24 */
25require_once 'HTML/QuickForm2/Element/Select/OptionIterator.php';
26
27/**
28 * Collection of <option>s and <optgroup>s
29 *
30 * This class handles the output of <option> tags. The class is not intended to
31 * be used directly.
32 *
33 * @category HTML
34 * @package  HTML_QuickForm2
35 * @author   Alexey Borzov <avb@php.net>
36 * @author   Bertrand Mansion <golgote@mamasam.com>
37 * @license  https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
38 * @version  Release: 2.2.2
39 * @link     https://pear.php.net/package/HTML_QuickForm2
40 * @internal
41 */
42class HTML_QuickForm2_Element_Select_OptionContainer extends HTML_Common2
43    implements IteratorAggregate, Countable
44{
45   /**
46    * List of options and optgroups in this container
47    *
48    * Options are stored as arrays (for performance reasons), optgroups as
49    * instances of Optgroup class.
50    *
51    * @var array
52    */
53    protected $options = [];
54
55   /**
56    * Reference to parent <select>'s values
57    * @var array
58    */
59    protected $values;
60
61   /**
62    * Reference to parent <select>'s possible values
63    * @var array
64    */
65    protected $possibleValues;
66
67
68   /**
69    * Class constructor
70    *
71    * @param array &$values         Reference to values of parent <select> element
72    * @param array &$possibleValues Reference to possible values of parent <select> element
73    */
74    public function __construct(&$values, &$possibleValues)
75    {
76        $this->values         =& $values;
77        $this->possibleValues =& $possibleValues;
78    }
79
80   /**
81    * Adds a new option
82    *
83    * Please note that if you pass 'selected' attribute in the $attributes
84    * parameter then this option's value will be added to <select>'s values.
85    *
86    * @param string       $text       Option text
87    * @param string       $value      'value' attribute for <option> tag
88    * @param string|array $attributes Additional attributes for <option> tag
89    *                     (either as a string or as an associative array)
90    */
91    public function addOption($text, $value, $attributes = null)
92    {
93        if (null === $attributes) {
94            $attributes = ['value' => (string)$value];
95        } else {
96            $attributes = self::prepareAttributes($attributes);
97            if (isset($attributes['selected'])) {
98                // the 'selected' attribute will be set in __toString()
99                unset($attributes['selected']);
100                if (!in_array($value, $this->values)) {
101                    $this->values[] = $value;
102                }
103            }
104            $attributes['value'] = (string)$value;
105        }
106        if (!isset($attributes['disabled'])) {
107            $this->possibleValues[(string)$value] = true;
108        }
109        $this->options[] = ['text' => $text, 'attr' => $attributes];
110    }
111
112   /**
113    * Adds a new optgroup
114    *
115    * @param string       $label      'label' attribute for optgroup tag
116    * @param string|array $attributes Additional attributes for <optgroup> tag
117    *                     (either as a string or as an associative array)
118    *
119    * @return   HTML_QuickForm2_Element_Select_Optgroup
120    */
121    public function addOptgroup($label, $attributes = null)
122    {
123        $optgroup = new HTML_QuickForm2_Element_Select_Optgroup(
124            $this->values, $this->possibleValues, $label, $attributes
125        );
126        $this->options[] = $optgroup;
127        return $optgroup;
128    }
129
130   /**
131    * Returns an array of contained options
132    *
133    * @return   array
134    */
135    public function getOptions()
136    {
137        return $this->options;
138    }
139
140    public function __toString()
141    {
142        $indentLvl = $this->getIndentLevel();
143        $indent    = $this->getIndent() . self::getOption(self::OPTION_INDENT);
144        $linebreak = self::getOption(self::OPTION_LINEBREAK);
145        $html      = '';
146        $strValues = array_map('strval', $this->values);
147        foreach ($this->options as $option) {
148            if (is_array($option)) {
149                if (in_array($option['attr']['value'], $strValues, true)) {
150                    $option['attr']['selected'] = 'selected';
151                }
152                $html .= $indent . '<option' .
153                         self::getAttributesString($option['attr']) .
154                         '>' . $option['text'] . '</option>' . $linebreak;
155            } elseif ($option instanceof HTML_QuickForm2_Element_Select_OptionContainer) {
156                $option->setIndentLevel($indentLvl + 1);
157                $html .= $option->__toString();
158            }
159        }
160        return $html;
161    }
162
163   /**
164    * Returns an iterator over contained elements
165    *
166    * @return   HTML_QuickForm2_Element_Select_OptionIterator
167    */
168    public function getIterator()
169    {
170        return new HTML_QuickForm2_Element_Select_OptionIterator($this->options);
171    }
172
173   /**
174    * Returns a recursive iterator over contained elements
175    *
176    * @return   RecursiveIteratorIterator
177    */
178    public function getRecursiveIterator()
179    {
180        return new RecursiveIteratorIterator(
181            new HTML_QuickForm2_Element_Select_OptionIterator($this->options),
182            RecursiveIteratorIterator::SELF_FIRST
183        );
184    }
185
186   /**
187    * Returns the number of options in the container
188    *
189    * @return   int
190    */
191    public function count()
192    {
193        return count($this->options);
194    }
195}
196?>