scratch – Blame information for rev 87

Subversion Repositories:
Rev:
Rev Author Line No. Line
87 office 1 <?php
2  
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11  
12 namespace Symfony\Component\DomCrawler\Field;
13  
14 /**
15 * ChoiceFormField represents a choice form field.
16 *
17 * It is constructed from a HTML select tag, or a HTML checkbox, or radio inputs.
18 *
19 * @author Fabien Potencier <fabien@symfony.com>
20 */
21 class ChoiceFormField extends FormField
22 {
23 /**
24 * @var string
25 */
26 private $type;
27 /**
28 * @var bool
29 */
30 private $multiple;
31 /**
32 * @var array
33 */
34 private $options;
35 /**
36 * @var bool
37 */
38 private $validationDisabled = false;
39  
40 /**
41 * Returns true if the field should be included in the submitted values.
42 *
43 * @return bool true if the field should be included in the submitted values, false otherwise
44 */
45 public function hasValue()
46 {
47 // don't send a value for unchecked checkboxes
48 if (in_array($this->type, array('checkbox', 'radio')) && null === $this->value) {
49 return false;
50 }
51  
52 return true;
53 }
54  
55 /**
56 * Check if the current selected option is disabled.
57 *
58 * @return bool
59 */
60 public function isDisabled()
61 {
62 if (parent::isDisabled() && 'select' === $this->type) {
63 return true;
64 }
65  
66 foreach ($this->options as $option) {
67 if ($option['value'] == $this->value && $option['disabled']) {
68 return true;
69 }
70 }
71  
72 return false;
73 }
74  
75 /**
76 * Sets the value of the field.
77 *
78 * @param string $value The value of the field
79 */
80 public function select($value)
81 {
82 $this->setValue($value);
83 }
84  
85 /**
86 * Ticks a checkbox.
87 *
88 * @throws \LogicException When the type provided is not correct
89 */
90 public function tick()
91 {
92 if ('checkbox' !== $this->type) {
93 throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type));
94 }
95  
96 $this->setValue(true);
97 }
98  
99 /**
100 * Ticks a checkbox.
101 *
102 * @throws \LogicException When the type provided is not correct
103 */
104 public function untick()
105 {
106 if ('checkbox' !== $this->type) {
107 throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type));
108 }
109  
110 $this->setValue(false);
111 }
112  
113 /**
114 * Sets the value of the field.
115 *
116 * @param string $value The value of the field
117 *
118 * @throws \InvalidArgumentException When value type provided is not correct
119 */
120 public function setValue($value)
121 {
122 if ('checkbox' === $this->type && false === $value) {
123 // uncheck
124 $this->value = null;
125 } elseif ('checkbox' === $this->type && true === $value) {
126 // check
127 $this->value = $this->options[0]['value'];
128 } else {
129 if (is_array($value)) {
130 if (!$this->multiple) {
131 throw new \InvalidArgumentException(sprintf('The value for "%s" cannot be an array.', $this->name));
132 }
133  
134 foreach ($value as $v) {
135 if (!$this->containsOption($v, $this->options)) {
136 throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $v, implode(', ', $this->availableOptionValues())));
137 }
138 }
139 } elseif (!$this->containsOption($value, $this->options)) {
140 throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $value, implode(', ', $this->availableOptionValues())));
141 }
142  
143 if ($this->multiple) {
144 $value = (array) $value;
145 }
146  
147 if (is_array($value)) {
148 $this->value = $value;
149 } else {
150 parent::setValue($value);
151 }
152 }
153 }
154  
155 /**
156 * Adds a choice to the current ones.
157 *
158 * @param \DOMElement $node
159 *
160 * @throws \LogicException When choice provided is not multiple nor radio
161 *
162 * @internal
163 */
164 public function addChoice(\DOMElement $node)
165 {
166 if (!$this->multiple && 'radio' !== $this->type) {
167 throw new \LogicException(sprintf('Unable to add a choice for "%s" as it is not multiple or is not a radio button.', $this->name));
168 }
169  
170 $option = $this->buildOptionValue($node);
171 $this->options[] = $option;
172  
173 if ($node->hasAttribute('checked')) {
174 $this->value = $option['value'];
175 }
176 }
177  
178 /**
179 * Returns the type of the choice field (radio, select, or checkbox).
180 *
181 * @return string The type
182 */
183 public function getType()
184 {
185 return $this->type;
186 }
187  
188 /**
189 * Returns true if the field accepts multiple values.
190 *
191 * @return bool true if the field accepts multiple values, false otherwise
192 */
193 public function isMultiple()
194 {
195 return $this->multiple;
196 }
197  
198 /**
199 * Initializes the form field.
200 *
201 * @throws \LogicException When node type is incorrect
202 */
203 protected function initialize()
204 {
205 if ('input' !== $this->node->nodeName && 'select' !== $this->node->nodeName) {
206 throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input or select tag (%s given).', $this->node->nodeName));
207 }
208  
209 if ('input' === $this->node->nodeName && 'checkbox' !== strtolower($this->node->getAttribute('type')) && 'radio' !== strtolower($this->node->getAttribute('type'))) {
210 throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input tag with a type of checkbox or radio (given type is %s).', $this->node->getAttribute('type')));
211 }
212  
213 $this->value = null;
214 $this->options = array();
215 $this->multiple = false;
216  
217 if ('input' == $this->node->nodeName) {
218 $this->type = strtolower($this->node->getAttribute('type'));
219 $optionValue = $this->buildOptionValue($this->node);
220 $this->options[] = $optionValue;
221  
222 if ($this->node->hasAttribute('checked')) {
223 $this->value = $optionValue['value'];
224 }
225 } else {
226 $this->type = 'select';
227 if ($this->node->hasAttribute('multiple')) {
228 $this->multiple = true;
229 $this->value = array();
230 $this->name = str_replace('[]', '', $this->name);
231 }
232  
233 $found = false;
234 foreach ($this->xpath->query('descendant::option', $this->node) as $option) {
235 $optionValue = $this->buildOptionValue($option);
236 $this->options[] = $optionValue;
237  
238 if ($option->hasAttribute('selected')) {
239 $found = true;
240 if ($this->multiple) {
241 $this->value[] = $optionValue['value'];
242 } else {
243 $this->value = $optionValue['value'];
244 }
245 }
246 }
247  
248 // if no option is selected and if it is a simple select box, take the first option as the value
249 if (!$found && !$this->multiple && !empty($this->options)) {
250 $this->value = $this->options[0]['value'];
251 }
252 }
253 }
254  
255 /**
256 * Returns option value with associated disabled flag.
257 *
258 * @param \DOMElement $node
259 *
260 * @return array
261 */
262 private function buildOptionValue(\DOMElement $node)
263 {
264 $option = array();
265  
266 $defaultDefaultValue = 'select' === $this->node->nodeName ? '' : 'on';
267 $defaultValue = (isset($node->nodeValue) && !empty($node->nodeValue)) ? $node->nodeValue : $defaultDefaultValue;
268 $option['value'] = $node->hasAttribute('value') ? $node->getAttribute('value') : $defaultValue;
269 $option['disabled'] = $node->hasAttribute('disabled');
270  
271 return $option;
272 }
273  
274 /**
275 * Checks whether given value is in the existing options.
276 *
277 * @param string $optionValue
278 * @param array $options
279 *
280 * @return bool
281 */
282 public function containsOption($optionValue, $options)
283 {
284 if ($this->validationDisabled) {
285 return true;
286 }
287  
288 foreach ($options as $option) {
289 if ($option['value'] == $optionValue) {
290 return true;
291 }
292 }
293  
294 return false;
295 }
296  
297 /**
298 * Returns list of available field options.
299 *
300 * @return array
301 */
302 public function availableOptionValues()
303 {
304 $values = array();
305  
306 foreach ($this->options as $option) {
307 $values[] = $option['value'];
308 }
309  
310 return $values;
311 }
312  
313 /**
314 * Disables the internal validation of the field.
315 *
316 * @return self
317 */
318 public function disableValidation()
319 {
320 $this->validationDisabled = true;
321  
322 return $this;
323 }
324 }