1: <?php
2:
3: /**
4: * This file is part of the Nette Framework (http://nette.org)
5: *
6: * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
7: *
8: * For the full copyright and license information, please view
9: * the file license.txt that was distributed with this source code.
10: * @package Nette\Forms\Controls
11: */
12:
13:
14:
15: /**
16: * Select box control that allows single item selection.
17: *
18: * @author David Grudl
19: *
20: * @property-read mixed $rawValue
21: * @property bool $prompt
22: * @property array $items
23: * @property-read string $selectedItem
24: * @package Nette\Forms\Controls
25: */
26: class SelectBox extends FormControl
27: {
28: /** @var array */
29: private $items = array();
30:
31: /** @var array */
32: protected $allowed = array();
33:
34: /** @var mixed */
35: private $prompt = FALSE;
36:
37: /** @var bool */
38: private $useKeys = TRUE;
39:
40:
41: /**
42: * @param string label
43: * @param array items from which to choose
44: * @param int number of rows that should be visible
45: */
46: public function __construct($label = NULL, array $items = NULL, $size = NULL)
47: {
48: parent::__construct($label);
49: $this->control->setName('select');
50: $this->control->size = $size > 1 ? (int) $size : NULL;
51: if ($items !== NULL) {
52: $this->setItems($items);
53: }
54: }
55:
56:
57: /**
58: * Returns selected item key.
59: * @return mixed
60: */
61: public function getValue()
62: {
63: return is_scalar($this->value) && isset($this->allowed[$this->value]) ? $this->value : NULL;
64: }
65:
66:
67: /**
68: * Returns selected item key (not checked).
69: * @return mixed
70: */
71: public function getRawValue()
72: {
73: return is_scalar($this->value) ? $this->value : NULL;
74: }
75:
76:
77: /**
78: * Has been any item selected?
79: * @return bool
80: */
81: public function isFilled()
82: {
83: $value = $this->getValue();
84: return is_array($value) ? count($value) > 0 : $value !== NULL;
85: }
86:
87:
88: /**
89: * Sets first prompt item in select box.
90: * @param string
91: * @return self
92: */
93: public function setPrompt($prompt)
94: {
95: if ($prompt === TRUE) { // back compatibility
96: $prompt = reset($this->items);
97: unset($this->allowed[key($this->items)], $this->items[key($this->items)]);
98: }
99: $this->prompt = $prompt;
100: return $this;
101: }
102:
103:
104: /** @deprecated */
105: function skipFirst($v = NULL)
106: {
107: trigger_error(__METHOD__ . '() is deprecated; use setPrompt() instead.', E_USER_WARNING);
108: return $this->setPrompt($v);
109: }
110:
111:
112: /**
113: * Returns first prompt item?
114: * @return mixed
115: */
116: final public function getPrompt()
117: {
118: return $this->prompt;
119: }
120:
121:
122: /**
123: * Are the keys used?
124: * @return bool
125: */
126: final public function areKeysUsed()
127: {
128: return $this->useKeys;
129: }
130:
131:
132: /**
133: * Sets items from which to choose.
134: * @param array
135: * @param bool
136: * @return self
137: */
138: public function setItems(array $items, $useKeys = TRUE)
139: {
140: $allowed = array();
141: foreach ($items as $k => $v) {
142: foreach ((is_array($v) ? $v : array($k => $v)) as $key => $value) {
143: if (!$useKeys) {
144: if (!is_scalar($value)) {
145: throw new InvalidArgumentException("All items must be scalar.");
146: }
147: $key = $value;
148: }
149:
150: if (isset($allowed[$key])) {
151: throw new InvalidArgumentException("Items contain duplication for key '$key'.");
152: }
153:
154: $allowed[$key] = $value;
155: }
156: }
157:
158: $this->items = $items;
159: $this->allowed = $allowed;
160: $this->useKeys = (bool) $useKeys;
161: return $this;
162: }
163:
164:
165: /**
166: * Returns items from which to choose.
167: * @return array
168: */
169: final public function getItems()
170: {
171: return $this->items;
172: }
173:
174:
175: /**
176: * Returns selected value.
177: * @return string
178: */
179: public function getSelectedItem()
180: {
181: $value = $this->getValue();
182: return ($this->useKeys && $value !== NULL) ? $this->allowed[$value] : $value;
183: }
184:
185:
186: /**
187: * Generates control's HTML element.
188: * @return Html
189: */
190: public function getControl()
191: {
192: $selected = $this->getValue();
193: $selected = is_array($selected) ? array_flip($selected) : array($selected => TRUE);
194: $control = parent::getControl();
195: $option = Html::el('option');
196:
197: if ($this->prompt !== FALSE) {
198: $control->add($this->prompt instanceof Html
199: ? $this->prompt->value('')
200: : (string) $option->value('')->setText($this->translate((string) $this->prompt))
201: );
202: }
203:
204: foreach ($this->items as $key => $value) {
205: if (!is_array($value)) {
206: $value = array($key => $value);
207: $dest = $control;
208: } else {
209: $dest = $control->create('optgroup')->label($this->translate($key));
210: }
211:
212: foreach ($value as $key2 => $value2) {
213: if ($value2 instanceof Html) {
214: $dest->add((string) $value2->value($key2)
215: ->selected(isset($selected[$key2])));
216:
217: } else {
218: $key2 = $this->useKeys ? $key2 : $value2;
219: $dest->add((string) $option->value($key2)
220: ->selected(isset($selected[$key2]))
221: ->setText($this->translate((string) $value2)));
222: }
223: }
224: }
225: return $control;
226: }
227:
228: }
229: