getAttributes()->registerAttributeCallback( 'options', null, [$this, 'setOptions'] ); // ZF1 compatibility: $this->getAttributes()->registerAttributeCallback( 'multiOptions', null, [$this, 'setOptions'] ); parent::__construct($name, $attributes); } public function hasOption($value) { return isset($this->options[$value]); } public function validate() { $value = $this->getValue(); if ( $value !== null && ( ! ($option = $this->getOption($value)) || $option->getAttributes()->has('disabled') ) ) { $this->valid = false; $this->addMessage("'$value' is not allowed here"); } elseif ($this->isRequired() && $value === null) { $this->valid = false; } else { parent::validate(); } return $this; } public function deselect() { $this->setValue(null); return $this; } public function disableOption($value) { if ($option = $this->getOption($value)) { $option->getAttributes()->add('disabled', true); } if ($this->getValue() == $value) { $this->valid = false; $this->addMessage("'$value' is not allowed here"); } return $this; } public function disableOptions($values) { foreach ($values as $value) { $this->disableOption($value); } return $this; } /** * @param $value * @return SelectOption|null */ public function getOption($value) { if ($this->hasOption($value)) { return $this->options[$value]; } else { return null; } } /** * @param array $options * @return $this */ public function setOptions(array $options) { $this->options = []; foreach ($options as $value => $label) { $this->optionContent[$value] = $this->makeOption($value, $label); } return $this; } protected function makeOption($value, $label) { if (is_array($label)) { $grp = Html::tag('optgroup', ['label' => $value]); foreach ($label as $option => $val) { $grp->addHtml($this->makeOption($option, $val)); } return $grp; } else { $option = new SelectOption($value, $label); $option->getAttributes()->registerAttributeCallback('selected', function () use ($option) { $optionValue = $option->getValue(); return is_int($optionValue) // The loose comparison is required because PHP casts // numeric strings to integers if used as array keys ? $this->getValue() == $optionValue : $this->getValue() === $optionValue; }); $this->options[$value] = $option; return $this->options[$value]; } } protected function assemble() { $this->addHtml(...array_values($this->optionContent)); } }