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