1: <?php
  2: 
  3:   4:   5:   6: 
  7: 
  8: namespace Nette\Forms\Controls;
  9: 
 10: use Nette;
 11: 
 12: 
 13:  14:  15:  16:  17:  18: 
 19: abstract class MultiChoiceControl extends BaseControl
 20: {
 21:     
 22:     public $checkAllowedValues = TRUE;
 23: 
 24:     
 25:     private $items = array();
 26: 
 27: 
 28:     public function __construct($label = NULL, array $items = NULL)
 29:     {
 30:         parent::__construct($label);
 31:         if ($items !== NULL) {
 32:             $this->setItems($items);
 33:         }
 34:     }
 35: 
 36: 
 37:      38:  39:  40: 
 41:     public function loadHttpData()
 42:     {
 43:         $this->value = array_keys(array_flip($this->getHttpData(Nette\Forms\Form::DATA_TEXT)));
 44:         if (is_array($this->disabled)) {
 45:             $this->value = array_diff($this->value, array_keys($this->disabled));
 46:         }
 47:     }
 48: 
 49: 
 50:      51:  52:  53:  54:  55: 
 56:     public function setValue($values)
 57:     {
 58:         if (is_scalar($values) || $values === NULL) {
 59:             $values = (array) $values;
 60:         } elseif (!is_array($values)) {
 61:             throw new Nette\InvalidArgumentException(sprintf("Value must be array or NULL, %s given in field '%s'.", gettype($values), $this->name));
 62:         }
 63:         $flip = array();
 64:         foreach ($values as $value) {
 65:             if (!is_scalar($value) && !method_exists($value, '__toString')) {
 66:                 throw new Nette\InvalidArgumentException(sprintf("Values must be scalar, %s given in field '%s'.", gettype($value), $this->name));
 67:             }
 68:             $flip[(string) $value] = TRUE;
 69:         }
 70:         $values = array_keys($flip);
 71:         if ($this->checkAllowedValues && ($diff = array_diff($values, array_keys($this->items)))) {
 72:             $set = Nette\Utils\Strings::truncate(implode(', ', array_map(function ($s) { return var_export($s, TRUE); }, array_keys($this->items))), 70, '...');
 73:             $vals = (count($diff) > 1 ? 's' : '') . " '" . implode("', '", $diff) . "'";
 74:             throw new Nette\InvalidArgumentException("Value$vals are out of allowed set [$set] in field '{$this->name}'.");
 75:         }
 76:         $this->value = $values;
 77:         return $this;
 78:     }
 79: 
 80: 
 81:      82:  83:  84: 
 85:     public function getValue()
 86:     {
 87:         return array_values(array_intersect($this->value, array_keys($this->items)));
 88:     }
 89: 
 90: 
 91:      92:  93:  94: 
 95:     public function getRawValue()
 96:     {
 97:         return $this->value;
 98:     }
 99: 
100: 
101:     102: 103: 104: 
105:     public function isFilled()
106:     {
107:         return $this->getValue() !== array();
108:     }
109: 
110: 
111:     112: 113: 114: 115: 116: 
117:     public function setItems(array $items, $useKeys = TRUE)
118:     {
119:         $this->items = $useKeys ? $items : array_combine($items, $items);
120:         return $this;
121:     }
122: 
123: 
124:     125: 126: 127: 
128:     public function getItems()
129:     {
130:         return $this->items;
131:     }
132: 
133: 
134:     135: 136: 137: 
138:     public function getSelectedItems()
139:     {
140:         return array_intersect_key($this->items, array_flip($this->value));
141:     }
142: 
143: 
144:     145: 146: 147: 148: 
149:     public function setDisabled($value = TRUE)
150:     {
151:         if (!is_array($value)) {
152:             return parent::setDisabled($value);
153:         }
154: 
155:         parent::setDisabled(FALSE);
156:         $this->disabled = array_fill_keys($value, TRUE);
157:         $this->value = array_diff($this->value, $value);
158:         return $this;
159:     }
160: 
161: 
162:     163: 164: 165: 
166:     public function getHtmlName()
167:     {
168:         return parent::getHtmlName() . '[]';
169:     }
170: 
171: }
172: