*/ abstract class AbstractChoiceField extends AbstractVisibleField { /** * Список опций * @var AbstractChoiceOption[] */ private $options = []; /** * Список выбранных опций * @var AbstractChoiceOption[] */ private $selectedOptions = []; private $multiselect = false; /** * Возвращает, можно ли делать множественный выбор * @return boolean */ public function isMultiSelect() { return $this->multiselect; } /** * Переключает поле в режим множественного выбора * @return $this */ public function setMultiSelect() { $this->multiselect = true; return $this; } /** * Переключает поле в режим единственного выбора * @return $this */ public function setSingleSelect() { $this->multiselect = false; if (count($this->selectedOptions) > 0) { $this->selectedOptions = [$this->selectedOptions[0]]; } return $this; } /** * Возвращает значение выделенной опции * @return mixed */ public function value() { if (empty($this->selectedOptions)) { return null; } if (!$this->multiselect) { return $this->selectedOptions[0]->value(); } $values = []; foreach ($this->selectedOptions as $option) { $values[] = $option->value(); } return $values; } /** * Задаёт новое значение для select поля * @param mixed $newValue * @return $this */ public function setValue($newValue) { if (is_array($newValue)) { $values = self::getUniqueValues($newValue); } else { $values = [$newValue]; } $this->selectedOptions = []; foreach ($values as $value) { foreach ($this->options as $option) { if ($option->value() == $value && !in_array($option, $this->selectedOptions)) { $this->selectedOptions[] = $option; continue 2; } } } return $this; } private static function getUniqueValues(array $values) { $unquie = []; foreach ($values as $value) { if (!in_array($value, $unquie)) { $unquie[] = $value; } } return $unquie; } /** * Метод возвращает список всех опций * @return AbstractChoiceOption[] */ public function options() { return $this->options; } /** * Метод возвращает список выбранных опций * @return AbstractChoiceOption[] */ public function selection() { return $this->selectedOptions; } /** * Устанавливает новый набор опций для поля * @param array $options * @return $this */ public function setOptions(array $options) { $this->options = []; $this->selectedOptions = []; foreach ($options as $key => $data) { $this->registerOption($key, $data); } return $this; } private function registerOption($key, $data) { if (is_string($data) || is_numeric($data)) { $this->addOption($key, $data); return; } if (!is_array($data)) { return; } $value = array_key_exists('value', $data) ? $data['value'] : $key; $text = array_key_exists('text', $data) ? $data['text'] : ''; $option = $this->addOption($value, $text); if ((array_key_exists('disabled', $data) && !empty($data['disabled'])) || (array_key_exists('disable', $data) && !empty($data['disable']))) { $option->disable(); } if ((array_key_exists('selected', $data) && !empty($data['selected'])) || (array_key_exists('select', $data) && !empty($data['select']))) { $this->select($option); } } /** * Метод добавляет опцию со значением $value и текстом $text * @param string|int|float $value * @param string $text * @param array $parameters * @return AbstractChoiceOption */ public function addOption($value, $text) { $option = $this->createOption($value, $text); $this->options[] = $option; return $option; } /** * Проверяет, выбрана ли данная опция * @param AbstractChoiceOption $option * @return boolean */ public function isSelected(AbstractChoiceOption $option) { return in_array($option, $this->selectedOptions); } /** * * @param AbstractChoiceOption $option * @return boolean */ public function select(AbstractChoiceOption $option) { if (!in_array($option, $this->options)) { return false; } if (!$this->multiselect) { $this->selectedOptions = [$option]; return true; } if (!in_array($option, $this->selectedOptions)) { $this->selectedOptions[] = $option; } return true; } public function getAssociativeAttributes() { $attributes = parent::getAssociativeAttributes(); $this->appendVisibleAttributes($attributes); $this->appendSizeAttribute($attributes); return $attributes; } /** * Создаёт новый экземпляр опции * @return AbstractChoiceOption */ protected abstract function createOption($value, $text); public abstract function appendAttributesToOption(AbstractChoiceOption $option, array & $attributes); }