<?php
/**
* Classes for <select> elements
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2006-2014, Alexey Borzov <avb@php.net>,
* Bertrand Mansion <golgote@mamasam.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category HTML
* @package HTML_QuickForm2
* @author Alexey Borzov <avb@php.net>
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/HTML_QuickForm2
*/
/**
* Base class for simple HTML_QuickForm2 elements
*/
require_once 'HTML/QuickForm2/Element.php';
/**
* Collection of <option>s and <optgroup>s
*
* This class handles the output of <option> tags. The class is not intended to
* be used directly.
*
* @category HTML
* @package HTML_QuickForm2
* @author Alexey Borzov <avb@php.net>
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 2.0.2
* @link http://pear.php.net/package/HTML_QuickForm2
*/
class HTML_QuickForm2_Element_Select_OptionContainer extends HTML_Common2
implements IteratorAggregate, Countable
{
/**
* List of options and optgroups in this container
*
* Options are stored as arrays (for performance reasons), optgroups as
* instances of Optgroup class.
*
* @var array
*/
protected $options = array();
/**
* Reference to parent <select>'s values
* @var array
*/
protected $values;
/**
* Reference to parent <select>'s possible values
* @var array
*/
protected $possibleValues;
/**
* Class constructor
*
* @param array &$values Reference to values of parent <select> element
* @param array &$possibleValues Reference to possible values of parent <select> element
*/
public function __construct(&$values, &$possibleValues)
{
$this->values =& $values;
$this->possibleValues =& $possibleValues;
}
/**
* Adds a new option
*
* Please note that if you pass 'selected' attribute in the $attributes
* parameter then this option's value will be added to <select>'s values.
*
* @param string $text Option text
* @param string $value 'value' attribute for <option> tag
* @param string|array $attributes Additional attributes for <option> tag
* (either as a string or as an associative array)
*/
public function addOption($text, $value, $attributes = null)
{
if (null === $attributes) {
$attributes = array('value' => (string)$value);
} else {
$attributes = self::prepareAttributes($attributes);
if (isset($attributes['selected'])) {
// the 'selected' attribute will be set in __toString()
unset($attributes['selected']);
if (!in_array($value, $this->values)) {
$this->values[] = $value;
}
}
$attributes['value'] = (string)$value;
}
if (!isset($attributes['disabled'])) {
$this->possibleValues[(string)$value] = true;
}
$this->options[] = array('text' => $text, 'attr' => $attributes);
}
/**
* Adds a new optgroup
*
* @param string $label 'label' attribute for optgroup tag
* @param string|array $attributes Additional attributes for <optgroup> tag
* (either as a string or as an associative array)
*
* @return HTML_QuickForm2_Element_Select_Optgroup
*/
public function addOptgroup($label, $attributes = null)
{
$optgroup = new HTML_QuickForm2_Element_Select_Optgroup(
$this->values, $this->possibleValues, $label, $attributes
);
$this->options[] = $optgroup;
return $optgroup;
}
/**
* Returns an array of contained options
*
* @return array
*/
public function getOptions()
{
return $this->options;
}
public function __toString()
{
$indentLvl = $this->getIndentLevel();
$indent = $this->getIndent() . self::getOption('indent');
$linebreak = self::getOption('linebreak');
$html = '';
$strValues = array_map('strval', $this->values);
foreach ($this->options as $option) {
if (is_array($option)) {
if (in_array($option['attr']['value'], $strValues, true)) {
$option['attr']['selected'] = 'selected';
}
$html .= $indent . '<option' .
self::getAttributesString($option['attr']) .
'>' . $option['text'] . '</option>' . $linebreak;
} elseif ($option instanceof HTML_QuickForm2_Element_Select_OptionContainer) {
$option->setIndentLevel($indentLvl + 1);
$html .= $option->__toString();
}
}
return $html;
}
/**
* Returns an iterator over contained elements
*
* @return HTML_QuickForm2_Element_Select_OptionIterator
*/
public function getIterator()
{
return new HTML_QuickForm2_Element_Select_OptionIterator($this->options);
}
/**
* Returns a recursive iterator over contained elements
*
* @return RecursiveIteratorIterator
*/
public function getRecursiveIterator()
{
return new RecursiveIteratorIterator(
new HTML_QuickForm2_Element_Select_OptionIterator($this->options),
RecursiveIteratorIterator::SELF_FIRST
);
}
/**
* Returns the number of options in the container
*
* @return int
*/
public function count()
{
return count($this->options);
}
}
/**
* Class representing an <optgroup> tag
*
* Do not instantiate this class yourself, use
* {@link HTML_QuickForm2_Element_Select::addOptgroup()} method
*
* @category HTML
* @package HTML_QuickForm2
* @author Alexey Borzov <avb@php.net>
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 2.0.2
* @link http://pear.php.net/package/HTML_QuickForm2
*/
class HTML_QuickForm2_Element_Select_Optgroup
extends HTML_QuickForm2_Element_Select_OptionContainer
{
/**
* Class constructor
*
* @param array &$values Reference to values of parent <select> element
* @param array &$possibleValues Reference to possible values of parent <select> element
* @param string $label 'label' attribute for optgroup tag
* @param string|array $attributes Additional attributes for <optgroup> tag
* (either as a string or as an associative array)
*/
public function __construct(&$values, &$possibleValues, $label, $attributes = null)
{
parent::__construct($values, $possibleValues);
$this->setAttributes($attributes);
$this->attributes['label'] = (string)$label;
}
public function __toString()
{
$indent = $this->getIndent();
$linebreak = self::getOption('linebreak');
return $indent . '<optgroup' . $this->getAttributes(true) . '>' .
$linebreak . parent::__toString() . $indent . '</optgroup>' . $linebreak;
}
}
/**
* Implements a recursive iterator for options arrays
*
* @category HTML
* @package HTML_QuickForm2
* @author Alexey Borzov <avb@php.net>
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 2.0.2
* @link http://pear.php.net/package/HTML_QuickForm2
*/
class HTML_QuickForm2_Element_Select_OptionIterator extends RecursiveArrayIterator
implements RecursiveIterator
{
public function hasChildren()
{
return $this->current() instanceof HTML_QuickForm2_Element_Select_OptionContainer;
}
public function getChildren()
{
return new HTML_QuickForm2_Element_Select_OptionIterator(
$this->current()->getOptions()
);
}
}
/**
* Class representing a <select> element
*
* @category HTML
* @package HTML_QuickForm2
* @author Alexey Borzov <avb@php.net>
* @author Bertrand Mansion <golgote@mamasam.com>
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 2.0.2
* @link http://pear.php.net/package/HTML_QuickForm2
*/
class HTML_QuickForm2_Element_Select extends HTML_QuickForm2_Element
{
protected $persistent = true;
/**
* Values for the select element (i.e. values of the selected options)
* @var array
*/
protected $values = array();
/**
* Possible values for select elements
*
* A value is considered possible if it is present as a value attribute of
* some option and that option is not disabled.
* @var array
*/
protected $possibleValues = array();
/**
* Object containing options for the <select> element
* @var HTML_QuickForm2_Element_Select_OptionContainer
*/
protected $optionContainer;
/**
* Enable intrinsic validation by default
* @var array
*/
protected $data = array('intrinsic_validation' => true);
/**
* Class constructor
*
* Select element can understand the following keys in $data parameter:
* - 'options': data to populate element's options with. Passed to
* {@link loadOptions()} method.
* - 'intrinsic_validation': setting this to false will disable
* that validation, {@link getValue()} will then return all submit
* values, not just those corresponding to options present in the
* element. May be useful in AJAX scenarios.
*
* @param string $name Element name
* @param string|array $attributes Attributes (either a string or an array)
* @param array $data Additional element data
*
* @throws HTML_QuickForm2_InvalidArgumentException if junk is given in $options
*/
public function __construct($name = null, $attributes = null, array $data = array())
{
$options = isset($data['options'])? $data['options']: array();
unset($data['options']);
parent::__construct($name, $attributes, $data);
$this->loadOptions($options);
}
public function getType()
{
return 'select';
}
public function __toString()
{
if ($this->frozen) {
return $this->getFrozenHtml();
} else {
if (empty($this->attributes['multiple'])) {
$attrString = $this->getAttributes(true);
} else {
$this->attributes['name'] .= '[]';
$attrString = $this->getAttributes(true);
$this->attributes['name'] = substr($this->attributes['name'], 0, -2);
}
$indent = $this->getIndent();
return $indent . '<select' . $attrString . '>' .
self::getOption('linebreak') .
$this->optionContainer->__toString() .
$indent . '</select>';
}
}
protected function getFrozenHtml()
{
if (null === ($value = $this->getValue())) {
return ' ';
}
$valueHash = is_array($value)? array_flip($value): array($value => true);
$options = array();
foreach ($this->optionContainer->getRecursiveIterator() as $child) {
if (is_array($child) && isset($valueHash[$child['attr']['value']])
&& empty($child['attr']['disabled'])
) {
$options[] = $child['text'];
}
}
$html = implode('<br />', $options);
if ($this->persistent) {
$name = $this->attributes['name'] .
(empty($this->attributes['multiple'])? '': '[]');
// Only use id attribute if doing single hidden input
$idAttr = (1 == count($valueHash))? array('id' => $this->getId()): array();
foreach ($valueHash as $key => $item) {
$html .= '<input type="hidden"' . self::getAttributesString(array(
'name' => $name,
'value' => $key
) + $idAttr) . ' />';
}
}
return $html;
}
/**
* Returns the value of the <select> element
*
* Please note that the returned value may not necessarily be equal to that
* passed to {@link setValue()}. It passes "intrinsic validation" confirming
* that such value could possibly be submitted by this <select> element.
* Specifically, this method will return null if the elements "disabled"
* attribute is set, it will not return values if there are no options having
* such a "value" attribute or if such options' "disabled" attribute is set.
* It will also only return a scalar value for single selects, mimicking
* the common browsers' behaviour.
*
* @return mixed "value" attribute of selected option in case of single
* select, array of selected options' "value" attributes in
* case of multiple selects, null if no options selected
*/
public function getRawValue()
{
if (!empty($this->attributes['disabled']) || 0 == count($this->values)
|| ($this->data['intrinsic_validation']
&& (0 == count($this->optionContainer) || 0 == count($this->possibleValues)))
) {
return null;
}
$values = array();
foreach ($this->values as $value) {
if (!$this->data['intrinsic_validation'] || !empty($this->possibleValues[$value])) {
$values[] = $value;
}
}
if (0 == count($values)) {
return null;
} elseif (!empty($this->attributes['multiple'])) {
return $values;
} elseif (1 == count($values)) {
return $values[0];
} else {
// The <select> is not multiple, but several options are to be
// selected. At least IE and Mozilla select the last selected
// option in this case, we should do the same
$lastValue = null;
foreach ($this->optionContainer->getRecursiveIterator() as $child) {
if (is_array($child) && in_array($child['attr']['value'], $values)) {
$lastValue = $child['attr']['value'];
}
}
return $lastValue;
}
}
public function setValue($value)
{
if (is_array($value)) {
$this->values = array_values($value);
} else {
$this->values = array($value);
}
return $this;
}
/**
* Loads <option>s (and <optgroup>s) for select element
*
* The method expects a array of options and optgroups:
* <pre>
* array(
* 'option value 1' => 'option text 1',
* ...
* 'option value N' => 'option text N',
* 'optgroup label 1' => array(
* 'option value' => 'option text',
* ...
* ),
* ...
* )
* </pre>
* If value is a scalar, then array key is treated as "value" attribute of
* <option> and value as this <option>'s text. If value is an array, then
* key is treated as a "label" attribute of <optgroup> and value as an
* array of <option>s for this <optgroup>.
*
* If you need to specify additional attributes for <option> and <optgroup>
* tags, then you need to use {@link addOption()} and {@link addOptgroup()}
* methods instead of this one.
*
* @param array $options
*
* @throws HTML_QuickForm2_InvalidArgumentException if junk is given in $options
* @return $this
*/
public function loadOptions(array $options)
{
$this->possibleValues = array();
$this->optionContainer = new HTML_QuickForm2_Element_Select_OptionContainer(
$this->values, $this->possibleValues
);
$this->loadOptionsFromArray($this->optionContainer, $options);
return $this;
}
/**
* Adds options from given array into given container
*
* @param HTML_QuickForm2_Element_Select_OptionContainer $container options will be
* added to this container
* @param array $options options array
*/
protected function loadOptionsFromArray(
HTML_QuickForm2_Element_Select_OptionContainer $container, $options
) {
foreach ($options as $key => $value) {
if (is_array($value)) {
$optgroup = $container->addOptgroup($key);
$this->loadOptionsFromArray($optgroup, $value);
} else {
$container->addOption($value, $key);
}
}
}
/**
* Adds a new option
*
* Please note that if you pass 'selected' attribute in the $attributes
* parameter then this option's value will be added to <select>'s values.
*
* @param string $text Option text
* @param string $value 'value' attribute for <option> tag
* @param string|array $attributes Additional attributes for <option> tag
* (either as a string or as an associative array)
*/
public function addOption($text, $value, $attributes = null)
{
$this->optionContainer->addOption($text, $value, $attributes);
}
/**
* Adds a new optgroup
*
* @param string $label 'label' attribute for optgroup tag
* @param string|array $attributes Additional attributes for <optgroup> tag
* (either as a string or as an associative array)
*
* @return HTML_QuickForm2_Element_Select_Optgroup
*/
public function addOptgroup($label, $attributes = null)
{
return $this->optionContainer->addOptgroup($label, $attributes);
}
protected function updateValue()
{
if (!$this->getAttribute('multiple')) {
parent::updateValue();
} else {
$name = $this->getName();
/* @var $ds HTML_QuickForm2_DataSource_NullAware */
foreach ($this->getDataSources() as $ds) {
if (null !== ($value = $ds->getValue($name))
|| $ds instanceof HTML_QuickForm2_DataSource_Submit
|| ($ds instanceof HTML_QuickForm2_DataSource_NullAware && $ds->hasValue($name))
) {
$this->setValue((array)$value);
return;
}
}
}
}
/**
* Get the select's option container, e.g. for rendering purposes.
*
* @return HTML_QuickForm2_Element_Select_OptionContainer
*/
public function getOptionContainer()
{
return $this->optionContainer;
}
}
?>
Copyright 2K16 - 2K18 Indonesian Hacker Rulez