PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.13.5
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.13.5
5.12.0 5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / libs / HTML / QuickForm2 / Element / Select.php
matomo / app / libs / HTML / QuickForm2 / Element Last commit date
Button.php 6 years ago Date.php 5 years ago Input.php 6 years ago InputButton.php 6 years ago InputCheckable.php 5 years ago InputCheckbox.php 6 years ago InputFile.php 4 years ago InputHidden.php 6 years ago InputImage.php 6 years ago InputPassword.php 6 years ago InputRadio.php 6 years ago InputReset.php 6 years ago InputSubmit.php 6 years ago InputText.php 6 years ago Select.php 4 years ago Static.php 6 years ago Textarea.php 6 years ago
Select.php
575 lines
1 <?php
2 /**
3 * Classes for <select> elements
4 *
5 * PHP version 5
6 *
7 * LICENSE:
8 *
9 * Copyright (c) 2006-2010, 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 SVN: $Id: Select.php 300722 2010-06-24 10:15:52Z mansion $
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 * Implements a recursive iterator for options arrays
53 *
54 * @category HTML
55 * @package HTML_QuickForm2
56 * @author Alexey Borzov <avb@php.net>
57 * @author Bertrand Mansion <golgote@mamasam.com>
58 * @version Release: @package_version@
59 */
60 class HTML_QuickForm2_Element_Select_OptionIterator extends RecursiveArrayIterator
61 implements RecursiveIterator
62 {
63 public function hasChildren(): bool
64 {
65 return $this->current() instanceof HTML_QuickForm2_Element_Select_OptionContainer;
66 }
67
68 public function getChildren(): HTML_QuickForm2_Element_Select_OptionIterator
69 {
70 return new HTML_QuickForm2_Element_Select_OptionIterator(
71 $this->current()->getOptions()
72 );
73 }
74 }
75
76 /**
77 * Collection of <option>s and <optgroup>s
78 *
79 * This class handles the output of <option> tags. The class is not intended to
80 * be used directly.
81 *
82 * @category HTML
83 * @package HTML_QuickForm2
84 * @author Alexey Borzov <avb@php.net>
85 * @author Bertrand Mansion <golgote@mamasam.com>
86 * @version Release: @package_version@
87 */
88 class HTML_QuickForm2_Element_Select_OptionContainer extends HTML_Common2
89 implements IteratorAggregate, Countable
90 {
91 /**
92 * List of options and optgroups in this container
93 *
94 * Options are stored as arrays (for performance reasons), optgroups as
95 * instances of Optgroup class.
96 *
97 * @var array
98 */
99 protected $options = array();
100
101 /**
102 * Reference to parent <select>'s values
103 * @var array
104 */
105 protected $values;
106
107 /**
108 * Reference to parent <select>'s possible values
109 * @var array
110 */
111 protected $possibleValues;
112
113
114 /**
115 * Class constructor
116 *
117 * @param array Reference to values of parent <select> element
118 * @param array Reference to possible values of parent <select> element
119 */
120 public function __construct(&$values, &$possibleValues)
121 {
122 $this->values =& $values;
123 $this->possibleValues =& $possibleValues;
124 }
125
126 /**
127 * Adds a new option
128 *
129 * Please note that if you pass 'selected' attribute in the $attributes
130 * parameter then this option's value will be added to <select>'s values.
131 *
132 * @param string Option text
133 * @param string 'value' attribute for <option> tag
134 * @param mixed Additional attributes for <option> tag (either as a
135 * string or as an associative array)
136 */
137 public function addOption($text, $value, $attributes = null)
138 {
139 if (null === $attributes) {
140 $attributes = array('value' => (string)$value);
141 } else {
142 $attributes = self::prepareAttributes($attributes);
143 if (isset($attributes['selected'])) {
144 // the 'selected' attribute will be set in __toString()
145 unset($attributes['selected']);
146 if (!in_array($value, $this->values)) {
147 $this->values[] = $value;
148 }
149 }
150 $attributes['value'] = (string)$value;
151 }
152 if (!isset($attributes['disabled'])) {
153 $this->possibleValues[(string)$value] = true;
154 }
155 $this->options[] = array('text' => $text, 'attr' => $attributes);
156 }
157
158 /**
159 * Adds a new optgroup
160 *
161 * @param string 'label' attribute for optgroup tag
162 * @param mixed Additional attributes for <optgroup> tag (either as a
163 * string or as an associative array)
164 * @return HTML_QuickForm2_Element_Select_Optgroup
165 */
166 public function addOptgroup($label, $attributes = null)
167 {
168 $optgroup = new HTML_QuickForm2_Element_Select_Optgroup(
169 $this->values, $this->possibleValues,
170 $label, $attributes
171 );
172 $this->options[] = $optgroup;
173 return $optgroup;
174 }
175
176 /**
177 * Returns an array of contained options
178 *
179 * @return array
180 */
181 public function getOptions()
182 {
183 return $this->options;
184 }
185
186 public function __toString()
187 {
188 $indentLvl = $this->getIndentLevel();
189 $indent = $this->getIndent() . self::getOption('indent');
190 $linebreak = self::getOption('linebreak');
191 $html = '';
192 $strValues = array_map('strval', $this->values);
193 foreach ($this->options as $option) {
194 if (is_array($option)) {
195 if (in_array($option['attr']['value'], $strValues, true)) {
196 $option['attr']['selected'] = 'selected';
197 }
198 $html .= $indent . '<option' .
199 self::getAttributesString($option['attr']) .
200 '>' . $option['text'] . '</option>' . $linebreak;
201 } elseif ($option instanceof HTML_QuickForm2_Element_Select_OptionContainer) {
202 $option->setIndentLevel($indentLvl + 1);
203 $html .= $option->__toString();
204 }
205 }
206 return $html;
207 }
208
209 /**
210 * Returns an iterator over contained elements
211 *
212 * @return HTML_QuickForm2_Element_Select_OptionIterator
213 */
214 public function getIterator(): HTML_QuickForm2_Element_Select_OptionIterator
215 {
216 return new HTML_QuickForm2_Element_Select_OptionIterator($this->options);
217 }
218
219 /**
220 * Returns a recursive iterator over contained elements
221 *
222 * @return RecursiveIteratorIterator
223 */
224 public function getRecursiveIterator(): RecursiveIteratorIterator
225 {
226 return new RecursiveIteratorIterator(
227 new HTML_QuickForm2_Element_Select_OptionIterator($this->options),
228 RecursiveIteratorIterator::SELF_FIRST
229 );
230 }
231
232 /**
233 * Returns the number of options in the container
234 *
235 * @return int
236 */
237 public function count(): int
238 {
239 return count($this->options);
240 }
241 }
242
243
244 /**
245 * Class representing an <optgroup> tag
246 *
247 * Do not instantiate this class yourself, use
248 * {@link HTML_QuickForm2_Element_Select::addOptgroup()} method
249 *
250 * @category HTML
251 * @package HTML_QuickForm2
252 * @author Alexey Borzov <avb@php.net>
253 * @author Bertrand Mansion <golgote@mamasam.com>
254 * @version Release: @package_version@
255 */
256 class HTML_QuickForm2_Element_Select_Optgroup
257 extends HTML_QuickForm2_Element_Select_OptionContainer
258 {
259 /**
260 * Class constructor
261 *
262 * @param array Reference to values of parent <select> element
263 * @param array Reference to possible values of parent <select> element
264 * @param string 'label' attribute for optgroup tag
265 * @param mixed Additional attributes for <optgroup> tag (either as a
266 * string or as an associative array)
267 */
268 public function __construct(&$values, &$possibleValues, $label, $attributes = null)
269 {
270 parent::__construct($values, $possibleValues);
271 $this->setAttributes($attributes);
272 $this->attributes['label'] = (string)$label;
273 }
274
275 public function __toString()
276 {
277 $indent = $this->getIndent();
278 $linebreak = self::getOption('linebreak');
279 return $indent . '<optgroup' . $this->getAttributes(true) . '>' .
280 $linebreak . parent::__toString() . $indent . '</optgroup>' . $linebreak;
281 }
282 }
283
284
285 /**
286 * Class representing a <select> element
287 *
288 * @category HTML
289 * @package HTML_QuickForm2
290 * @author Alexey Borzov <avb@php.net>
291 * @author Bertrand Mansion <golgote@mamasam.com>
292 * @version Release: @package_version@
293 */
294 class HTML_QuickForm2_Element_Select extends HTML_QuickForm2_Element
295 {
296 protected $persistent = true;
297
298 /**
299 * Values for the select element (i.e. values of the selected options)
300 * @var array
301 */
302 protected $values = array();
303
304 /**
305 * Possible values for select elements
306 *
307 * A value is considered possible if it is present as a value attribute of
308 * some option and that option is not disabled.
309 * @var array
310 */
311 protected $possibleValues = array();
312
313
314 /**
315 * Object containing options for the <select> element
316 * @var HTML_QuickForm2_Element_Select_OptionContainer
317 */
318 protected $optionContainer;
319
320 /**
321 * Enable intrinsic validation by default
322 * @var array
323 */
324 protected $data = array('intrinsic_validation' => true);
325
326 /**
327 * Class constructor
328 *
329 * Select element can understand the following keys in $data parameter:
330 * - 'options': data to populate element's options with. Passed to
331 * {@link loadOptions()} method.
332 * - 'intrinsic_validation': setting this to false will disable
333 * that validation, {@link getValue()} will then return all submit
334 * values, not just those corresponding to options present in the
335 * element. May be useful in AJAX scenarios.
336 *
337 * @param string Element name
338 * @param mixed Attributes (either a string or an array)
339 * @param array Additional element data
340 * @throws HTML_QuickForm2_InvalidArgumentException if junk is given in $options
341 */
342 public function __construct($name = null, $attributes = null, array $data = array())
343 {
344 $options = isset($data['options'])? $data['options']: array();
345 unset($data['options']);
346 parent::__construct($name, $attributes, $data);
347 $this->loadOptions($options);
348 }
349
350 public function getType()
351 {
352 return 'select';
353 }
354
355 public function __toString()
356 {
357 if ($this->frozen) {
358 return $this->getFrozenHtml();
359 } else {
360 if (empty($this->attributes['multiple'])) {
361 $attrString = $this->getAttributes(true);
362 } else {
363 $this->attributes['name'] .= '[]';
364 $attrString = $this->getAttributes(true);
365 $this->attributes['name'] = substr($this->attributes['name'], 0, -2);
366 }
367 $indent = $this->getIndent();
368 return $indent . '<select' . $attrString . '>' .
369 self::getOption('linebreak') .
370 $this->optionContainer->__toString() .
371 $indent . '</select>';
372 }
373 }
374
375 protected function getFrozenHtml()
376 {
377 if (null === ($value = $this->getValue())) {
378 return '&nbsp;';
379 }
380 $valueHash = is_array($value)? array_flip($value): array($value => true);
381 $options = array();
382 foreach ($this->optionContainer->getRecursiveIterator() as $child) {
383 if (is_array($child) && isset($valueHash[$child['attr']['value']]) &&
384 empty($child['attr']['disabled']))
385 {
386 $options[] = $child['text'];
387 }
388 }
389
390 $html = implode('<br />', $options);
391 if ($this->persistent) {
392 $name = $this->attributes['name'] .
393 (empty($this->attributes['multiple'])? '': '[]');
394 // Only use id attribute if doing single hidden input
395 $idAttr = (1 == count($valueHash))? array('id' => $this->getId()): array();
396 foreach ($valueHash as $key => $item) {
397 $html .= '<input type="hidden"' . self::getAttributesString(array(
398 'name' => $name,
399 'value' => $key
400 ) + $idAttr) . ' />';
401 }
402 }
403 return $html;
404 }
405
406 /**
407 * Returns the value of the <select> element
408 *
409 * Please note that the returned value may not necessarily be equal to that
410 * passed to {@link setValue()}. It passes "intrinsic validation" confirming
411 * that such value could possibly be submitted by this <select> element.
412 * Specifically, this method will return null if the elements "disabled"
413 * attribute is set, it will not return values if there are no options having
414 * such a "value" attribute or if such options' "disabled" attribute is set.
415 * It will also only return a scalar value for single selects, mimicking
416 * the common browsers' behaviour.
417 *
418 * @return mixed "value" attribute of selected option in case of single
419 * select, array of selected options' "value" attributes in
420 * case of multiple selects, null if no options selected
421 */
422 public function getValue()
423 {
424 if (!empty($this->attributes['disabled']) || 0 == count($this->values)
425 || ($this->data['intrinsic_validation']
426 && (0 == count($this->optionContainer) || 0 == count($this->possibleValues)))
427 ) {
428 return null;
429 }
430
431 $values = array();
432 foreach ($this->values as $value) {
433 if (!$this->data['intrinsic_validation'] || !empty($this->possibleValues[$value])) {
434 $values[] = $value;
435 }
436 }
437 if (0 == count($values)) {
438 return null;
439 } elseif (!empty($this->attributes['multiple'])) {
440 return $this->applyFilters($values);
441 } elseif (1 == count($values)) {
442 return $this->applyFilters($values[0]);
443 } else {
444 // The <select> is not multiple, but several options are to be
445 // selected. At least IE and Mozilla select the last selected
446 // option in this case, we should do the same
447 foreach ($this->optionContainer->getRecursiveIterator() as $child) {
448 if (is_array($child) && in_array($child['attr']['value'], $values)) {
449 $lastValue = $child['attr']['value'];
450 }
451 }
452 return $this->applyFilters($lastValue);
453 }
454 }
455
456 public function setValue($value)
457 {
458 if (is_array($value)) {
459 $this->values = array_values($value);
460 } else {
461 $this->values = array($value);
462 }
463 return $this;
464 }
465
466 /**
467 * Loads <option>s (and <optgroup>s) for select element
468 *
469 * The method expects a array of options and optgroups:
470 * <pre>
471 * array(
472 * 'option value 1' => 'option text 1',
473 * ...
474 * 'option value N' => 'option text N',
475 * 'optgroup label 1' => array(
476 * 'option value' => 'option text',
477 * ...
478 * ),
479 * ...
480 * )
481 * </pre>
482 * If value is a scalar, then array key is treated as "value" attribute of
483 * <option> and value as this <option>'s text. If value is an array, then
484 * key is treated as a "label" attribute of <optgroup> and value as an
485 * array of <option>s for this <optgroup>.
486 *
487 * If you need to specify additional attributes for <option> and <optgroup>
488 * tags, then you need to use {@link addOption()} and {@link addOptgroup()}
489 * methods instead of this one.
490 *
491 * @param array
492 * @throws HTML_QuickForm2_InvalidArgumentException if junk is given in $options
493 * @return HTML_QuickForm2_Element_Select
494 */
495 public function loadOptions(array $options)
496 {
497 $this->possibleValues = array();
498 $this->optionContainer = new HTML_QuickForm2_Element_Select_OptionContainer(
499 $this->values, $this->possibleValues
500 );
501 $this->loadOptionsFromArray($this->optionContainer, $options);
502 return $this;
503 }
504
505
506 /**
507 * Adds options from given array into given container
508 *
509 * @param HTML_QuickForm2_Element_Select_OptionContainer options will be
510 * added to this container
511 * @param array options array
512 */
513 protected function loadOptionsFromArray(
514 HTML_QuickForm2_Element_Select_OptionContainer $container, $options
515 )
516 {
517 foreach ($options as $key => $value) {
518 if (is_array($value)) {
519 $optgroup = $container->addOptgroup($key);
520 $this->loadOptionsFromArray($optgroup, $value);
521 } else {
522 $container->addOption($value, $key);
523 }
524 }
525 }
526
527
528 /**
529 * Adds a new option
530 *
531 * Please note that if you pass 'selected' attribute in the $attributes
532 * parameter then this option's value will be added to <select>'s values.
533 *
534 * @param string Option text
535 * @param string 'value' attribute for <option> tag
536 * @param mixed Additional attributes for <option> tag (either as a
537 * string or as an associative array)
538 */
539 public function addOption($text, $value, $attributes = null)
540 {
541 return $this->optionContainer->addOption($text, $value, $attributes);
542 }
543
544 /**
545 * Adds a new optgroup
546 *
547 * @param string 'label' attribute for optgroup tag
548 * @param mixed Additional attributes for <optgroup> tag (either as a
549 * string or as an associative array)
550 * @return HTML_QuickForm2_Element_Select_Optgroup
551 */
552 public function addOptgroup($label, $attributes = null)
553 {
554 return $this->optionContainer->addOptgroup($label, $attributes);
555 }
556
557 public function updateValue()
558 {
559 if (!$this->getAttribute('multiple')) {
560 parent::updateValue();
561 } else {
562 $name = $this->getName();
563 foreach ($this->getDataSources() as $ds) {
564 if (null !== ($value = $ds->getValue($name)) ||
565 $ds instanceof HTML_QuickForm2_DataSource_Submit)
566 {
567 $this->setValue(null === $value? array(): $value);
568 return;
569 }
570 }
571 }
572 }
573 }
574 ?>
575