3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Form\Element
;
13 use Zend\Form\Element
;
14 use Zend\Form\ElementInterface
;
15 use Zend\Form\Exception\InvalidArgumentException
;
16 use Zend\InputFilter\InputProviderInterface
;
17 use Zend\Validator\Explode
as ExplodeValidator
;
18 use Zend\Validator\InArray
as InArrayValidator
;
20 class Select
extends Element
implements InputProviderInterface
27 protected $attributes = [
32 * @var \Zend\Validator\ValidatorInterface
39 protected $disableInArrayValidator = false;
42 * Create an empty option (option with label but no value). If set to null, no option is created
46 protected $emptyOption = null;
51 protected $valueOptions = [];
56 protected $useHiddenElement = false;
61 protected $unselectedValue = '';
66 public function getValueOptions()
68 return $this->valueOptions
;
72 * @param array $options
75 public function setValueOptions(array $options)
77 $this->valueOptions
= $options;
79 // Update InArrayValidator validator haystack
80 if (null !== $this->validator
) {
81 if ($this->validator
instanceof InArrayValidator
) {
82 $validator = $this->validator
;
84 if ($this->validator
instanceof ExplodeValidator
85 && $this->validator
->getValidator() instanceof InArrayValidator
87 $validator = $this->validator
->getValidator();
89 if (! empty($validator)) {
90 $validator->setHaystack($this->getValueOptionsValues());
101 public function unsetValueOption($key)
103 if (isset($this->valueOptions
[$key])) {
104 unset($this->valueOptions
[$key]);
111 * Set options for an element. Accepted options are:
112 * - label: label to associate with the element
113 * - label_attributes: attributes to use when the label is rendered
114 * - value_options: list of values and labels for the select options
115 * - empty_option: should an empty option be prepended to the options ?
117 * @param array|Traversable $options
118 * @return Select|ElementInterface
119 * @throws InvalidArgumentException
121 public function setOptions($options)
123 parent
::setOptions($options);
125 if (isset($this->options
['value_options'])) {
126 $this->setValueOptions($this->options
['value_options']);
128 // Alias for 'value_options'
129 if (isset($this->options
['options'])) {
130 $this->setValueOptions($this->options
['options']);
133 if (isset($this->options
['empty_option'])) {
134 $this->setEmptyOption($this->options
['empty_option']);
137 if (isset($this->options
['disable_inarray_validator'])) {
138 $this->setDisableInArrayValidator($this->options
['disable_inarray_validator']);
141 if (isset($options['use_hidden_element'])) {
142 $this->setUseHiddenElement($options['use_hidden_element']);
145 if (isset($options['unselected_value'])) {
146 $this->setUnselectedValue($options['unselected_value']);
153 * Set a single element attribute
156 * @param mixed $value
157 * @return Select|ElementInterface
159 public function setAttribute($key, $value)
161 // Do not include the options in the list of attributes
162 // TODO: Deprecate this
163 if ($key === 'options') {
164 $this->setValueOptions($value);
167 return parent
::setAttribute($key, $value);
171 * Set the flag to allow for disabling the automatic addition of an InArray validator.
173 * @param bool $disableOption
176 public function setDisableInArrayValidator($disableOption)
178 $this->disableInArrayValidator
= (bool) $disableOption;
183 * Get the disable in array validator flag.
187 public function disableInArrayValidator()
189 return $this->disableInArrayValidator
;
193 * Set the string for an empty option (can be empty string). If set to null, no option will be added
195 * @param string|null $emptyOption
198 public function setEmptyOption($emptyOption)
200 $this->emptyOption
= $emptyOption;
205 * Return the string for the empty option (null if none)
207 * @return string|null
209 public function getEmptyOption()
211 return $this->emptyOption
;
217 * @return \Zend\Validator\ValidatorInterface
219 protected function getValidator()
221 if (null === $this->validator
&& ! $this->disableInArrayValidator()) {
222 $validator = new InArrayValidator([
223 'haystack' => $this->getValueOptionsValues(),
227 if ($this->isMultiple()) {
228 $validator = new ExplodeValidator([
229 'validator' => $validator,
230 'valueDelimiter' => null, // skip explode if only one value
234 $this->validator
= $validator;
236 return $this->validator
;
240 * Do we render hidden element?
242 * @param bool $useHiddenElement
245 public function setUseHiddenElement($useHiddenElement)
247 $this->useHiddenElement
= (bool) $useHiddenElement;
252 * Do we render hidden element?
256 public function useHiddenElement()
258 return $this->useHiddenElement
;
262 * Set the value if the select is not selected
264 * @param string $unselectedValue
267 public function setUnselectedValue($unselectedValue)
269 $this->unselectedValue
= (string) $unselectedValue;
274 * Get the value when the select is not selected
278 public function getUnselectedValue()
280 return $this->unselectedValue
;
284 * Provide default input rules for this element
288 public function getInputSpecification()
291 'name' => $this->getName(),
295 if ($this->useHiddenElement() && $this->isMultiple()) {
296 $unselectedValue = $this->getUnselectedValue();
298 $spec['allow_empty'] = true;
299 $spec['continue_if_empty'] = true;
300 $spec['filters'] = [[
301 'name' => 'Callback',
303 'callback' => function ($value) use ($unselectedValue) {
304 if ($value === $unselectedValue) {
313 if ($validator = $this->getValidator()) {
314 $spec['validators'] = [
323 * Get only the values from the options attribute
327 protected function getValueOptionsValues()
330 $options = $this->getValueOptions();
331 foreach ($options as $key => $optionSpec) {
332 if (is_array($optionSpec) && array_key_exists('options', $optionSpec)) {
333 foreach ($optionSpec['options'] as $nestedKey => $nestedOptionSpec) {
334 $values[] = $this->getOptionValue($nestedKey, $nestedOptionSpec);
339 $values[] = $this->getOptionValue($key, $optionSpec);
344 protected function getOptionValue($key, $optionSpec)
346 return is_array($optionSpec) ?
$optionSpec['value'] : $key;
350 * Element has the multiple attribute
354 public function isMultiple()
356 return isset($this->attributes
['multiple'])
357 && ($this->attributes
['multiple'] === true ||
$this->attributes
['multiple'] === 'multiple');