aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/symfony/form/Symfony/Component/Form/Extension/Core
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/symfony/form/Symfony/Component/Form/Extension/Core')
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php510
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.php149
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.php149
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php184
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php164
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/CoreExtension.php59
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php92
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php86
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php52
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php85
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php118
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php62
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php117
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php83
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.php86
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php184
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php169
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php82
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php231
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php89
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php53
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php90
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php184
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php149
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php91
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php62
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php66
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php56
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php137
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php173
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/TrimListener.php55
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BaseType.php121
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BirthdayType.php44
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ButtonType.php38
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CheckboxType.php67
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php274
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CollectionType.php103
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CountryType.php45
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php45
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php281
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateType.php309
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/EmailType.php33
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FileType.php61
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FormType.php214
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/HiddenType.php40
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/IntegerType.php68
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LanguageType.php45
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LocaleType.php46
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/MoneyType.php111
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/NumberType.php66
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PasswordType.php57
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PercentType.php55
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RadioType.php33
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php67
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ResetType.php39
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SearchType.php33
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SubmitType.php46
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextType.php36
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextareaType.php43
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimeType.php225
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php86
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/UrlType.php54
-rw-r--r--vendor/symfony/form/Symfony/Component/Form/Extension/Core/View/ChoiceView.php55
63 files changed, 6707 insertions, 0 deletions
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php
new file mode 100644
index 00000000..f9d381cd
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php
@@ -0,0 +1,510 @@
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
12namespace Symfony\Component\Form\Extension\Core\ChoiceList;
13
14use Symfony\Component\Form\FormConfigBuilder;
15use Symfony\Component\Form\Exception\UnexpectedTypeException;
16use Symfony\Component\Form\Exception\InvalidConfigurationException;
17use Symfony\Component\Form\Exception\InvalidArgumentException;
18use Symfony\Component\Form\Extension\Core\View\ChoiceView;
19
20/**
21 * A choice list for choices of arbitrary data types.
22 *
23 * Choices and labels are passed in two arrays. The indices of the choices
24 * and the labels should match. Choices may also be given as hierarchy of
25 * unlimited depth by creating nested arrays. The title of the sub-hierarchy
26 * can be stored in the array key pointing to the nested array. The topmost
27 * level of the hierarchy may also be a \Traversable.
28 *
29 * <code>
30 * $choices = array(true, false);
31 * $labels = array('Agree', 'Disagree');
32 * $choiceList = new ChoiceList($choices, $labels);
33 * </code>
34 *
35 * @author Bernhard Schussek <bschussek@gmail.com>
36 */
37class ChoiceList implements ChoiceListInterface
38{
39 /**
40 * The choices with their indices as keys.
41 *
42 * @var array
43 */
44 private $choices = array();
45
46 /**
47 * The choice values with the indices of the matching choices as keys.
48 *
49 * @var array
50 */
51 private $values = array();
52
53 /**
54 * The preferred view objects as hierarchy containing also the choice groups
55 * with the indices of the matching choices as bottom-level keys.
56 *
57 * @var array
58 */
59 private $preferredViews = array();
60
61 /**
62 * The non-preferred view objects as hierarchy containing also the choice
63 * groups with the indices of the matching choices as bottom-level keys.
64 *
65 * @var array
66 */
67 private $remainingViews = array();
68
69 /**
70 * Creates a new choice list.
71 *
72 * @param array|\Traversable $choices The array of choices. Choices may also be given
73 * as hierarchy of unlimited depth. Hierarchies are
74 * created by creating nested arrays. The title of
75 * the sub-hierarchy can be stored in the array
76 * key pointing to the nested array. The topmost
77 * level of the hierarchy may also be a \Traversable.
78 * @param array $labels The array of labels. The structure of this array
79 * should match the structure of $choices.
80 * @param array $preferredChoices A flat array of choices that should be
81 * presented to the user with priority.
82 *
83 * @throws UnexpectedTypeException If the choices are not an array or \Traversable.
84 */
85 public function __construct($choices, array $labels, array $preferredChoices = array())
86 {
87 if (!is_array($choices) && !$choices instanceof \Traversable) {
88 throw new UnexpectedTypeException($choices, 'array or \Traversable');
89 }
90
91 $this->initialize($choices, $labels, $preferredChoices);
92 }
93
94 /**
95 * Initializes the list with choices.
96 *
97 * Safe to be called multiple times. The list is cleared on every call.
98 *
99 * @param array|\Traversable $choices The choices to write into the list.
100 * @param array $labels The labels belonging to the choices.
101 * @param array $preferredChoices The choices to display with priority.
102 */
103 protected function initialize($choices, array $labels, array $preferredChoices)
104 {
105 $this->choices = array();
106 $this->values = array();
107 $this->preferredViews = array();
108 $this->remainingViews = array();
109
110 $this->addChoices(
111 $this->preferredViews,
112 $this->remainingViews,
113 $choices,
114 $labels,
115 $preferredChoices
116 );
117 }
118
119 /**
120 * {@inheritdoc}
121 */
122 public function getChoices()
123 {
124 return $this->choices;
125 }
126
127 /**
128 * {@inheritdoc}
129 */
130 public function getValues()
131 {
132 return $this->values;
133 }
134
135 /**
136 * {@inheritdoc}
137 */
138 public function getPreferredViews()
139 {
140 return $this->preferredViews;
141 }
142
143 /**
144 * {@inheritdoc}
145 */
146 public function getRemainingViews()
147 {
148 return $this->remainingViews;
149 }
150
151 /**
152 * {@inheritdoc}
153 */
154 public function getChoicesForValues(array $values)
155 {
156 $values = $this->fixValues($values);
157 $choices = array();
158
159 foreach ($values as $j => $givenValue) {
160 foreach ($this->values as $i => $value) {
161 if ($value === $givenValue) {
162 $choices[] = $this->choices[$i];
163 unset($values[$j]);
164
165 if (0 === count($values)) {
166 break 2;
167 }
168 }
169 }
170 }
171
172 return $choices;
173 }
174
175 /**
176 * {@inheritdoc}
177 */
178 public function getValuesForChoices(array $choices)
179 {
180 $choices = $this->fixChoices($choices);
181 $values = array();
182
183 foreach ($this->choices as $i => $choice) {
184 foreach ($choices as $j => $givenChoice) {
185 if ($choice === $givenChoice) {
186 $values[] = $this->values[$i];
187 unset($choices[$j]);
188
189 if (0 === count($choices)) {
190 break 2;
191 }
192 }
193 }
194 }
195
196 return $values;
197 }
198
199 /**
200 * {@inheritdoc}
201 */
202 public function getIndicesForChoices(array $choices)
203 {
204 $choices = $this->fixChoices($choices);
205 $indices = array();
206
207 foreach ($this->choices as $i => $choice) {
208 foreach ($choices as $j => $givenChoice) {
209 if ($choice === $givenChoice) {
210 $indices[] = $i;
211 unset($choices[$j]);
212
213 if (0 === count($choices)) {
214 break 2;
215 }
216 }
217 }
218 }
219
220 return $indices;
221 }
222
223 /**
224 * {@inheritdoc}
225 */
226 public function getIndicesForValues(array $values)
227 {
228 $values = $this->fixValues($values);
229 $indices = array();
230
231 foreach ($this->values as $i => $value) {
232 foreach ($values as $j => $givenValue) {
233 if ($value === $givenValue) {
234 $indices[] = $i;
235 unset($values[$j]);
236
237 if (0 === count($values)) {
238 break 2;
239 }
240 }
241 }
242 }
243
244 return $indices;
245 }
246
247 /**
248 * Recursively adds the given choices to the list.
249 *
250 * @param array $bucketForPreferred The bucket where to store the preferred
251 * view objects.
252 * @param array $bucketForRemaining The bucket where to store the
253 * non-preferred view objects.
254 * @param array|\Traversable $choices The list of choices.
255 * @param array $labels The labels corresponding to the choices.
256 * @param array $preferredChoices The preferred choices.
257 *
258 * @throws InvalidArgumentException If the structures of the choices and labels array do not match.
259 * @throws InvalidConfigurationException If no valid value or index could be created for a choice.
260 */
261 protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices)
262 {
263 // Add choices to the nested buckets
264 foreach ($choices as $group => $choice) {
265 if (!array_key_exists($group, $labels)) {
266 throw new InvalidArgumentException('The structures of the choices and labels array do not match.');
267 }
268
269 if (is_array($choice)) {
270 // Don't do the work if the array is empty
271 if (count($choice) > 0) {
272 $this->addChoiceGroup(
273 $group,
274 $bucketForPreferred,
275 $bucketForRemaining,
276 $choice,
277 $labels[$group],
278 $preferredChoices
279 );
280 }
281 } else {
282 $this->addChoice(
283 $bucketForPreferred,
284 $bucketForRemaining,
285 $choice,
286 $labels[$group],
287 $preferredChoices
288 );
289 }
290 }
291 }
292
293 /**
294 * Recursively adds a choice group.
295 *
296 * @param string $group The name of the group.
297 * @param array $bucketForPreferred The bucket where to store the preferred
298 * view objects.
299 * @param array $bucketForRemaining The bucket where to store the
300 * non-preferred view objects.
301 * @param array $choices The list of choices in the group.
302 * @param array $labels The labels corresponding to the choices in the group.
303 * @param array $preferredChoices The preferred choices.
304 *
305 * @throws InvalidConfigurationException If no valid value or index could be created for a choice.
306 */
307 protected function addChoiceGroup($group, array &$bucketForPreferred, array &$bucketForRemaining, array $choices, array $labels, array $preferredChoices)
308 {
309 // If this is a choice group, create a new level in the choice
310 // key hierarchy
311 $bucketForPreferred[$group] = array();
312 $bucketForRemaining[$group] = array();
313
314 $this->addChoices(
315 $bucketForPreferred[$group],
316 $bucketForRemaining[$group],
317 $choices,
318 $labels,
319 $preferredChoices
320 );
321
322 // Remove child levels if empty
323 if (empty($bucketForPreferred[$group])) {
324 unset($bucketForPreferred[$group]);
325 }
326 if (empty($bucketForRemaining[$group])) {
327 unset($bucketForRemaining[$group]);
328 }
329 }
330
331 /**
332 * Adds a new choice.
333 *
334 * @param array $bucketForPreferred The bucket where to store the preferred
335 * view objects.
336 * @param array $bucketForRemaining The bucket where to store the
337 * non-preferred view objects.
338 * @param mixed $choice The choice to add.
339 * @param string $label The label for the choice.
340 * @param array $preferredChoices The preferred choices.
341 *
342 * @throws InvalidConfigurationException If no valid value or index could be created.
343 */
344 protected function addChoice(array &$bucketForPreferred, array &$bucketForRemaining, $choice, $label, array $preferredChoices)
345 {
346 $index = $this->createIndex($choice);
347
348 if ('' === $index || null === $index || !FormConfigBuilder::isValidName((string) $index)) {
349 throw new InvalidConfigurationException(sprintf('The index "%s" created by the choice list is invalid. It should be a valid, non-empty Form name.', $index));
350 }
351
352 $value = $this->createValue($choice);
353
354 if (!is_string($value)) {
355 throw new InvalidConfigurationException(sprintf('The value created by the choice list is of type "%s", but should be a string.', gettype($value)));
356 }
357
358 $view = new ChoiceView($choice, $value, $label);
359
360 $this->choices[$index] = $this->fixChoice($choice);
361 $this->values[$index] = $value;
362
363 if ($this->isPreferred($choice, $preferredChoices)) {
364 $bucketForPreferred[$index] = $view;
365 } else {
366 $bucketForRemaining[$index] = $view;
367 }
368 }
369
370 /**
371 * Returns whether the given choice should be preferred judging by the
372 * given array of preferred choices.
373 *
374 * Extension point to optimize performance by changing the structure of the
375 * $preferredChoices array.
376 *
377 * @param mixed $choice The choice to test.
378 * @param array $preferredChoices An array of preferred choices.
379 *
380 * @return Boolean Whether the choice is preferred.
381 */
382 protected function isPreferred($choice, array $preferredChoices)
383 {
384 return false !== array_search($choice, $preferredChoices, true);
385 }
386
387 /**
388 * Creates a new unique index for this choice.
389 *
390 * Extension point to change the indexing strategy.
391 *
392 * @param mixed $choice The choice to create an index for
393 *
394 * @return integer|string A unique index containing only ASCII letters,
395 * digits and underscores.
396 */
397 protected function createIndex($choice)
398 {
399 return count($this->choices);
400 }
401
402 /**
403 * Creates a new unique value for this choice.
404 *
405 * By default, an integer is generated since it cannot be guaranteed that
406 * all values in the list are convertible to (unique) strings. Subclasses
407 * can override this behaviour if they can guarantee this property.
408 *
409 * @param mixed $choice The choice to create a value for
410 *
411 * @return string A unique string.
412 */
413 protected function createValue($choice)
414 {
415 return (string) count($this->values);
416 }
417
418 /**
419 * Fixes the data type of the given choice value to avoid comparison
420 * problems.
421 *
422 * @param mixed $value The choice value.
423 *
424 * @return string The value as string.
425 */
426 protected function fixValue($value)
427 {
428 return (string) $value;
429 }
430
431 /**
432 * Fixes the data types of the given choice values to avoid comparison
433 * problems.
434 *
435 * @param array $values The choice values.
436 *
437 * @return array The values as strings.
438 */
439 protected function fixValues(array $values)
440 {
441 foreach ($values as $i => $value) {
442 $values[$i] = $this->fixValue($value);
443 }
444
445 return $values;
446 }
447
448 /**
449 * Fixes the data type of the given choice index to avoid comparison
450 * problems.
451 *
452 * @param mixed $index The choice index.
453 *
454 * @return integer|string The index as PHP array key.
455 */
456 protected function fixIndex($index)
457 {
458 if (is_bool($index) || (string) (int) $index === (string) $index) {
459 return (int) $index;
460 }
461
462 return (string) $index;
463 }
464
465 /**
466 * Fixes the data types of the given choice indices to avoid comparison
467 * problems.
468 *
469 * @param array $indices The choice indices.
470 *
471 * @return array The indices as strings.
472 */
473 protected function fixIndices(array $indices)
474 {
475 foreach ($indices as $i => $index) {
476 $indices[$i] = $this->fixIndex($index);
477 }
478
479 return $indices;
480 }
481
482 /**
483 * Fixes the data type of the given choice to avoid comparison problems.
484 *
485 * Extension point. In this implementation, choices are guaranteed to
486 * always maintain their type and thus can be typesafely compared.
487 *
488 * @param mixed $choice The choice.
489 *
490 * @return mixed The fixed choice.
491 */
492 protected function fixChoice($choice)
493 {
494 return $choice;
495 }
496
497 /**
498 * Fixes the data type of the given choices to avoid comparison problems.
499 *
500 * @param array $choices The choices.
501 *
502 * @return array The fixed choices.
503 *
504 * @see fixChoice
505 */
506 protected function fixChoices(array $choices)
507 {
508 return $choices;
509 }
510}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.php
new file mode 100644
index 00000000..099ace82
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceListInterface.php
@@ -0,0 +1,149 @@
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
12namespace Symfony\Component\Form\Extension\Core\ChoiceList;
13
14/**
15 * Contains choices that can be selected in a form field.
16 *
17 * Each choice has three different properties:
18 *
19 * - Choice: The choice that should be returned to the application by the
20 * choice field. Can be any scalar value or an object, but no
21 * array.
22 * - Label: A text representing the choice that is displayed to the user.
23 * - Value: A uniquely identifying value that can contain arbitrary
24 * characters, but no arrays or objects. This value is displayed
25 * in the HTML "value" attribute.
26 *
27 * @author Bernhard Schussek <bschussek@gmail.com>
28 */
29interface ChoiceListInterface
30{
31 /**
32 * Returns the list of choices
33 *
34 * @return array The choices with their indices as keys
35 */
36 public function getChoices();
37
38 /**
39 * Returns the values for the choices
40 *
41 * @return array The values with the corresponding choice indices as keys
42 */
43 public function getValues();
44
45 /**
46 * Returns the choice views of the preferred choices as nested array with
47 * the choice groups as top-level keys.
48 *
49 * Example:
50 *
51 * <source>
52 * array(
53 * 'Group 1' => array(
54 * 10 => ChoiceView object,
55 * 20 => ChoiceView object,
56 * ),
57 * 'Group 2' => array(
58 * 30 => ChoiceView object,
59 * ),
60 * )
61 * </source>
62 *
63 * @return array A nested array containing the views with the corresponding
64 * choice indices as keys on the lowest levels and the choice
65 * group names in the keys of the higher levels
66 */
67 public function getPreferredViews();
68
69 /**
70 * Returns the choice views of the choices that are not preferred as nested
71 * array with the choice groups as top-level keys.
72 *
73 * Example:
74 *
75 * <source>
76 * array(
77 * 'Group 1' => array(
78 * 10 => ChoiceView object,
79 * 20 => ChoiceView object,
80 * ),
81 * 'Group 2' => array(
82 * 30 => ChoiceView object,
83 * ),
84 * )
85 * </source>
86 *
87 * @return array A nested array containing the views with the corresponding
88 * choice indices as keys on the lowest levels and the choice
89 * group names in the keys of the higher levels
90 *
91 * @see getPreferredValues
92 */
93 public function getRemainingViews();
94
95 /**
96 * Returns the choices corresponding to the given values.
97 *
98 * The choices can have any data type.
99 *
100 * @param array $values An array of choice values. Not existing values in
101 * this array are ignored
102 *
103 * @return array An array of choices with ascending, 0-based numeric keys
104 */
105 public function getChoicesForValues(array $values);
106
107 /**
108 * Returns the values corresponding to the given choices.
109 *
110 * The values must be strings.
111 *
112 * @param array $choices An array of choices. Not existing choices in this
113 * array are ignored
114 *
115 * @return array An array of choice values with ascending, 0-based numeric
116 * keys
117 */
118 public function getValuesForChoices(array $choices);
119
120 /**
121 * Returns the indices corresponding to the given choices.
122 *
123 * The indices must be positive integers or strings accepted by
124 * {@link FormConfigBuilder::validateName()}.
125 *
126 * The index "placeholder" is internally reserved.
127 *
128 * @param array $choices An array of choices. Not existing choices in this
129 * array are ignored
130 *
131 * @return array An array of indices with ascending, 0-based numeric keys
132 */
133 public function getIndicesForChoices(array $choices);
134
135 /**
136 * Returns the indices corresponding to the given values.
137 *
138 * The indices must be positive integers or strings accepted by
139 * {@link FormConfigBuilder::validateName()}.
140 *
141 * The index "placeholder" is internally reserved.
142 *
143 * @param array $values An array of choice values. Not existing values in
144 * this array are ignored
145 *
146 * @return array An array of indices with ascending, 0-based numeric keys
147 */
148 public function getIndicesForValues(array $values);
149}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.php
new file mode 100644
index 00000000..996f900c
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/LazyChoiceList.php
@@ -0,0 +1,149 @@
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
12namespace Symfony\Component\Form\Extension\Core\ChoiceList;
13
14use Symfony\Component\Form\Exception\InvalidArgumentException;
15
16/**
17 * A choice list that is loaded lazily
18 *
19 * This list loads itself as soon as any of the getters is accessed for the
20 * first time. You should implement loadChoiceList() in your child classes,
21 * which should return a ChoiceListInterface instance.
22 *
23 * @author Bernhard Schussek <bschussek@gmail.com>
24 */
25abstract class LazyChoiceList implements ChoiceListInterface
26{
27 /**
28 * The loaded choice list
29 *
30 * @var ChoiceListInterface
31 */
32 private $choiceList;
33
34 /**
35 * {@inheritdoc}
36 */
37 public function getChoices()
38 {
39 if (!$this->choiceList) {
40 $this->load();
41 }
42
43 return $this->choiceList->getChoices();
44 }
45
46 /**
47 * {@inheritdoc}
48 */
49 public function getValues()
50 {
51 if (!$this->choiceList) {
52 $this->load();
53 }
54
55 return $this->choiceList->getValues();
56 }
57
58 /**
59 * {@inheritdoc}
60 */
61 public function getPreferredViews()
62 {
63 if (!$this->choiceList) {
64 $this->load();
65 }
66
67 return $this->choiceList->getPreferredViews();
68 }
69
70 /**
71 * {@inheritdoc}
72 */
73 public function getRemainingViews()
74 {
75 if (!$this->choiceList) {
76 $this->load();
77 }
78
79 return $this->choiceList->getRemainingViews();
80 }
81
82 /**
83 * {@inheritdoc}
84 */
85 public function getChoicesForValues(array $values)
86 {
87 if (!$this->choiceList) {
88 $this->load();
89 }
90
91 return $this->choiceList->getChoicesForValues($values);
92 }
93
94 /**
95 * {@inheritdoc}
96 */
97 public function getValuesForChoices(array $choices)
98 {
99 if (!$this->choiceList) {
100 $this->load();
101 }
102
103 return $this->choiceList->getValuesForChoices($choices);
104 }
105
106 /**
107 * {@inheritdoc}
108 */
109 public function getIndicesForChoices(array $choices)
110 {
111 if (!$this->choiceList) {
112 $this->load();
113 }
114
115 return $this->choiceList->getIndicesForChoices($choices);
116 }
117
118 /**
119 * {@inheritdoc}
120 */
121 public function getIndicesForValues(array $values)
122 {
123 if (!$this->choiceList) {
124 $this->load();
125 }
126
127 return $this->choiceList->getIndicesForValues($values);
128 }
129
130 /**
131 * Loads the choice list
132 *
133 * Should be implemented by child classes.
134 *
135 * @return ChoiceListInterface The loaded choice list
136 */
137 abstract protected function loadChoiceList();
138
139 private function load()
140 {
141 $choiceList = $this->loadChoiceList();
142
143 if (!$choiceList instanceof ChoiceListInterface) {
144 throw new InvalidArgumentException(sprintf('loadChoiceList() should return a ChoiceListInterface instance. Got %s', gettype($choiceList)));
145 }
146
147 $this->choiceList = $choiceList;
148 }
149}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php
new file mode 100644
index 00000000..0a153883
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php
@@ -0,0 +1,184 @@
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
12namespace Symfony\Component\Form\Extension\Core\ChoiceList;
13
14use Symfony\Component\Form\Exception\StringCastException;
15use Symfony\Component\Form\Exception\InvalidArgumentException;
16use Symfony\Component\PropertyAccess\PropertyPath;
17use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
18use Symfony\Component\PropertyAccess\PropertyAccess;
19use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
20
21/**
22 * A choice list for object choices.
23 *
24 * Supports generation of choice labels, choice groups and choice values
25 * by calling getters of the object (or associated objects).
26 *
27 * <code>
28 * $choices = array($user1, $user2);
29 *
30 * // call getName() to determine the choice labels
31 * $choiceList = new ObjectChoiceList($choices, 'name');
32 * </code>
33 *
34 * @author Bernhard Schussek <bschussek@gmail.com>
35 */
36class ObjectChoiceList extends ChoiceList
37{
38 /**
39 * @var PropertyAccessorInterface
40 */
41 private $propertyAccessor;
42
43 /**
44 * The property path used to obtain the choice label.
45 *
46 * @var PropertyPath
47 */
48 private $labelPath;
49
50 /**
51 * The property path used for object grouping.
52 *
53 * @var PropertyPath
54 */
55 private $groupPath;
56
57 /**
58 * The property path used to obtain the choice value.
59 *
60 * @var PropertyPath
61 */
62 private $valuePath;
63
64 /**
65 * Creates a new object choice list.
66 *
67 * @param array|\Traversable $choices The array of choices. Choices may also be given
68 * as hierarchy of unlimited depth by creating nested
69 * arrays. The title of the sub-hierarchy can be
70 * stored in the array key pointing to the nested
71 * array. The topmost level of the hierarchy may also
72 * be a \Traversable.
73 * @param string $labelPath A property path pointing to the property used
74 * for the choice labels. The value is obtained
75 * by calling the getter on the object. If the
76 * path is NULL, the object's __toString() method
77 * is used instead.
78 * @param array $preferredChoices A flat array of choices that should be
79 * presented to the user with priority.
80 * @param string $groupPath A property path pointing to the property used
81 * to group the choices. Only allowed if
82 * the choices are given as flat array.
83 * @param string $valuePath A property path pointing to the property used
84 * for the choice values. If not given, integers
85 * are generated instead.
86 * @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths.
87 */
88 public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null, PropertyAccessorInterface $propertyAccessor = null)
89 {
90 $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
91 $this->labelPath = null !== $labelPath ? new PropertyPath($labelPath) : null;
92 $this->groupPath = null !== $groupPath ? new PropertyPath($groupPath) : null;
93 $this->valuePath = null !== $valuePath ? new PropertyPath($valuePath) : null;
94
95 parent::__construct($choices, array(), $preferredChoices);
96 }
97
98 /**
99 * Initializes the list with choices.
100 *
101 * Safe to be called multiple times. The list is cleared on every call.
102 *
103 * @param array|\Traversable $choices The choices to write into the list.
104 * @param array $labels Ignored.
105 * @param array $preferredChoices The choices to display with priority.
106 *
107 * @throws InvalidArgumentException When passing a hierarchy of choices and using
108 * the "groupPath" option at the same time.
109 */
110 protected function initialize($choices, array $labels, array $preferredChoices)
111 {
112 if (null !== $this->groupPath) {
113 $groupedChoices = array();
114
115 foreach ($choices as $i => $choice) {
116 if (is_array($choice)) {
117 throw new InvalidArgumentException('You should pass a plain object array (without groups) when using the "groupPath" option.');
118 }
119
120 try {
121 $group = $this->propertyAccessor->getValue($choice, $this->groupPath);
122 } catch (NoSuchPropertyException $e) {
123 // Don't group items whose group property does not exist
124 // see https://github.com/symfony/symfony/commit/d9b7abb7c7a0f28e0ce970afc5e305dce5dccddf
125 $group = null;
126 }
127
128 if (null === $group) {
129 $groupedChoices[$i] = $choice;
130 } else {
131 if (!isset($groupedChoices[$group])) {
132 $groupedChoices[$group] = array();
133 }
134
135 $groupedChoices[$group][$i] = $choice;
136 }
137 }
138
139 $choices = $groupedChoices;
140 }
141
142 $labels = array();
143
144 $this->extractLabels($choices, $labels);
145
146 parent::initialize($choices, $labels, $preferredChoices);
147 }
148
149 /**
150 * Creates a new unique value for this choice.
151 *
152 * If a property path for the value was given at object creation,
153 * the getter behind that path is now called to obtain a new value.
154 * Otherwise a new integer is generated.
155 *
156 * @param mixed $choice The choice to create a value for
157 *
158 * @return integer|string A unique value without character limitations.
159 */
160 protected function createValue($choice)
161 {
162 if ($this->valuePath) {
163 return (string) $this->propertyAccessor->getValue($choice, $this->valuePath);
164 }
165
166 return parent::createValue($choice);
167 }
168
169 private function extractLabels($choices, array &$labels)
170 {
171 foreach ($choices as $i => $choice) {
172 if (is_array($choice)) {
173 $labels[$i] = array();
174 $this->extractLabels($choice, $labels[$i]);
175 } elseif ($this->labelPath) {
176 $labels[$i] = $this->propertyAccessor->getValue($choice, $this->labelPath);
177 } elseif (method_exists($choice, '__toString')) {
178 $labels[$i] = (string) $choice;
179 } else {
180 throw new StringCastException(sprintf('A "__toString()" method was not found on the objects of type "%s" passed to the choice field. To read a custom getter instead, set the argument $labelPath to the desired property path.', get_class($choice)));
181 }
182 }
183 }
184}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php
new file mode 100644
index 00000000..914dbe5f
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php
@@ -0,0 +1,164 @@
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
12namespace Symfony\Component\Form\Extension\Core\ChoiceList;
13
14/**
15 * A choice list for choices of type string or integer.
16 *
17 * Choices and their associated labels can be passed in a single array. Since
18 * choices are passed as array keys, only strings or integer choices are
19 * allowed. Choices may also be given as hierarchy of unlimited depth by
20 * creating nested arrays. The title of the sub-hierarchy can be stored in the
21 * array key pointing to the nested array.
22 *
23 * <code>
24 * $choiceList = new SimpleChoiceList(array(
25 * 'creditcard' => 'Credit card payment',
26 * 'cash' => 'Cash payment',
27 * ));
28 * </code>
29 *
30 * @author Bernhard Schussek <bschussek@gmail.com>
31 */
32class SimpleChoiceList extends ChoiceList
33{
34 /**
35 * Creates a new simple choice list.
36 *
37 * @param array $choices The array of choices with the choices as keys and
38 * the labels as values. Choices may also be given
39 * as hierarchy of unlimited depth by creating nested
40 * arrays. The title of the sub-hierarchy is stored
41 * in the array key pointing to the nested array.
42 * @param array $preferredChoices A flat array of choices that should be
43 * presented to the user with priority.
44 */
45 public function __construct(array $choices, array $preferredChoices = array())
46 {
47 // Flip preferred choices to speed up lookup
48 parent::__construct($choices, $choices, array_flip($preferredChoices));
49 }
50
51 /**
52 * {@inheritdoc}
53 */
54 public function getChoicesForValues(array $values)
55 {
56 $values = $this->fixValues($values);
57
58 // The values are identical to the choices, so we can just return them
59 // to improve performance a little bit
60 return $this->fixChoices(array_intersect($values, $this->getValues()));
61 }
62
63 /**
64 * {@inheritdoc}
65 */
66 public function getValuesForChoices(array $choices)
67 {
68 $choices = $this->fixChoices($choices);
69
70 // The choices are identical to the values, so we can just return them
71 // to improve performance a little bit
72 return $this->fixValues(array_intersect($choices, $this->getValues()));
73 }
74
75 /**
76 * Recursively adds the given choices to the list.
77 *
78 * Takes care of splitting the single $choices array passed in the
79 * constructor into choices and labels.
80 *
81 * @param array $bucketForPreferred The bucket where to store the preferred
82 * view objects.
83 * @param array $bucketForRemaining The bucket where to store the
84 * non-preferred view objects.
85 * @param array|\Traversable $choices The list of choices.
86 * @param array $labels Ignored.
87 * @param array $preferredChoices The preferred choices.
88 */
89 protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices)
90 {
91 // Add choices to the nested buckets
92 foreach ($choices as $choice => $label) {
93 if (is_array($label)) {
94 // Don't do the work if the array is empty
95 if (count($label) > 0) {
96 $this->addChoiceGroup(
97 $choice,
98 $bucketForPreferred,
99 $bucketForRemaining,
100 $label,
101 $label,
102 $preferredChoices
103 );
104 }
105 } else {
106 $this->addChoice(
107 $bucketForPreferred,
108 $bucketForRemaining,
109 $choice,
110 $label,
111 $preferredChoices
112 );
113 }
114 }
115 }
116
117 /**
118 * Returns whether the given choice should be preferred judging by the
119 * given array of preferred choices.
120 *
121 * Optimized for performance by treating the preferred choices as array
122 * where choices are stored in the keys.
123 *
124 * @param mixed $choice The choice to test.
125 * @param array $preferredChoices An array of preferred choices.
126 *
127 * @return Boolean Whether the choice is preferred.
128 */
129 protected function isPreferred($choice, array $preferredChoices)
130 {
131 // Optimize performance over the default implementation
132 return isset($preferredChoices[$choice]);
133 }
134
135 /**
136 * Converts the choice to a valid PHP array key.
137 *
138 * @param mixed $choice The choice.
139 *
140 * @return string|integer A valid PHP array key.
141 */
142 protected function fixChoice($choice)
143 {
144 return $this->fixIndex($choice);
145 }
146
147 /**
148 * {@inheritdoc}
149 */
150 protected function fixChoices(array $choices)
151 {
152 return $this->fixIndices($choices);
153 }
154
155 /**
156 * {@inheritdoc}
157 */
158 protected function createValue($choice)
159 {
160 // Choices are guaranteed to be unique and scalar, so we can simply
161 // convert them to strings
162 return (string) $choice;
163 }
164}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/CoreExtension.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/CoreExtension.php
new file mode 100644
index 00000000..bbcac4ba
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/CoreExtension.php
@@ -0,0 +1,59 @@
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
12namespace Symfony\Component\Form\Extension\Core;
13
14use Symfony\Component\Form\AbstractExtension;
15use Symfony\Component\PropertyAccess\PropertyAccess;
16
17/**
18 * Represents the main form extension, which loads the core functionality.
19 *
20 * @author Bernhard Schussek <bschussek@gmail.com>
21 */
22class CoreExtension extends AbstractExtension
23{
24 protected function loadTypes()
25 {
26 return array(
27 new Type\FormType(PropertyAccess::getPropertyAccessor()),
28 new Type\BirthdayType(),
29 new Type\CheckboxType(),
30 new Type\ChoiceType(),
31 new Type\CollectionType(),
32 new Type\CountryType(),
33 new Type\DateType(),
34 new Type\DateTimeType(),
35 new Type\EmailType(),
36 new Type\HiddenType(),
37 new Type\IntegerType(),
38 new Type\LanguageType(),
39 new Type\LocaleType(),
40 new Type\MoneyType(),
41 new Type\NumberType(),
42 new Type\PasswordType(),
43 new Type\PercentType(),
44 new Type\RadioType(),
45 new Type\RepeatedType(),
46 new Type\SearchType(),
47 new Type\TextareaType(),
48 new Type\TextType(),
49 new Type\TimeType(),
50 new Type\TimezoneType(),
51 new Type\UrlType(),
52 new Type\FileType(),
53 new Type\ButtonType(),
54 new Type\SubmitType(),
55 new Type\ResetType(),
56 new Type\CurrencyType(),
57 );
58 }
59}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php
new file mode 100644
index 00000000..d8bd9c71
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataMapper/PropertyPathMapper.php
@@ -0,0 +1,92 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataMapper;
13
14use Symfony\Component\Form\DataMapperInterface;
15use Symfony\Component\Form\Exception\UnexpectedTypeException;
16use Symfony\Component\PropertyAccess\PropertyAccess;
17use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
18
19/**
20 * A data mapper using property paths to read/write data.
21 *
22 * @author Bernhard Schussek <bschussek@gmail.com>
23 */
24class PropertyPathMapper implements DataMapperInterface
25{
26 /**
27 * @var PropertyAccessorInterface
28 */
29 private $propertyAccessor;
30
31 /**
32 * Creates a new property path mapper.
33 *
34 * @param PropertyAccessorInterface $propertyAccessor
35 */
36 public function __construct(PropertyAccessorInterface $propertyAccessor = null)
37 {
38 $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
39 }
40
41 /**
42 * {@inheritdoc}
43 */
44 public function mapDataToForms($data, $forms)
45 {
46 if (null === $data || array() === $data) {
47 return;
48 }
49
50 if (!is_array($data) && !is_object($data)) {
51 throw new UnexpectedTypeException($data, 'object, array or empty');
52 }
53
54 foreach ($forms as $form) {
55 $propertyPath = $form->getPropertyPath();
56 $config = $form->getConfig();
57
58 if (null !== $propertyPath && $config->getMapped()) {
59 $form->setData($this->propertyAccessor->getValue($data, $propertyPath));
60 }
61 }
62 }
63
64 /**
65 * {@inheritdoc}
66 */
67 public function mapFormsToData($forms, &$data)
68 {
69 if (null === $data) {
70 return;
71 }
72
73 if (!is_array($data) && !is_object($data)) {
74 throw new UnexpectedTypeException($data, 'object, array or empty');
75 }
76
77 foreach ($forms as $form) {
78 $propertyPath = $form->getPropertyPath();
79 $config = $form->getConfig();
80
81 // Write-back is disabled if the form is not synchronized (transformation failed)
82 // and if the form is disabled (modification not allowed)
83 if (null !== $propertyPath && $config->getMapped() && $form->isSynchronized() && !$form->isDisabled()) {
84 // If the data is identical to the value in $data, we are
85 // dealing with a reference
86 if (!is_object($data) || !$config->getByReference() || $form->getData() !== $this->propertyAccessor->getValue($data, $propertyPath)) {
87 $this->propertyAccessor->setValue($data, $propertyPath, $form->getData());
88 }
89 }
90 }
91 }
92}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php
new file mode 100644
index 00000000..fc080f25
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ArrayToPartsTransformer.php
@@ -0,0 +1,86 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\DataTransformerInterface;
15use Symfony\Component\Form\Exception\TransformationFailedException;
16
17/**
18 * @author Bernhard Schussek <bschussek@gmail.com>
19 */
20class ArrayToPartsTransformer implements DataTransformerInterface
21{
22 private $partMapping;
23
24 public function __construct(array $partMapping)
25 {
26 $this->partMapping = $partMapping;
27 }
28
29 public function transform($array)
30 {
31 if (null === $array) {
32 $array = array();
33 }
34
35 if (!is_array($array) ) {
36 throw new TransformationFailedException('Expected an array.');
37 }
38
39 $result = array();
40
41 foreach ($this->partMapping as $partKey => $originalKeys) {
42 if (empty($array)) {
43 $result[$partKey] = null;
44 } else {
45 $result[$partKey] = array_intersect_key($array, array_flip($originalKeys));
46 }
47 }
48
49 return $result;
50 }
51
52 public function reverseTransform($array)
53 {
54 if (!is_array($array) ) {
55 throw new TransformationFailedException('Expected an array.');
56 }
57
58 $result = array();
59 $emptyKeys = array();
60
61 foreach ($this->partMapping as $partKey => $originalKeys) {
62 if (!empty($array[$partKey])) {
63 foreach ($originalKeys as $originalKey) {
64 if (isset($array[$partKey][$originalKey])) {
65 $result[$originalKey] = $array[$partKey][$originalKey];
66 }
67 }
68 } else {
69 $emptyKeys[] = $partKey;
70 }
71 }
72
73 if (count($emptyKeys) > 0) {
74 if (count($emptyKeys) === count($this->partMapping)) {
75 // All parts empty
76 return null;
77 }
78
79 throw new TransformationFailedException(
80 sprintf('The keys "%s" should not be empty', implode('", "', $emptyKeys)
81 ));
82 }
83
84 return $result;
85 }
86}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php
new file mode 100644
index 00000000..e4e8932e
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php
@@ -0,0 +1,52 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\DataTransformerInterface;
15use Symfony\Component\Form\Exception\UnexpectedTypeException;
16
17abstract class BaseDateTimeTransformer implements DataTransformerInterface
18{
19 protected static $formats = array(
20 \IntlDateFormatter::NONE,
21 \IntlDateFormatter::FULL,
22 \IntlDateFormatter::LONG,
23 \IntlDateFormatter::MEDIUM,
24 \IntlDateFormatter::SHORT,
25 );
26
27 protected $inputTimezone;
28
29 protected $outputTimezone;
30
31 /**
32 * Constructor.
33 *
34 * @param string $inputTimezone The name of the input timezone
35 * @param string $outputTimezone The name of the output timezone
36 *
37 * @throws UnexpectedTypeException if a timezone is not a string
38 */
39 public function __construct($inputTimezone = null, $outputTimezone = null)
40 {
41 if (!is_string($inputTimezone) && null !== $inputTimezone) {
42 throw new UnexpectedTypeException($inputTimezone, 'string');
43 }
44
45 if (!is_string($outputTimezone) && null !== $outputTimezone) {
46 throw new UnexpectedTypeException($outputTimezone, 'string');
47 }
48
49 $this->inputTimezone = $inputTimezone ?: date_default_timezone_get();
50 $this->outputTimezone = $outputTimezone ?: date_default_timezone_get();
51 }
52}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php
new file mode 100644
index 00000000..95e7332d
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php
@@ -0,0 +1,85 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\DataTransformerInterface;
15use Symfony\Component\Form\Exception\TransformationFailedException;
16
17/**
18 * Transforms between a Boolean and a string.
19 *
20 * @author Bernhard Schussek <bschussek@gmail.com>
21 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
22 */
23class BooleanToStringTransformer implements DataTransformerInterface
24{
25 /**
26 * The value emitted upon transform if the input is true
27 * @var string
28 */
29 private $trueValue;
30
31 /**
32 * Sets the value emitted upon transform if the input is true.
33 *
34 * @param string $trueValue
35 */
36 public function __construct($trueValue)
37 {
38 $this->trueValue = $trueValue;
39 }
40
41 /**
42 * Transforms a Boolean into a string.
43 *
44 * @param Boolean $value Boolean value.
45 *
46 * @return string String value.
47 *
48 * @throws TransformationFailedException If the given value is not a Boolean.
49 */
50 public function transform($value)
51 {
52 if (null === $value) {
53 return null;
54 }
55
56 if (!is_bool($value)) {
57 throw new TransformationFailedException('Expected a Boolean.');
58 }
59
60 return true === $value ? $this->trueValue : null;
61 }
62
63 /**
64 * Transforms a string into a Boolean.
65 *
66 * @param string $value String value.
67 *
68 * @return Boolean Boolean value.
69 *
70 * @throws TransformationFailedException If the given value is not a string.
71 */
72 public function reverseTransform($value)
73 {
74 if (null === $value) {
75 return false;
76 }
77
78 if (!is_string($value)) {
79 throw new TransformationFailedException('Expected a string.');
80 }
81
82 return true;
83 }
84
85}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php
new file mode 100644
index 00000000..79b3f7ac
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php
@@ -0,0 +1,118 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
15use Symfony\Component\Form\DataTransformerInterface;
16use Symfony\Component\Form\Exception\TransformationFailedException;
17
18/**
19 * @author Bernhard Schussek <bschussek@gmail.com>
20 */
21class ChoiceToBooleanArrayTransformer implements DataTransformerInterface
22{
23 private $choiceList;
24
25 private $placeholderPresent;
26
27 /**
28 * Constructor.
29 *
30 * @param ChoiceListInterface $choiceList
31 * @param Boolean $placeholderPresent
32 */
33 public function __construct(ChoiceListInterface $choiceList, $placeholderPresent)
34 {
35 $this->choiceList = $choiceList;
36 $this->placeholderPresent = $placeholderPresent;
37 }
38
39 /**
40 * Transforms a single choice to a format appropriate for the nested
41 * checkboxes/radio buttons.
42 *
43 * The result is an array with the options as keys and true/false as values,
44 * depending on whether a given option is selected. If this field is rendered
45 * as select tag, the value is not modified.
46 *
47 * @param mixed $choice An array if "multiple" is set to true, a scalar
48 * value otherwise.
49 *
50 * @return mixed An array
51 *
52 * @throws TransformationFailedException If the given value is not scalar or
53 * if the choices can not be retrieved.
54 */
55 public function transform($choice)
56 {
57 try {
58 $values = $this->choiceList->getValues();
59 } catch (\Exception $e) {
60 throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e);
61 }
62
63 $index = current($this->choiceList->getIndicesForChoices(array($choice)));
64
65 foreach ($values as $i => $value) {
66 $values[$i] = $i === $index;
67 }
68
69 if ($this->placeholderPresent) {
70 $values['placeholder'] = false === $index;
71 }
72
73 return $values;
74 }
75
76 /**
77 * Transforms a checkbox/radio button array to a single choice.
78 *
79 * The input value is an array with the choices as keys and true/false as
80 * values, depending on whether a given choice is selected. The output
81 * is the selected choice.
82 *
83 * @param array $values An array of values
84 *
85 * @return mixed A scalar value
86 *
87 * @throws TransformationFailedException If the given value is not an array,
88 * if the recuperation of the choices
89 * fails or if some choice can't be
90 * found.
91 */
92 public function reverseTransform($values)
93 {
94 if (!is_array($values)) {
95 throw new TransformationFailedException('Expected an array.');
96 }
97
98 try {
99 $choices = $this->choiceList->getChoices();
100 } catch (\Exception $e) {
101 throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e);
102 }
103
104 foreach ($values as $i => $selected) {
105 if ($selected) {
106 if (isset($choices[$i])) {
107 return $choices[$i] === '' ? null : $choices[$i];
108 } elseif ($this->placeholderPresent && 'placeholder' === $i) {
109 return null;
110 } else {
111 throw new TransformationFailedException(sprintf('The choice "%s" does not exist', $i));
112 }
113 }
114 }
115
116 return null;
117 }
118}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php
new file mode 100644
index 00000000..5a818558
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php
@@ -0,0 +1,62 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\DataTransformerInterface;
15use Symfony\Component\Form\Exception\TransformationFailedException;
16use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
17
18/**
19 * @author Bernhard Schussek <bschussek@gmail.com>
20 */
21class ChoiceToValueTransformer implements DataTransformerInterface
22{
23 private $choiceList;
24
25 /**
26 * Constructor.
27 *
28 * @param ChoiceListInterface $choiceList
29 */
30 public function __construct(ChoiceListInterface $choiceList)
31 {
32 $this->choiceList = $choiceList;
33 }
34
35 public function transform($choice)
36 {
37 return (string) current($this->choiceList->getValuesForChoices(array($choice)));
38 }
39
40 public function reverseTransform($value)
41 {
42 if (null !== $value && !is_scalar($value)) {
43 throw new TransformationFailedException('Expected a scalar.');
44 }
45
46 // These are now valid ChoiceList values, so we can return null
47 // right away
48 if ('' === $value || null === $value) {
49 return null;
50 }
51
52 $choices = $this->choiceList->getChoicesForValues(array($value));
53
54 if (1 !== count($choices)) {
55 throw new TransformationFailedException(sprintf('The choice "%s" does not exist or is not unique', $value));
56 }
57
58 $choice = current($choices);
59
60 return '' === $choice ? null : $choice;
61 }
62}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php
new file mode 100644
index 00000000..a13c0d4d
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php
@@ -0,0 +1,117 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
15use Symfony\Component\Form\DataTransformerInterface;
16use Symfony\Component\Form\Exception\TransformationFailedException;
17
18/**
19 * @author Bernhard Schussek <bschussek@gmail.com>
20 */
21class ChoicesToBooleanArrayTransformer implements DataTransformerInterface
22{
23 private $choiceList;
24
25 public function __construct(ChoiceListInterface $choiceList)
26 {
27 $this->choiceList = $choiceList;
28 }
29
30 /**
31 * Transforms an array of choices to a format appropriate for the nested
32 * checkboxes/radio buttons.
33 *
34 * The result is an array with the options as keys and true/false as values,
35 * depending on whether a given option is selected. If this field is rendered
36 * as select tag, the value is not modified.
37 *
38 * @param mixed $array An array
39 *
40 * @return mixed An array
41 *
42 * @throws TransformationFailedException If the given value is not an array
43 * or if the choices can not be retrieved.
44 */
45 public function transform($array)
46 {
47 if (null === $array) {
48 return array();
49 }
50
51 if (!is_array($array)) {
52 throw new TransformationFailedException('Expected an array.');
53 }
54
55 try {
56 $values = $this->choiceList->getValues();
57 } catch (\Exception $e) {
58 throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e);
59 }
60
61 $indexMap = array_flip($this->choiceList->getIndicesForChoices($array));
62
63 foreach ($values as $i => $value) {
64 $values[$i] = isset($indexMap[$i]);
65 }
66
67 return $values;
68 }
69
70 /**
71 * Transforms a checkbox/radio button array to an array of choices.
72 *
73 * The input value is an array with the choices as keys and true/false as
74 * values, depending on whether a given choice is selected. The output
75 * is an array with the selected choices.
76 *
77 * @param mixed $values An array
78 *
79 * @return mixed An array
80 *
81 * @throws TransformationFailedException If the given value is not an array,
82 * if the recuperation of the choices
83 * fails or if some choice can't be
84 * found.
85 */
86 public function reverseTransform($values)
87 {
88 if (!is_array($values)) {
89 throw new TransformationFailedException('Expected an array.');
90 }
91
92 try {
93 $choices = $this->choiceList->getChoices();
94 } catch (\Exception $e) {
95 throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e);
96 }
97
98 $result = array();
99 $unknown = array();
100
101 foreach ($values as $i => $selected) {
102 if ($selected) {
103 if (isset($choices[$i])) {
104 $result[] = $choices[$i];
105 } else {
106 $unknown[] = $i;
107 }
108 }
109 }
110
111 if (count($unknown) > 0) {
112 throw new TransformationFailedException(sprintf('The choices "%s" were not found', implode('", "', $unknown)));
113 }
114
115 return $result;
116 }
117}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php
new file mode 100644
index 00000000..4492865e
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php
@@ -0,0 +1,83 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\Exception\TransformationFailedException;
15
16use Symfony\Component\Form\DataTransformerInterface;
17use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
18
19/**
20 * @author Bernhard Schussek <bschussek@gmail.com>
21 */
22class ChoicesToValuesTransformer implements DataTransformerInterface
23{
24 private $choiceList;
25
26 /**
27 * Constructor.
28 *
29 * @param ChoiceListInterface $choiceList
30 */
31 public function __construct(ChoiceListInterface $choiceList)
32 {
33 $this->choiceList = $choiceList;
34 }
35
36 /**
37 * @param array $array
38 *
39 * @return array
40 *
41 * @throws TransformationFailedException If the given value is not an array.
42 */
43 public function transform($array)
44 {
45 if (null === $array) {
46 return array();
47 }
48
49 if (!is_array($array)) {
50 throw new TransformationFailedException('Expected an array.');
51 }
52
53 return $this->choiceList->getValuesForChoices($array);
54 }
55
56 /**
57 * @param array $array
58 *
59 * @return array
60 *
61 * @throws TransformationFailedException If the given value is not an array
62 * or if no matching choice could be
63 * found for some given value.
64 */
65 public function reverseTransform($array)
66 {
67 if (null === $array) {
68 return array();
69 }
70
71 if (!is_array($array)) {
72 throw new TransformationFailedException('Expected an array.');
73 }
74
75 $choices = $this->choiceList->getChoicesForValues($array);
76
77 if (count($choices) !== count($array)) {
78 throw new TransformationFailedException('Could not find all matching choices for the given values');
79 }
80
81 return $choices;
82 }
83}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.php
new file mode 100644
index 00000000..9cc185e1
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DataTransformerChain.php
@@ -0,0 +1,86 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\DataTransformerInterface;
15use Symfony\Component\Form\Exception\TransformationFailedException;
16
17/**
18 * Passes a value through multiple value transformers
19 *
20 * @author Bernhard Schussek <bschussek@gmail.com>
21 */
22class DataTransformerChain implements DataTransformerInterface
23{
24 /**
25 * The value transformers
26 * @var DataTransformerInterface[]
27 */
28 protected $transformers;
29
30 /**
31 * Uses the given value transformers to transform values
32 *
33 * @param array $transformers
34 */
35 public function __construct(array $transformers)
36 {
37 $this->transformers = $transformers;
38 }
39
40 /**
41 * Passes the value through the transform() method of all nested transformers
42 *
43 * The transformers receive the value in the same order as they were passed
44 * to the constructor. Each transformer receives the result of the previous
45 * transformer as input. The output of the last transformer is returned
46 * by this method.
47 *
48 * @param mixed $value The original value
49 *
50 * @return mixed The transformed value
51 *
52 * @throws TransformationFailedException
53 */
54 public function transform($value)
55 {
56 foreach ($this->transformers as $transformer) {
57 $value = $transformer->transform($value);
58 }
59
60 return $value;
61 }
62
63 /**
64 * Passes the value through the reverseTransform() method of all nested
65 * transformers
66 *
67 * The transformers receive the value in the reverse order as they were passed
68 * to the constructor. Each transformer receives the result of the previous
69 * transformer as input. The output of the last transformer is returned
70 * by this method.
71 *
72 * @param mixed $value The transformed value
73 *
74 * @return mixed The reverse-transformed value
75 *
76 * @throws TransformationFailedException
77 */
78 public function reverseTransform($value)
79 {
80 for ($i = count($this->transformers) - 1; $i >= 0; --$i) {
81 $value = $this->transformers[$i]->reverseTransform($value);
82 }
83
84 return $value;
85 }
86}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php
new file mode 100644
index 00000000..34af2820
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php
@@ -0,0 +1,184 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\Exception\TransformationFailedException;
15use Symfony\Component\Form\Exception\UnexpectedTypeException;
16
17/**
18 * Transforms between a normalized time and a localized time string/array.
19 *
20 * @author Bernhard Schussek <bschussek@gmail.com>
21 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
22 */
23class DateTimeToArrayTransformer extends BaseDateTimeTransformer
24{
25 private $pad;
26
27 private $fields;
28
29 /**
30 * Constructor.
31 *
32 * @param string $inputTimezone The input timezone
33 * @param string $outputTimezone The output timezone
34 * @param array $fields The date fields
35 * @param Boolean $pad Whether to use padding
36 *
37 * @throws UnexpectedTypeException if a timezone is not a string
38 */
39 public function __construct($inputTimezone = null, $outputTimezone = null, array $fields = null, $pad = false)
40 {
41 parent::__construct($inputTimezone, $outputTimezone);
42
43 if (null === $fields) {
44 $fields = array('year', 'month', 'day', 'hour', 'minute', 'second');
45 }
46
47 $this->fields = $fields;
48 $this->pad = (Boolean) $pad;
49 }
50
51 /**
52 * Transforms a normalized date into a localized date.
53 *
54 * @param \DateTime $dateTime Normalized date.
55 *
56 * @return array Localized date.
57 *
58 * @throws TransformationFailedException If the given value is not an
59 * instance of \DateTime or if the
60 * output timezone is not supported.
61 */
62 public function transform($dateTime)
63 {
64 if (null === $dateTime) {
65 return array_intersect_key(array(
66 'year' => '',
67 'month' => '',
68 'day' => '',
69 'hour' => '',
70 'minute' => '',
71 'second' => '',
72 ), array_flip($this->fields));
73 }
74
75 if (!$dateTime instanceof \DateTime) {
76 throw new TransformationFailedException('Expected a \DateTime.');
77 }
78
79 $dateTime = clone $dateTime;
80 if ($this->inputTimezone !== $this->outputTimezone) {
81 try {
82 $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
83 } catch (\Exception $e) {
84 throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
85 }
86 }
87
88 $result = array_intersect_key(array(
89 'year' => $dateTime->format('Y'),
90 'month' => $dateTime->format('m'),
91 'day' => $dateTime->format('d'),
92 'hour' => $dateTime->format('H'),
93 'minute' => $dateTime->format('i'),
94 'second' => $dateTime->format('s'),
95 ), array_flip($this->fields));
96
97 if (!$this->pad) {
98 foreach ($result as &$entry) {
99 // remove leading zeros
100 $entry = (string) (int) $entry;
101 }
102 }
103
104 return $result;
105 }
106
107 /**
108 * Transforms a localized date into a normalized date.
109 *
110 * @param array $value Localized date
111 *
112 * @return \DateTime Normalized date
113 *
114 * @throws TransformationFailedException If the given value is not an array,
115 * if the value could not be transformed
116 * or if the input timezone is not
117 * supported.
118 */
119 public function reverseTransform($value)
120 {
121 if (null === $value) {
122 return null;
123 }
124
125 if (!is_array($value)) {
126 throw new TransformationFailedException('Expected an array.');
127 }
128
129 if ('' === implode('', $value)) {
130 return null;
131 }
132
133 $emptyFields = array();
134
135 foreach ($this->fields as $field) {
136 if (!isset($value[$field])) {
137 $emptyFields[] = $field;
138 }
139 }
140
141 if (count($emptyFields) > 0) {
142 throw new TransformationFailedException(
143 sprintf('The fields "%s" should not be empty', implode('", "', $emptyFields)
144 ));
145 }
146
147 if (isset($value['month']) && !ctype_digit($value['month']) && !is_int($value['month'])) {
148 throw new TransformationFailedException('This month is invalid');
149 }
150
151 if (isset($value['day']) && !ctype_digit($value['day']) && !is_int($value['day'])) {
152 throw new TransformationFailedException('This day is invalid');
153 }
154
155 if (isset($value['year']) && !ctype_digit($value['year']) && !is_int($value['year'])) {
156 throw new TransformationFailedException('This year is invalid');
157 }
158
159 if (!empty($value['month']) && !empty($value['day']) && !empty($value['year']) && false === checkdate($value['month'], $value['day'], $value['year'])) {
160 throw new TransformationFailedException('This is an invalid date');
161 }
162
163 try {
164 $dateTime = new \DateTime(sprintf(
165 '%s-%s-%s %s:%s:%s %s',
166 empty($value['year']) ? '1970' : $value['year'],
167 empty($value['month']) ? '1' : $value['month'],
168 empty($value['day']) ? '1' : $value['day'],
169 empty($value['hour']) ? '0' : $value['hour'],
170 empty($value['minute']) ? '0' : $value['minute'],
171 empty($value['second']) ? '0' : $value['second'],
172 $this->outputTimezone
173 ));
174
175 if ($this->inputTimezone !== $this->outputTimezone) {
176 $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
177 }
178 } catch (\Exception $e) {
179 throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
180 }
181
182 return $dateTime;
183 }
184}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php
new file mode 100644
index 00000000..d755e485
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php
@@ -0,0 +1,169 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\Exception\TransformationFailedException;
15use Symfony\Component\Form\Exception\UnexpectedTypeException;
16
17/**
18 * Transforms between a normalized time and a localized time string
19 *
20 * @author Bernhard Schussek <bschussek@gmail.com>
21 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
22 */
23class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
24{
25 private $dateFormat;
26 private $timeFormat;
27 private $pattern;
28 private $calendar;
29
30 /**
31 * Constructor.
32 *
33 * @see BaseDateTimeTransformer::formats for available format options
34 *
35 * @param string $inputTimezone The name of the input timezone
36 * @param string $outputTimezone The name of the output timezone
37 * @param integer $dateFormat The date format
38 * @param integer $timeFormat The time format
39 * @param integer $calendar One of the \IntlDateFormatter calendar constants
40 * @param string $pattern A pattern to pass to \IntlDateFormatter
41 *
42 * @throws UnexpectedTypeException If a format is not supported or if a timezone is not a string
43 */
44 public function __construct($inputTimezone = null, $outputTimezone = null, $dateFormat = null, $timeFormat = null, $calendar = \IntlDateFormatter::GREGORIAN, $pattern = null)
45 {
46 parent::__construct($inputTimezone, $outputTimezone);
47
48 if (null === $dateFormat) {
49 $dateFormat = \IntlDateFormatter::MEDIUM;
50 }
51
52 if (null === $timeFormat) {
53 $timeFormat = \IntlDateFormatter::SHORT;
54 }
55
56 if (!in_array($dateFormat, self::$formats, true)) {
57 throw new UnexpectedTypeException($dateFormat, implode('", "', self::$formats));
58 }
59
60 if (!in_array($timeFormat, self::$formats, true)) {
61 throw new UnexpectedTypeException($timeFormat, implode('", "', self::$formats));
62 }
63
64 $this->dateFormat = $dateFormat;
65 $this->timeFormat = $timeFormat;
66 $this->calendar = $calendar;
67 $this->pattern = $pattern;
68 }
69
70 /**
71 * Transforms a normalized date into a localized date string/array.
72 *
73 * @param \DateTime $dateTime Normalized date.
74 *
75 * @return string|array Localized date string/array.
76 *
77 * @throws TransformationFailedException If the given value is not an instance
78 * of \DateTime or if the date could not
79 * be transformed.
80 */
81 public function transform($dateTime)
82 {
83 if (null === $dateTime) {
84 return '';
85 }
86
87 if (!$dateTime instanceof \DateTime) {
88 throw new TransformationFailedException('Expected a \DateTime.');
89 }
90
91 // convert time to UTC before passing it to the formatter
92 $dateTime = clone $dateTime;
93 if ('UTC' !== $this->inputTimezone) {
94 $dateTime->setTimezone(new \DateTimeZone('UTC'));
95 }
96
97 $value = $this->getIntlDateFormatter()->format((int) $dateTime->format('U'));
98
99 if (intl_get_error_code() != 0) {
100 throw new TransformationFailedException(intl_get_error_message());
101 }
102
103 return $value;
104 }
105
106 /**
107 * Transforms a localized date string/array into a normalized date.
108 *
109 * @param string|array $value Localized date string/array
110 *
111 * @return \DateTime Normalized date
112 *
113 * @throws TransformationFailedException if the given value is not a string,
114 * if the date could not be parsed or
115 * if the input timezone is not supported
116 */
117 public function reverseTransform($value)
118 {
119 if (!is_string($value)) {
120 throw new TransformationFailedException('Expected a string.');
121 }
122
123 if ('' === $value) {
124 return null;
125 }
126
127 $timestamp = $this->getIntlDateFormatter()->parse($value);
128
129 if (intl_get_error_code() != 0) {
130 throw new TransformationFailedException(intl_get_error_message());
131 }
132
133 try {
134 // read timestamp into DateTime object - the formatter delivers in UTC
135 $dateTime = new \DateTime(sprintf('@%s UTC', $timestamp));
136 } catch (\Exception $e) {
137 throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
138 }
139
140 if ('UTC' !== $this->inputTimezone) {
141 try {
142 $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
143 } catch (\Exception $e) {
144 throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
145 }
146 }
147
148 return $dateTime;
149 }
150
151 /**
152 * Returns a preconfigured IntlDateFormatter instance
153 *
154 * @return \IntlDateFormatter
155 */
156 protected function getIntlDateFormatter()
157 {
158 $dateFormat = $this->dateFormat;
159 $timeFormat = $this->timeFormat;
160 $timezone = $this->outputTimezone;
161 $calendar = $this->calendar;
162 $pattern = $this->pattern;
163
164 $intlDateFormatter = new \IntlDateFormatter(\Locale::getDefault(), $dateFormat, $timeFormat, $timezone, $calendar, $pattern);
165 $intlDateFormatter->setLenient(false);
166
167 return $intlDateFormatter;
168 }
169}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php
new file mode 100644
index 00000000..0eb07422
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php
@@ -0,0 +1,82 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\Exception\TransformationFailedException;
15
16/**
17 * @author Bernhard Schussek <bschussek@gmail.com>
18 */
19class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer
20{
21 /**
22 * {@inheritDoc}
23 */
24 public function transform($dateTime)
25 {
26 if (null === $dateTime) {
27 return '';
28 }
29
30 if (!$dateTime instanceof \DateTime) {
31 throw new TransformationFailedException('Expected a \DateTime.');
32 }
33
34 if ($this->inputTimezone !== $this->outputTimezone) {
35 $dateTime = clone $dateTime;
36 $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
37 }
38
39 return preg_replace('/\+00:00$/', 'Z', $dateTime->format('c'));
40 }
41
42 /**
43 * {@inheritDoc}
44 */
45 public function reverseTransform($rfc3339)
46 {
47 if (!is_string($rfc3339)) {
48 throw new TransformationFailedException('Expected a string.');
49 }
50
51 if ('' === $rfc3339) {
52 return null;
53 }
54
55 try {
56 $dateTime = new \DateTime($rfc3339);
57 } catch (\Exception $e) {
58 throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
59 }
60
61 if ($this->outputTimezone !== $this->inputTimezone) {
62 try {
63 $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
64 } catch (\Exception $e) {
65 throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
66 }
67 }
68
69 if (preg_match('/(\d{4})-(\d{2})-(\d{2})/', $rfc3339, $matches)) {
70 if (!checkdate($matches[2], $matches[3], $matches[1])) {
71 throw new TransformationFailedException(sprintf(
72 'The date "%s-%s-%s" is not a valid date.',
73 $matches[1],
74 $matches[2],
75 $matches[3]
76 ));
77 }
78 }
79
80 return $dateTime;
81 }
82}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php
new file mode 100644
index 00000000..131f45cb
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php
@@ -0,0 +1,231 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\Exception\TransformationFailedException;
15use Symfony\Component\Form\Exception\UnexpectedTypeException;
16
17/**
18 * Transforms between a date string and a DateTime object
19 *
20 * @author Bernhard Schussek <bschussek@gmail.com>
21 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
22 */
23class DateTimeToStringTransformer extends BaseDateTimeTransformer
24{
25 /**
26 * Format used for generating strings
27 * @var string
28 */
29 private $generateFormat;
30
31 /**
32 * Format used for parsing strings
33 *
34 * Different than the {@link $generateFormat} because formats for parsing
35 * support additional characters in PHP that are not supported for
36 * generating strings.
37 *
38 * @var string
39 */
40 private $parseFormat;
41
42 /**
43 * Whether to parse by appending a pipe "|" to the parse format.
44 *
45 * This only works as of PHP 5.3.7.
46 *
47 * @var Boolean
48 */
49 private $parseUsingPipe;
50
51 /**
52 * Transforms a \DateTime instance to a string
53 *
54 * @see \DateTime::format() for supported formats
55 *
56 * @param string $inputTimezone The name of the input timezone
57 * @param string $outputTimezone The name of the output timezone
58 * @param string $format The date format
59 * @param Boolean $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format
60 *
61 * @throws UnexpectedTypeException if a timezone is not a string
62 */
63 public function __construct($inputTimezone = null, $outputTimezone = null, $format = 'Y-m-d H:i:s', $parseUsingPipe = null)
64 {
65 parent::__construct($inputTimezone, $outputTimezone);
66
67 $this->generateFormat = $this->parseFormat = $format;
68
69 // The pipe in the parser pattern only works as of PHP 5.3.7
70 // See http://bugs.php.net/54316
71 $this->parseUsingPipe = null === $parseUsingPipe
72 ? version_compare(phpversion(), '5.3.7', '>=')
73 : $parseUsingPipe;
74
75 // See http://php.net/manual/en/datetime.createfromformat.php
76 // The character "|" in the format makes sure that the parts of a date
77 // that are *not* specified in the format are reset to the corresponding
78 // values from 1970-01-01 00:00:00 instead of the current time.
79 // Without "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 12:32:47",
80 // where the time corresponds to the current server time.
81 // With "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 00:00:00",
82 // which is at least deterministic and thus used here.
83 if ($this->parseUsingPipe && false === strpos($this->parseFormat, '|')) {
84 $this->parseFormat .= '|';
85 }
86 }
87
88 /**
89 * Transforms a DateTime object into a date string with the configured format
90 * and timezone
91 *
92 * @param \DateTime $value A DateTime object
93 *
94 * @return string A value as produced by PHP's date() function
95 *
96 * @throws TransformationFailedException If the given value is not a \DateTime
97 * instance or if the output timezone
98 * is not supported.
99 */
100 public function transform($value)
101 {
102 if (null === $value) {
103 return '';
104 }
105
106 if (!$value instanceof \DateTime) {
107 throw new TransformationFailedException('Expected a \DateTime.');
108 }
109
110 $value = clone $value;
111 try {
112 $value->setTimezone(new \DateTimeZone($this->outputTimezone));
113 } catch (\Exception $e) {
114 throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
115 }
116
117 return $value->format($this->generateFormat);
118 }
119
120 /**
121 * Transforms a date string in the configured timezone into a DateTime object.
122 *
123 * @param string $value A value as produced by PHP's date() function
124 *
125 * @return \DateTime An instance of \DateTime
126 *
127 * @throws TransformationFailedException If the given value is not a string,
128 * if the date could not be parsed or
129 * if the input timezone is not supported.
130 */
131 public function reverseTransform($value)
132 {
133 if (empty($value)) {
134 return null;
135 }
136
137 if (!is_string($value)) {
138 throw new TransformationFailedException('Expected a string.');
139 }
140
141 try {
142 $outputTz = new \DateTimeZone($this->outputTimezone);
143 $dateTime = \DateTime::createFromFormat($this->parseFormat, $value, $outputTz);
144
145 $lastErrors = \DateTime::getLastErrors();
146
147 if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) {
148 throw new TransformationFailedException(
149 implode(', ', array_merge(
150 array_values($lastErrors['warnings']),
151 array_values($lastErrors['errors'])
152 ))
153 );
154 }
155
156 // On PHP versions < 5.3.7 we need to emulate the pipe operator
157 // and reset parts not given in the format to their equivalent
158 // of the UNIX base timestamp.
159 if (!$this->parseUsingPipe) {
160 list($year, $month, $day, $hour, $minute, $second) = explode('-', $dateTime->format('Y-m-d-H-i-s'));
161
162 // Check which of the date parts are present in the pattern
163 preg_match(
164 '/(' .
165 '(?P<day>[djDl])|' .
166 '(?P<month>[FMmn])|' .
167 '(?P<year>[Yy])|' .
168 '(?P<hour>[ghGH])|' .
169 '(?P<minute>i)|' .
170 '(?P<second>s)|' .
171 '(?P<dayofyear>z)|' .
172 '(?P<timestamp>U)|' .
173 '[^djDlFMmnYyghGHiszU]' .
174 ')*/',
175 $this->parseFormat,
176 $matches
177 );
178
179 // preg_match() does not guarantee to set all indices, so
180 // set them unless given
181 $matches = array_merge(array(
182 'day' => false,
183 'month' => false,
184 'year' => false,
185 'hour' => false,
186 'minute' => false,
187 'second' => false,
188 'dayofyear' => false,
189 'timestamp' => false,
190 ), $matches);
191
192 // Reset all parts that don't exist in the format to the
193 // corresponding part of the UNIX base timestamp
194 if (!$matches['timestamp']) {
195 if (!$matches['dayofyear']) {
196 if (!$matches['day']) {
197 $day = 1;
198 }
199 if (!$matches['month']) {
200 $month = 1;
201 }
202 }
203 if (!$matches['year']) {
204 $year = 1970;
205 }
206 if (!$matches['hour']) {
207 $hour = 0;
208 }
209 if (!$matches['minute']) {
210 $minute = 0;
211 }
212 if (!$matches['second']) {
213 $second = 0;
214 }
215 $dateTime->setDate($year, $month, $day);
216 $dateTime->setTime($hour, $minute, $second);
217 }
218 }
219
220 if ($this->inputTimezone !== $this->outputTimezone) {
221 $dateTime->setTimeZone(new \DateTimeZone($this->inputTimezone));
222 }
223 } catch (TransformationFailedException $e) {
224 throw $e;
225 } catch (\Exception $e) {
226 throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
227 }
228
229 return $dateTime;
230 }
231}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php
new file mode 100644
index 00000000..d2ca6604
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php
@@ -0,0 +1,89 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\Exception\TransformationFailedException;
15
16/**
17 * Transforms between a timestamp and a DateTime object
18 *
19 * @author Bernhard Schussek <bschussek@gmail.com>
20 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
21 */
22class DateTimeToTimestampTransformer extends BaseDateTimeTransformer
23{
24 /**
25 * Transforms a DateTime object into a timestamp in the configured timezone.
26 *
27 * @param \DateTime $value A \DateTime object
28 *
29 * @return integer A timestamp
30 *
31 * @throws TransformationFailedException If the given value is not an instance
32 * of \DateTime or if the output
33 * timezone is not supported.
34 */
35 public function transform($value)
36 {
37 if (null === $value) {
38 return null;
39 }
40
41 if (!$value instanceof \DateTime) {
42 throw new TransformationFailedException('Expected a \DateTime.');
43 }
44
45 $value = clone $value;
46 try {
47 $value->setTimezone(new \DateTimeZone($this->outputTimezone));
48 } catch (\Exception $e) {
49 throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
50 }
51
52 return (int) $value->format('U');
53 }
54
55 /**
56 * Transforms a timestamp in the configured timezone into a DateTime object
57 *
58 * @param string $value A timestamp
59 *
60 * @return \DateTime A \DateTime object
61 *
62 * @throws TransformationFailedException If the given value is not a timestamp
63 * or if the given timestamp is invalid.
64 */
65 public function reverseTransform($value)
66 {
67 if (null === $value) {
68 return null;
69 }
70
71 if (!is_numeric($value)) {
72 throw new TransformationFailedException('Expected a numeric.');
73 }
74
75 try {
76 $dateTime = new \DateTime();
77 $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
78 $dateTime->setTimestamp($value);
79
80 if ($this->inputTimezone !== $this->outputTimezone) {
81 $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
82 }
83 } catch (\Exception $e) {
84 throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
85 }
86
87 return $dateTime;
88 }
89}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php
new file mode 100644
index 00000000..6bb48a9a
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php
@@ -0,0 +1,53 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\Exception\TransformationFailedException;
15
16/**
17 * Transforms between an integer and a localized number with grouping
18 * (each thousand) and comma separators.
19 *
20 * @author Bernhard Schussek <bschussek@gmail.com>
21 */
22class IntegerToLocalizedStringTransformer extends NumberToLocalizedStringTransformer
23{
24 /**
25 * {@inheritDoc}
26 */
27 public function reverseTransform($value)
28 {
29 if (!is_string($value)) {
30 throw new TransformationFailedException('Expected a string.');
31 }
32
33 if ('' === $value) {
34 return null;
35 }
36
37 if ('NaN' === $value) {
38 throw new TransformationFailedException('"NaN" is not a valid integer');
39 }
40
41 $formatter = $this->getNumberFormatter();
42 $value = $formatter->parse(
43 $value,
44 PHP_INT_SIZE == 8 ? $formatter::TYPE_INT64 : $formatter::TYPE_INT32
45 );
46
47 if (intl_is_failure($formatter->getErrorCode())) {
48 throw new TransformationFailedException($formatter->getErrorMessage());
49 }
50
51 return $value;
52 }
53}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php
new file mode 100644
index 00000000..5b8e9d96
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php
@@ -0,0 +1,90 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\Exception\TransformationFailedException;
15
16/**
17 * Transforms between a normalized format and a localized money string.
18 *
19 * @author Bernhard Schussek <bschussek@gmail.com>
20 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
21 */
22class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransformer
23{
24
25 private $divisor;
26
27 public function __construct($precision = null, $grouping = null, $roundingMode = null, $divisor = null)
28 {
29 if (null === $grouping) {
30 $grouping = true;
31 }
32
33 if (null === $precision) {
34 $precision = 2;
35 }
36
37 parent::__construct($precision, $grouping, $roundingMode);
38
39 if (null === $divisor) {
40 $divisor = 1;
41 }
42
43 $this->divisor = $divisor;
44 }
45
46 /**
47 * Transforms a normalized format into a localized money string.
48 *
49 * @param number $value Normalized number
50 *
51 * @return string Localized money string.
52 *
53 * @throws TransformationFailedException If the given value is not numeric or
54 * if the value can not be transformed.
55 */
56 public function transform($value)
57 {
58 if (null !== $value) {
59 if (!is_numeric($value)) {
60 throw new TransformationFailedException('Expected a numeric.');
61 }
62
63 $value /= $this->divisor;
64 }
65
66 return parent::transform($value);
67 }
68
69 /**
70 * Transforms a localized money string into a normalized format.
71 *
72 * @param string $value Localized money string
73 *
74 * @return number Normalized number
75 *
76 * @throws TransformationFailedException If the given value is not a string
77 * or if the value can not be transformed.
78 */
79 public function reverseTransform($value)
80 {
81 $value = parent::reverseTransform($value);
82
83 if (null !== $value) {
84 $value *= $this->divisor;
85 }
86
87 return $value;
88 }
89
90}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php
new file mode 100644
index 00000000..b0c59b3e
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php
@@ -0,0 +1,184 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\DataTransformerInterface;
15use Symfony\Component\Form\Exception\TransformationFailedException;
16
17/**
18 * Transforms between a number type and a localized number with grouping
19 * (each thousand) and comma separators.
20 *
21 * @author Bernhard Schussek <bschussek@gmail.com>
22 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
23 */
24class NumberToLocalizedStringTransformer implements DataTransformerInterface
25{
26 const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR;
27 const ROUND_DOWN = \NumberFormatter::ROUND_DOWN;
28 const ROUND_HALFDOWN = \NumberFormatter::ROUND_HALFDOWN;
29 const ROUND_HALFEVEN = \NumberFormatter::ROUND_HALFEVEN;
30 const ROUND_HALFUP = \NumberFormatter::ROUND_HALFUP;
31 const ROUND_UP = \NumberFormatter::ROUND_UP;
32 const ROUND_CEILING = \NumberFormatter::ROUND_CEILING;
33
34 protected $precision;
35
36 protected $grouping;
37
38 protected $roundingMode;
39
40 public function __construct($precision = null, $grouping = null, $roundingMode = null)
41 {
42 if (null === $grouping) {
43 $grouping = false;
44 }
45
46 if (null === $roundingMode) {
47 $roundingMode = self::ROUND_HALFUP;
48 }
49
50 $this->precision = $precision;
51 $this->grouping = $grouping;
52 $this->roundingMode = $roundingMode;
53 }
54
55 /**
56 * Transforms a number type into localized number.
57 *
58 * @param integer|float $value Number value.
59 *
60 * @return string Localized value.
61 *
62 * @throws TransformationFailedException If the given value is not numeric
63 * or if the value can not be transformed.
64 */
65 public function transform($value)
66 {
67 if (null === $value) {
68 return '';
69 }
70
71 if (!is_numeric($value)) {
72 throw new TransformationFailedException('Expected a numeric.');
73 }
74
75 $formatter = $this->getNumberFormatter();
76 $value = $formatter->format($value);
77
78 if (intl_is_failure($formatter->getErrorCode())) {
79 throw new TransformationFailedException($formatter->getErrorMessage());
80 }
81
82 // Convert fixed spaces to normal ones
83 $value = str_replace("\xc2\xa0", ' ', $value);
84
85 return $value;
86 }
87
88 /**
89 * Transforms a localized number into an integer or float
90 *
91 * @param string $value The localized value
92 *
93 * @return integer|float The numeric value
94 *
95 * @throws TransformationFailedException If the given value is not a string
96 * or if the value can not be transformed.
97 */
98 public function reverseTransform($value)
99 {
100 if (!is_string($value)) {
101 throw new TransformationFailedException('Expected a string.');
102 }
103
104 if ('' === $value) {
105 return null;
106 }
107
108 if ('NaN' === $value) {
109 throw new TransformationFailedException('"NaN" is not a valid number');
110 }
111
112 $position = 0;
113 $formatter = $this->getNumberFormatter();
114 $groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL);
115 $decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
116
117 if ('.' !== $decSep && (!$this->grouping || '.' !== $groupSep)) {
118 $value = str_replace('.', $decSep, $value);
119 }
120
121 if (',' !== $decSep && (!$this->grouping || ',' !== $groupSep)) {
122 $value = str_replace(',', $decSep, $value);
123 }
124
125 $result = $formatter->parse($value, \NumberFormatter::TYPE_DOUBLE, $position);
126
127 if (intl_is_failure($formatter->getErrorCode())) {
128 throw new TransformationFailedException($formatter->getErrorMessage());
129 }
130
131 if ($result >= PHP_INT_MAX || $result <= -PHP_INT_MAX) {
132 throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like');
133 }
134
135 if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value)) {
136 $strlen = function ($string) use ($encoding) {
137 return mb_strlen($string, $encoding);
138 };
139 $substr = function ($string, $offset, $length) use ($encoding) {
140 return mb_substr($string, $offset, $length, $encoding);
141 };
142 } else {
143 $strlen = 'strlen';
144 $substr = 'substr';
145 }
146
147 $length = $strlen($value);
148
149 // After parsing, position holds the index of the character where the
150 // parsing stopped
151 if ($position < $length) {
152 // Check if there are unrecognized characters at the end of the
153 // number (excluding whitespace characters)
154 $remainder = trim($substr($value, $position, $length), " \t\n\r\0\x0b\xc2\xa0");
155
156 if ('' !== $remainder) {
157 throw new TransformationFailedException(
158 sprintf('The number contains unrecognized characters: "%s"', $remainder)
159 );
160 }
161 }
162
163 return $result;
164 }
165
166 /**
167 * Returns a preconfigured \NumberFormatter instance
168 *
169 * @return \NumberFormatter
170 */
171 protected function getNumberFormatter()
172 {
173 $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL);
174
175 if (null !== $this->precision) {
176 $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->precision);
177 $formatter->setAttribute(\NumberFormatter::ROUNDING_MODE, $this->roundingMode);
178 }
179
180 $formatter->setAttribute(\NumberFormatter::GROUPING_USED, $this->grouping);
181
182 return $formatter;
183 }
184}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php
new file mode 100644
index 00000000..e099d436
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php
@@ -0,0 +1,149 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\DataTransformerInterface;
15use Symfony\Component\Form\Exception\TransformationFailedException;
16use Symfony\Component\Form\Exception\UnexpectedTypeException;
17
18/**
19 * Transforms between a normalized format (integer or float) and a percentage value.
20 *
21 * @author Bernhard Schussek <bschussek@gmail.com>
22 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
23 */
24class PercentToLocalizedStringTransformer implements DataTransformerInterface
25{
26 const FRACTIONAL = 'fractional';
27 const INTEGER = 'integer';
28
29 protected static $types = array(
30 self::FRACTIONAL,
31 self::INTEGER,
32 );
33
34 private $type;
35
36 private $precision;
37
38 /**
39 * Constructor.
40 *
41 * @see self::$types for a list of supported types
42 *
43 * @param integer $precision The precision
44 * @param string $type One of the supported types
45 *
46 * @throws UnexpectedTypeException if the given value of type is unknown
47 */
48 public function __construct($precision = null, $type = null)
49 {
50 if (null === $precision) {
51 $precision = 0;
52 }
53
54 if (null === $type) {
55 $type = self::FRACTIONAL;
56 }
57
58 if (!in_array($type, self::$types, true)) {
59 throw new UnexpectedTypeException($type, implode('", "', self::$types));
60 }
61
62 $this->type = $type;
63 $this->precision = $precision;
64 }
65
66 /**
67 * Transforms between a normalized format (integer or float) into a percentage value.
68 *
69 * @param number $value Normalized value
70 *
71 * @return number Percentage value
72 *
73 * @throws TransformationFailedException If the given value is not numeric or
74 * if the value could not be transformed.
75 */
76 public function transform($value)
77 {
78 if (null === $value) {
79 return '';
80 }
81
82 if (!is_numeric($value)) {
83 throw new TransformationFailedException('Expected a numeric.');
84 }
85
86 if (self::FRACTIONAL == $this->type) {
87 $value *= 100;
88 }
89
90 $formatter = $this->getNumberFormatter();
91 $value = $formatter->format($value);
92
93 if (intl_is_failure($formatter->getErrorCode())) {
94 throw new TransformationFailedException($formatter->getErrorMessage());
95 }
96
97 // replace the UTF-8 non break spaces
98 return $value;
99 }
100
101 /**
102 * Transforms between a percentage value into a normalized format (integer or float).
103 *
104 * @param number $value Percentage value.
105 *
106 * @return number Normalized value.
107 *
108 * @throws TransformationFailedException If the given value is not a string or
109 * if the value could not be transformed.
110 */
111 public function reverseTransform($value)
112 {
113 if (!is_string($value)) {
114 throw new TransformationFailedException('Expected a string.');
115 }
116
117 if ('' === $value) {
118 return null;
119 }
120
121 $formatter = $this->getNumberFormatter();
122 // replace normal spaces so that the formatter can read them
123 $value = $formatter->parse(str_replace(' ', ' ', $value));
124
125 if (intl_is_failure($formatter->getErrorCode())) {
126 throw new TransformationFailedException($formatter->getErrorMessage());
127 }
128
129 if (self::FRACTIONAL == $this->type) {
130 $value /= 100;
131 }
132
133 return $value;
134 }
135
136 /**
137 * Returns a preconfigured \NumberFormatter instance
138 *
139 * @return \NumberFormatter
140 */
141 protected function getNumberFormatter()
142 {
143 $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL);
144
145 $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->precision);
146
147 return $formatter;
148 }
149}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php
new file mode 100644
index 00000000..c34a0139
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php
@@ -0,0 +1,91 @@
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
12namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13
14use Symfony\Component\Form\DataTransformerInterface;
15use Symfony\Component\Form\Exception\TransformationFailedException;
16
17/**
18 * @author Bernhard Schussek <bschussek@gmail.com>
19 */
20class ValueToDuplicatesTransformer implements DataTransformerInterface
21{
22 private $keys;
23
24 public function __construct(array $keys)
25 {
26 $this->keys = $keys;
27 }
28
29 /**
30 * Duplicates the given value through the array.
31 *
32 * @param mixed $value The value
33 *
34 * @return array The array
35 */
36 public function transform($value)
37 {
38 $result = array();
39
40 foreach ($this->keys as $key) {
41 $result[$key] = $value;
42 }
43
44 return $result;
45 }
46
47 /**
48 * Extracts the duplicated value from an array.
49 *
50 * @param array $array
51 *
52 * @return mixed The value
53 *
54 * @throws TransformationFailedException If the given value is not an array or
55 * if the given array can not be transformed.
56 */
57 public function reverseTransform($array)
58 {
59 if (!is_array($array)) {
60 throw new TransformationFailedException('Expected an array.');
61 }
62
63 $result = current($array);
64 $emptyKeys = array();
65
66 foreach ($this->keys as $key) {
67 if (!empty($array[$key])) {
68 if ($array[$key] !== $result) {
69 throw new TransformationFailedException(
70 'All values in the array should be the same'
71 );
72 }
73 } else {
74 $emptyKeys[] = $key;
75 }
76 }
77
78 if (count($emptyKeys) > 0) {
79 if (count($emptyKeys) == count($this->keys)) {
80 // All keys empty
81 return null;
82 }
83
84 throw new TransformationFailedException(
85 sprintf('The keys "%s" should not be empty', implode('", "', $emptyKeys)
86 ));
87 }
88
89 return $result;
90 }
91}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php
new file mode 100644
index 00000000..1f62e060
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php
@@ -0,0 +1,62 @@
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
12namespace Symfony\Component\Form\Extension\Core\EventListener;
13
14use Symfony\Component\Form\FormEvents;
15use Symfony\Component\Form\FormEvent;
16use Symfony\Component\EventDispatcher\EventSubscriberInterface;
17use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
18
19/**
20 * Takes care of converting the input from a list of checkboxes to a correctly
21 * indexed array.
22 *
23 * @author Bernhard Schussek <bschussek@gmail.com>
24 */
25class FixCheckboxInputListener implements EventSubscriberInterface
26{
27 private $choiceList;
28
29 /**
30 * Constructor.
31 *
32 * @param ChoiceListInterface $choiceList
33 */
34 public function __construct(ChoiceListInterface $choiceList)
35 {
36 $this->choiceList = $choiceList;
37 }
38
39 public function preSubmit(FormEvent $event)
40 {
41 $values = (array) $event->getData();
42 $indices = $this->choiceList->getIndicesForValues($values);
43
44 $event->setData(count($indices) > 0 ? array_combine($indices, $values) : array());
45 }
46
47 /**
48 * Alias of {@link preSubmit()}.
49 *
50 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
51 * {@link preSubmit()} instead.
52 */
53 public function preBind(FormEvent $event)
54 {
55 $this->preSubmit($event);
56 }
57
58 public static function getSubscribedEvents()
59 {
60 return array(FormEvents::PRE_SUBMIT => 'preSubmit');
61 }
62}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php
new file mode 100644
index 00000000..bf03792f
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php
@@ -0,0 +1,66 @@
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
12namespace Symfony\Component\Form\Extension\Core\EventListener;
13
14use Symfony\Component\Form\FormEvents;
15use Symfony\Component\Form\FormEvent;
16use Symfony\Component\EventDispatcher\EventSubscriberInterface;
17use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
18
19/**
20 * Takes care of converting the input from a single radio button
21 * to an array.
22 *
23 * @author Bernhard Schussek <bschussek@gmail.com>
24 */
25class FixRadioInputListener implements EventSubscriberInterface
26{
27 private $choiceList;
28
29 private $placeholderPresent;
30
31 /**
32 * Constructor.
33 *
34 * @param ChoiceListInterface $choiceList
35 * @param Boolean $placeholderPresent
36 */
37 public function __construct(ChoiceListInterface $choiceList, $placeholderPresent)
38 {
39 $this->choiceList = $choiceList;
40 $this->placeholderPresent = $placeholderPresent;
41 }
42
43 public function preSubmit(FormEvent $event)
44 {
45 $value = $event->getData();
46 $index = current($this->choiceList->getIndicesForValues(array($value)));
47
48 $event->setData(false !== $index ? array($index => $value) : ($this->placeholderPresent ? array('placeholder' => '') : array())) ;
49 }
50
51 /**
52 * Alias of {@link preSubmit()}.
53 *
54 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
55 * {@link preSubmit()} instead.
56 */
57 public function preBind(FormEvent $event)
58 {
59 $this->preSubmit($event);
60 }
61
62 public static function getSubscribedEvents()
63 {
64 return array(FormEvents::PRE_SUBMIT => 'preSubmit');
65 }
66}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php
new file mode 100644
index 00000000..e25dacf2
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php
@@ -0,0 +1,56 @@
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
12namespace Symfony\Component\Form\Extension\Core\EventListener;
13
14use Symfony\Component\Form\FormEvents;
15use Symfony\Component\Form\FormEvent;
16use Symfony\Component\EventDispatcher\EventSubscriberInterface;
17
18/**
19 * Adds a protocol to a URL if it doesn't already have one.
20 *
21 * @author Bernhard Schussek <bschussek@gmail.com>
22 */
23class FixUrlProtocolListener implements EventSubscriberInterface
24{
25 private $defaultProtocol;
26
27 public function __construct($defaultProtocol = 'http')
28 {
29 $this->defaultProtocol = $defaultProtocol;
30 }
31
32 public function onSubmit(FormEvent $event)
33 {
34 $data = $event->getData();
35
36 if ($this->defaultProtocol && $data && !preg_match('~^\w+://~', $data)) {
37 $event->setData($this->defaultProtocol.'://'.$data);
38 }
39 }
40
41 /**
42 * Alias of {@link onSubmit()}.
43 *
44 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
45 * {@link onSubmit()} instead.
46 */
47 public function onBind(FormEvent $event)
48 {
49 $this->onSubmit($event);
50 }
51
52 public static function getSubscribedEvents()
53 {
54 return array(FormEvents::SUBMIT => 'onSubmit');
55 }
56}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php
new file mode 100644
index 00000000..4d0bdfaa
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php
@@ -0,0 +1,137 @@
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
12namespace Symfony\Component\Form\Extension\Core\EventListener;
13
14use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15use Symfony\Component\Form\FormEvents;
16use Symfony\Component\Form\FormEvent;
17use Symfony\Component\Form\Exception\UnexpectedTypeException;
18
19/**
20 * @author Bernhard Schussek <bschussek@gmail.com>
21 */
22class MergeCollectionListener implements EventSubscriberInterface
23{
24 /**
25 * Whether elements may be added to the collection
26 * @var Boolean
27 */
28 private $allowAdd;
29
30 /**
31 * Whether elements may be removed from the collection
32 * @var Boolean
33 */
34 private $allowDelete;
35
36 /**
37 * Creates a new listener.
38 *
39 * @param Boolean $allowAdd Whether values might be added to the
40 * collection.
41 * @param Boolean $allowDelete Whether values might be removed from the
42 * collection.
43 */
44 public function __construct($allowAdd = false, $allowDelete = false)
45 {
46 $this->allowAdd = $allowAdd;
47 $this->allowDelete = $allowDelete;
48 }
49
50 public static function getSubscribedEvents()
51 {
52 return array(
53 FormEvents::SUBMIT => 'onSubmit',
54 );
55 }
56
57 public function onSubmit(FormEvent $event)
58 {
59 $dataToMergeInto = $event->getForm()->getNormData();
60 $data = $event->getData();
61
62 if (null === $data) {
63 $data = array();
64 }
65
66 if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) {
67 throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
68 }
69
70 if (null !== $dataToMergeInto && !is_array($dataToMergeInto) && !($dataToMergeInto instanceof \Traversable && $dataToMergeInto instanceof \ArrayAccess)) {
71 throw new UnexpectedTypeException($dataToMergeInto, 'array or (\Traversable and \ArrayAccess)');
72 }
73
74 // If we are not allowed to change anything, return immediately
75 if ((!$this->allowAdd && !$this->allowDelete) || $data === $dataToMergeInto) {
76 $event->setData($dataToMergeInto);
77
78 return;
79 }
80
81 if (!$dataToMergeInto) {
82 // No original data was set. Set it if allowed
83 if ($this->allowAdd) {
84 $dataToMergeInto = $data;
85 }
86 } else {
87 // Calculate delta
88 $itemsToAdd = is_object($data) ? clone $data : $data;
89 $itemsToDelete = array();
90
91 foreach ($dataToMergeInto as $beforeKey => $beforeItem) {
92 foreach ($data as $afterKey => $afterItem) {
93 if ($afterItem === $beforeItem) {
94 // Item found, next original item
95 unset($itemsToAdd[$afterKey]);
96 continue 2;
97 }
98 }
99
100 // Item not found, remember for deletion
101 $itemsToDelete[] = $beforeKey;
102 }
103
104 // Remove deleted items before adding to free keys that are to be
105 // replaced
106 if ($this->allowDelete) {
107 foreach ($itemsToDelete as $key) {
108 unset($dataToMergeInto[$key]);
109 }
110 }
111
112 // Add remaining items
113 if ($this->allowAdd) {
114 foreach ($itemsToAdd as $key => $item) {
115 if (!isset($dataToMergeInto[$key])) {
116 $dataToMergeInto[$key] = $item;
117 } else {
118 $dataToMergeInto[] = $item;
119 }
120 }
121 }
122 }
123
124 $event->setData($dataToMergeInto);
125 }
126
127 /**
128 * Alias of {@link onSubmit()}.
129 *
130 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
131 * {@link onSubmit()} instead.
132 */
133 public function onBind(FormEvent $event)
134 {
135 $this->onSubmit($event);
136 }
137}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php
new file mode 100644
index 00000000..f1c39db2
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php
@@ -0,0 +1,173 @@
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
12namespace Symfony\Component\Form\Extension\Core\EventListener;
13
14use Symfony\Component\Form\FormEvents;
15use Symfony\Component\Form\FormEvent;
16use Symfony\Component\Form\Exception\UnexpectedTypeException;
17use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18
19/**
20 * Resize a collection form element based on the data sent from the client.
21 *
22 * @author Bernhard Schussek <bschussek@gmail.com>
23 */
24class ResizeFormListener implements EventSubscriberInterface
25{
26 /**
27 * @var string
28 */
29 protected $type;
30
31 /**
32 * @var array
33 */
34 protected $options;
35
36 /**
37 * Whether children could be added to the group
38 * @var Boolean
39 */
40 protected $allowAdd;
41
42 /**
43 * Whether children could be removed from the group
44 * @var Boolean
45 */
46 protected $allowDelete;
47
48 public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false)
49 {
50 $this->type = $type;
51 $this->allowAdd = $allowAdd;
52 $this->allowDelete = $allowDelete;
53 $this->options = $options;
54 }
55
56 public static function getSubscribedEvents()
57 {
58 return array(
59 FormEvents::PRE_SET_DATA => 'preSetData',
60 FormEvents::PRE_SUBMIT => 'preSubmit',
61 // (MergeCollectionListener, MergeDoctrineCollectionListener)
62 FormEvents::SUBMIT => array('onSubmit', 50),
63 );
64 }
65
66 public function preSetData(FormEvent $event)
67 {
68 $form = $event->getForm();
69 $data = $event->getData();
70
71 if (null === $data) {
72 $data = array();
73 }
74
75 if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) {
76 throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
77 }
78
79 // First remove all rows
80 foreach ($form as $name => $child) {
81 $form->remove($name);
82 }
83
84 // Then add all rows again in the correct order
85 foreach ($data as $name => $value) {
86 $form->add($name, $this->type, array_replace(array(
87 'property_path' => '['.$name.']',
88 ), $this->options));
89 }
90 }
91
92 public function preSubmit(FormEvent $event)
93 {
94 $form = $event->getForm();
95 $data = $event->getData();
96
97 if (null === $data || '' === $data) {
98 $data = array();
99 }
100
101 if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) {
102 throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
103 }
104
105 // Remove all empty rows
106 if ($this->allowDelete) {
107 foreach ($form as $name => $child) {
108 if (!isset($data[$name])) {
109 $form->remove($name);
110 }
111 }
112 }
113
114 // Add all additional rows
115 if ($this->allowAdd) {
116 foreach ($data as $name => $value) {
117 if (!$form->has($name)) {
118 $form->add($name, $this->type, array_replace(array(
119 'property_path' => '['.$name.']',
120 ), $this->options));
121 }
122 }
123 }
124 }
125
126 public function onSubmit(FormEvent $event)
127 {
128 $form = $event->getForm();
129 $data = $event->getData();
130
131 if (null === $data) {
132 $data = array();
133 }
134
135 if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) {
136 throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
137 }
138
139 // The data mapper only adds, but does not remove items, so do this
140 // here
141 if ($this->allowDelete) {
142 foreach ($data as $name => $child) {
143 if (!$form->has($name)) {
144 unset($data[$name]);
145 }
146 }
147 }
148
149 $event->setData($data);
150 }
151
152 /**
153 * Alias of {@link preSubmit()}.
154 *
155 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
156 * {@link preSubmit()} instead.
157 */
158 public function preBind(FormEvent $event)
159 {
160 $this->preSubmit($event);
161 }
162
163 /**
164 * Alias of {@link onSubmit()}.
165 *
166 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
167 * {@link onSubmit()} instead.
168 */
169 public function onBind(FormEvent $event)
170 {
171 $this->onSubmit($event);
172 }
173}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/TrimListener.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/TrimListener.php
new file mode 100644
index 00000000..cbe6e0ab
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/EventListener/TrimListener.php
@@ -0,0 +1,55 @@
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
12namespace Symfony\Component\Form\Extension\Core\EventListener;
13
14use Symfony\Component\Form\FormEvents;
15use Symfony\Component\Form\FormEvent;
16use Symfony\Component\EventDispatcher\EventSubscriberInterface;
17
18/**
19 * Trims string data
20 *
21 * @author Bernhard Schussek <bschussek@gmail.com>
22 */
23class TrimListener implements EventSubscriberInterface
24{
25 public function preSubmit(FormEvent $event)
26 {
27 $data = $event->getData();
28
29 if (!is_string($data)) {
30 return;
31 }
32
33 if (null !== $result = @preg_replace('/^[\pZ\p{Cc}]+|[\pZ\p{Cc}]+$/u', '', $data)) {
34 $event->setData($result);
35 } else {
36 $event->setData(trim($data));
37 }
38 }
39
40 /**
41 * Alias of {@link preSubmit()}.
42 *
43 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
44 * {@link preSubmit()} instead.
45 */
46 public function preBind(FormEvent $event)
47 {
48 $this->preSubmit($event);
49 }
50
51 public static function getSubscribedEvents()
52 {
53 return array(FormEvents::PRE_SUBMIT => 'preSubmit');
54 }
55}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BaseType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BaseType.php
new file mode 100644
index 00000000..79333a67
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BaseType.php
@@ -0,0 +1,121 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormBuilderInterface;
16use Symfony\Component\Form\FormInterface;
17use Symfony\Component\Form\FormView;
18use Symfony\Component\OptionsResolver\OptionsResolverInterface;
19
20/**
21 * Encapsulates common logic of {@link FormType} and {@link ButtonType}.
22 *
23 * This type does not appear in the form's type inheritance chain and as such
24 * cannot be extended (via {@link FormTypeExtension}s) nor themed.
25 *
26 * @author Bernhard Schussek <bschussek@gmail.com>
27 */
28abstract class BaseType extends AbstractType
29{
30 /**
31 * {@inheritdoc}
32 */
33 public function buildForm(FormBuilderInterface $builder, array $options)
34 {
35 $builder->setDisabled($options['disabled']);
36 }
37
38 /**
39 * {@inheritdoc}
40 */
41 public function buildView(FormView $view, FormInterface $form, array $options)
42 {
43 $name = $form->getName();
44 $blockName = $options['block_name'] ?: $form->getName();
45 $translationDomain = $options['translation_domain'];
46
47 if ($view->parent) {
48 if ('' !== ($parentFullName = $view->parent->vars['full_name'])) {
49 $id = sprintf('%s_%s', $view->parent->vars['id'], $name);
50 $fullName = sprintf('%s[%s]', $parentFullName, $name);
51 $uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName);
52 } else {
53 $id = $name;
54 $fullName = $name;
55 $uniqueBlockPrefix = '_'.$blockName;
56 }
57
58 if (!$translationDomain) {
59 $translationDomain = $view->parent->vars['translation_domain'];
60 }
61 } else {
62 $id = $name;
63 $fullName = $name;
64 $uniqueBlockPrefix = '_'.$blockName;
65
66 // Strip leading underscores and digits. These are allowed in
67 // form names, but not in HTML4 ID attributes.
68 // http://www.w3.org/TR/html401/struct/global.html#adef-id
69 $id = ltrim($id, '_0123456789');
70 }
71
72 $blockPrefixes = array();
73 for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) {
74 array_unshift($blockPrefixes, $type->getName());
75 }
76 $blockPrefixes[] = $uniqueBlockPrefix;
77
78 if (!$translationDomain) {
79 $translationDomain = 'messages';
80 }
81
82 $view->vars = array_replace($view->vars, array(
83 'form' => $view,
84 'id' => $id,
85 'name' => $name,
86 'full_name' => $fullName,
87 'disabled' => $form->isDisabled(),
88 'label' => $options['label'],
89 'multipart' => false,
90 'attr' => $options['attr'],
91 'block_prefixes' => $blockPrefixes,
92 'unique_block_prefix' => $uniqueBlockPrefix,
93 'translation_domain' => $translationDomain,
94 // Using the block name here speeds up performance in collection
95 // forms, where each entry has the same full block name.
96 // Including the type is important too, because if rows of a
97 // collection form have different types (dynamically), they should
98 // be rendered differently.
99 // https://github.com/symfony/symfony/issues/5038
100 'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(),
101 ));
102 }
103
104 /**
105 * {@inheritdoc}
106 */
107 public function setDefaultOptions(OptionsResolverInterface $resolver)
108 {
109 $resolver->setDefaults(array(
110 'block_name' => null,
111 'disabled' => false,
112 'label' => null,
113 'attr' => array(),
114 'translation_domain' => null,
115 ));
116
117 $resolver->setAllowedTypes(array(
118 'attr' => 'array',
119 ));
120 }
121}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BirthdayType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BirthdayType.php
new file mode 100644
index 00000000..5314c140
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/BirthdayType.php
@@ -0,0 +1,44 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\OptionsResolver\OptionsResolverInterface;
16
17class BirthdayType extends AbstractType
18{
19 /**
20 * {@inheritdoc}
21 */
22 public function setDefaultOptions(OptionsResolverInterface $resolver)
23 {
24 $resolver->setDefaults(array(
25 'years' => range(date('Y') - 120, date('Y')),
26 ));
27 }
28
29 /**
30 * {@inheritdoc}
31 */
32 public function getParent()
33 {
34 return 'date';
35 }
36
37 /**
38 * {@inheritdoc}
39 */
40 public function getName()
41 {
42 return 'birthday';
43 }
44}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ButtonType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ButtonType.php
new file mode 100644
index 00000000..3569963b
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ButtonType.php
@@ -0,0 +1,38 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\ButtonTypeInterface;
15
16/**
17 * A form button.
18 *
19 * @author Bernhard Schussek <bschussek@gmail.com>
20 */
21class ButtonType extends BaseType implements ButtonTypeInterface
22{
23 /**
24 * {@inheritdoc}
25 */
26 public function getParent()
27 {
28 return null;
29 }
30
31 /**
32 * {@inheritdoc}
33 */
34 public function getName()
35 {
36 return 'button';
37 }
38}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CheckboxType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CheckboxType.php
new file mode 100644
index 00000000..214e581a
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CheckboxType.php
@@ -0,0 +1,67 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormBuilderInterface;
16use Symfony\Component\Form\FormInterface;
17use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransformer;
18use Symfony\Component\Form\FormView;
19use Symfony\Component\OptionsResolver\OptionsResolverInterface;
20
21class CheckboxType extends AbstractType
22{
23 /**
24 * {@inheritdoc}
25 */
26 public function buildForm(FormBuilderInterface $builder, array $options)
27 {
28 $builder
29 ->addViewTransformer(new BooleanToStringTransformer($options['value']))
30 ;
31 }
32
33 /**
34 * {@inheritdoc}
35 */
36 public function buildView(FormView $view, FormInterface $form, array $options)
37 {
38 $view->vars = array_replace($view->vars, array(
39 'value' => $options['value'],
40 'checked' => null !== $form->getViewData(),
41 ));
42 }
43
44 /**
45 * {@inheritdoc}
46 */
47 public function setDefaultOptions(OptionsResolverInterface $resolver)
48 {
49 $emptyData = function (FormInterface $form, $clientData) {
50 return $clientData;
51 };
52
53 $resolver->setDefaults(array(
54 'value' => '1',
55 'empty_data' => $emptyData,
56 'compound' => false,
57 ));
58 }
59
60 /**
61 * {@inheritdoc}
62 */
63 public function getName()
64 {
65 return 'checkbox';
66 }
67}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php
new file mode 100644
index 00000000..9a3fdef1
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php
@@ -0,0 +1,274 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\Extension\Core\View\ChoiceView;
16use Symfony\Component\Form\FormBuilderInterface;
17use Symfony\Component\Form\FormInterface;
18use Symfony\Component\Form\FormView;
19use Symfony\Component\Form\Exception\LogicException;
20use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;
21use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener;
22use Symfony\Component\Form\Extension\Core\EventListener\FixCheckboxInputListener;
23use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener;
24use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer;
25use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToBooleanArrayTransformer;
26use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer;
27use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToBooleanArrayTransformer;
28use Symfony\Component\OptionsResolver\Options;
29use Symfony\Component\OptionsResolver\OptionsResolverInterface;
30
31class ChoiceType extends AbstractType
32{
33 /**
34 * Caches created choice lists.
35 * @var array
36 */
37 private $choiceListCache = array();
38
39 /**
40 * {@inheritdoc}
41 */
42 public function buildForm(FormBuilderInterface $builder, array $options)
43 {
44 if (!$options['choice_list'] && !is_array($options['choices']) && !$options['choices'] instanceof \Traversable) {
45 throw new LogicException('Either the option "choices" or "choice_list" must be set.');
46 }
47
48 if ($options['expanded']) {
49 // Initialize all choices before doing the index check below.
50 // This helps in cases where index checks are optimized for non
51 // initialized choice lists. For example, when using an SQL driver,
52 // the index check would read in one SQL query and the initialization
53 // requires another SQL query. When the initialization is done first,
54 // one SQL query is sufficient.
55 $preferredViews = $options['choice_list']->getPreferredViews();
56 $remainingViews = $options['choice_list']->getRemainingViews();
57
58 // Check if the choices already contain the empty value
59 // Only add the empty value option if this is not the case
60 if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getIndicesForValues(array('')))) {
61 $placeholderView = new ChoiceView(null, '', $options['empty_value']);
62
63 // "placeholder" is a reserved index
64 // see also ChoiceListInterface::getIndicesForChoices()
65 $this->addSubForms($builder, array('placeholder' => $placeholderView), $options);
66 }
67
68 $this->addSubForms($builder, $preferredViews, $options);
69 $this->addSubForms($builder, $remainingViews, $options);
70
71 if ($options['multiple']) {
72 $builder->addViewTransformer(new ChoicesToBooleanArrayTransformer($options['choice_list']));
73 $builder->addEventSubscriber(new FixCheckboxInputListener($options['choice_list']), 10);
74 } else {
75 $builder->addViewTransformer(new ChoiceToBooleanArrayTransformer($options['choice_list'], $builder->has('placeholder')));
76 $builder->addEventSubscriber(new FixRadioInputListener($options['choice_list'], $builder->has('placeholder')), 10);
77 }
78 } else {
79 if ($options['multiple']) {
80 $builder->addViewTransformer(new ChoicesToValuesTransformer($options['choice_list']));
81 } else {
82 $builder->addViewTransformer(new ChoiceToValueTransformer($options['choice_list']));
83 }
84 }
85
86 if ($options['multiple'] && $options['by_reference']) {
87 // Make sure the collection created during the client->norm
88 // transformation is merged back into the original collection
89 $builder->addEventSubscriber(new MergeCollectionListener(true, true));
90 }
91 }
92
93 /**
94 * {@inheritdoc}
95 */
96 public function buildView(FormView $view, FormInterface $form, array $options)
97 {
98 $view->vars = array_replace($view->vars, array(
99 'multiple' => $options['multiple'],
100 'expanded' => $options['expanded'],
101 'preferred_choices' => $options['choice_list']->getPreferredViews(),
102 'choices' => $options['choice_list']->getRemainingViews(),
103 'separator' => '-------------------',
104 'empty_value' => null,
105 ));
106
107 // The decision, whether a choice is selected, is potentially done
108 // thousand of times during the rendering of a template. Provide a
109 // closure here that is optimized for the value of the form, to
110 // avoid making the type check inside the closure.
111 if ($options['multiple']) {
112 $view->vars['is_selected'] = function ($choice, array $values) {
113 return false !== array_search($choice, $values, true);
114 };
115 } else {
116 $view->vars['is_selected'] = function ($choice, $value) {
117 return $choice === $value;
118 };
119 }
120
121 // Check if the choices already contain the empty value
122 // Only add the empty value option if this is not the case
123 if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getIndicesForValues(array('')))) {
124 $view->vars['empty_value'] = $options['empty_value'];
125 }
126
127 if ($options['multiple'] && !$options['expanded']) {
128 // Add "[]" to the name in case a select tag with multiple options is
129 // displayed. Otherwise only one of the selected options is sent in the
130 // POST request.
131 $view->vars['full_name'] = $view->vars['full_name'].'[]';
132 }
133 }
134
135 /**
136 * {@inheritdoc}
137 */
138 public function finishView(FormView $view, FormInterface $form, array $options)
139 {
140 if ($options['expanded']) {
141 // Radio buttons should have the same name as the parent
142 $childName = $view->vars['full_name'];
143
144 // Checkboxes should append "[]" to allow multiple selection
145 if ($options['multiple']) {
146 $childName .= '[]';
147 }
148
149 foreach ($view as $childView) {
150 $childView->vars['full_name'] = $childName;
151 }
152 }
153 }
154
155 /**
156 * {@inheritdoc}
157 */
158 public function setDefaultOptions(OptionsResolverInterface $resolver)
159 {
160 $choiceListCache =& $this->choiceListCache;
161
162 $choiceList = function (Options $options) use (&$choiceListCache) {
163 // Harden against NULL values (like in EntityType and ModelType)
164 $choices = null !== $options['choices'] ? $options['choices'] : array();
165
166 // Reuse existing choice lists in order to increase performance
167 $hash = md5(json_encode(array($choices, $options['preferred_choices'])));
168
169 if (!isset($choiceListCache[$hash])) {
170 $choiceListCache[$hash] = new SimpleChoiceList($choices, $options['preferred_choices']);
171 }
172
173 return $choiceListCache[$hash];
174 };
175
176 $emptyData = function (Options $options) {
177 if ($options['multiple'] || $options['expanded']) {
178 return array();
179 }
180
181 return '';
182 };
183
184 $emptyValue = function (Options $options) {
185 return $options['required'] ? null : '';
186 };
187
188 $emptyValueNormalizer = function (Options $options, $emptyValue) {
189 if ($options['multiple']) {
190 // never use an empty value for this case
191 return null;
192 } elseif (false === $emptyValue) {
193 // an empty value should be added but the user decided otherwise
194 return null;
195 } elseif ($options['expanded'] && '' === $emptyValue) {
196 // never use an empty label for radio buttons
197 return 'None';
198 }
199
200 // empty value has been set explicitly
201 return $emptyValue;
202 };
203
204 $compound = function (Options $options) {
205 return $options['expanded'];
206 };
207
208 $resolver->setDefaults(array(
209 'multiple' => false,
210 'expanded' => false,
211 'choice_list' => $choiceList,
212 'choices' => array(),
213 'preferred_choices' => array(),
214 'empty_data' => $emptyData,
215 'empty_value' => $emptyValue,
216 'error_bubbling' => false,
217 'compound' => $compound,
218 // The view data is always a string, even if the "data" option
219 // is manually set to an object.
220 // See https://github.com/symfony/symfony/pull/5582
221 'data_class' => null,
222 ));
223
224 $resolver->setNormalizers(array(
225 'empty_value' => $emptyValueNormalizer,
226 ));
227
228 $resolver->setAllowedTypes(array(
229 'choice_list' => array('null', 'Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface'),
230 ));
231 }
232
233 /**
234 * {@inheritdoc}
235 */
236 public function getName()
237 {
238 return 'choice';
239 }
240
241 /**
242 * Adds the sub fields for an expanded choice field.
243 *
244 * @param FormBuilderInterface $builder The form builder.
245 * @param array $choiceViews The choice view objects.
246 * @param array $options The build options.
247 */
248 private function addSubForms(FormBuilderInterface $builder, array $choiceViews, array $options)
249 {
250 foreach ($choiceViews as $i => $choiceView) {
251 if (is_array($choiceView)) {
252 // Flatten groups
253 $this->addSubForms($builder, $choiceView, $options);
254 } else {
255 $choiceOpts = array(
256 'value' => $choiceView->value,
257 'label' => $choiceView->label,
258 'translation_domain' => $options['translation_domain'],
259 );
260
261 if ($options['multiple']) {
262 $choiceType = 'checkbox';
263 // The user can check 0 or more checkboxes. If required
264 // is true, he is required to check all of them.
265 $choiceOpts['required'] = false;
266 } else {
267 $choiceType = 'radio';
268 }
269
270 $builder->add($i, $choiceType, $choiceOpts);
271 }
272 }
273 }
274}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CollectionType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CollectionType.php
new file mode 100644
index 00000000..0cb3af1b
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CollectionType.php
@@ -0,0 +1,103 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormBuilderInterface;
16use Symfony\Component\Form\FormView;
17use Symfony\Component\Form\FormInterface;
18use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener;
19use Symfony\Component\OptionsResolver\Options;
20use Symfony\Component\OptionsResolver\OptionsResolverInterface;
21
22class CollectionType extends AbstractType
23{
24 /**
25 * {@inheritdoc}
26 */
27 public function buildForm(FormBuilderInterface $builder, array $options)
28 {
29 if ($options['allow_add'] && $options['prototype']) {
30 $prototype = $builder->create($options['prototype_name'], $options['type'], array_replace(array(
31 'label' => $options['prototype_name'].'label__',
32 ), $options['options']));
33 $builder->setAttribute('prototype', $prototype->getForm());
34 }
35
36 $resizeListener = new ResizeFormListener(
37 $options['type'],
38 $options['options'],
39 $options['allow_add'],
40 $options['allow_delete']
41 );
42
43 $builder->addEventSubscriber($resizeListener);
44 }
45
46 /**
47 * {@inheritdoc}
48 */
49 public function buildView(FormView $view, FormInterface $form, array $options)
50 {
51 $view->vars = array_replace($view->vars, array(
52 'allow_add' => $options['allow_add'],
53 'allow_delete' => $options['allow_delete'],
54 ));
55
56 if ($form->getConfig()->hasAttribute('prototype')) {
57 $view->vars['prototype'] = $form->getConfig()->getAttribute('prototype')->createView($view);
58 }
59 }
60
61 /**
62 * {@inheritdoc}
63 */
64 public function finishView(FormView $view, FormInterface $form, array $options)
65 {
66 if ($form->getConfig()->hasAttribute('prototype') && $view->vars['prototype']->vars['multipart']) {
67 $view->vars['multipart'] = true;
68 }
69 }
70
71 /**
72 * {@inheritdoc}
73 */
74 public function setDefaultOptions(OptionsResolverInterface $resolver)
75 {
76 $optionsNormalizer = function (Options $options, $value) {
77 $value['block_name'] = 'entry';
78
79 return $value;
80 };
81
82 $resolver->setDefaults(array(
83 'allow_add' => false,
84 'allow_delete' => false,
85 'prototype' => true,
86 'prototype_name' => '__name__',
87 'type' => 'text',
88 'options' => array(),
89 ));
90
91 $resolver->setNormalizers(array(
92 'options' => $optionsNormalizer,
93 ));
94 }
95
96 /**
97 * {@inheritdoc}
98 */
99 public function getName()
100 {
101 return 'collection';
102 }
103}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CountryType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CountryType.php
new file mode 100644
index 00000000..3482ba66
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CountryType.php
@@ -0,0 +1,45 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Intl\Intl;
16use Symfony\Component\OptionsResolver\OptionsResolverInterface;
17
18class CountryType extends AbstractType
19{
20 /**
21 * {@inheritdoc}
22 */
23 public function setDefaultOptions(OptionsResolverInterface $resolver)
24 {
25 $resolver->setDefaults(array(
26 'choices' => Intl::getRegionBundle()->getCountryNames(),
27 ));
28 }
29
30 /**
31 * {@inheritdoc}
32 */
33 public function getParent()
34 {
35 return 'choice';
36 }
37
38 /**
39 * {@inheritdoc}
40 */
41 public function getName()
42 {
43 return 'country';
44 }
45}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php
new file mode 100644
index 00000000..3a925e3a
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php
@@ -0,0 +1,45 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Intl\Intl;
16use Symfony\Component\OptionsResolver\OptionsResolverInterface;
17
18class CurrencyType extends AbstractType
19{
20 /**
21 * {@inheritdoc}
22 */
23 public function setDefaultOptions(OptionsResolverInterface $resolver)
24 {
25 $resolver->setDefaults(array(
26 'choices' => Intl::getCurrencyBundle()->getCurrencyNames(),
27 ));
28 }
29
30 /**
31 * {@inheritdoc}
32 */
33 public function getParent()
34 {
35 return 'choice';
36 }
37
38 /**
39 * {@inheritdoc}
40 */
41 public function getName()
42 {
43 return 'currency';
44 }
45}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php
new file mode 100644
index 00000000..a612b6fc
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php
@@ -0,0 +1,281 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
16use Symfony\Component\Form\FormInterface;
17use Symfony\Component\Form\FormBuilderInterface;
18use Symfony\Component\Form\FormView;
19use Symfony\Component\Form\ReversedTransformer;
20use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain;
21use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
22use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
23use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer;
24use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
25use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer;
26use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer;
27use Symfony\Component\OptionsResolver\Options;
28use Symfony\Component\OptionsResolver\OptionsResolverInterface;
29
30class DateTimeType extends AbstractType
31{
32 const DEFAULT_DATE_FORMAT = \IntlDateFormatter::MEDIUM;
33
34 const DEFAULT_TIME_FORMAT = \IntlDateFormatter::MEDIUM;
35
36 /**
37 * This is not quite the HTML5 format yet, because ICU lacks the
38 * capability of parsing and generating RFC 3339 dates, which
39 * are like the below pattern but with a timezone suffix. The
40 * timezone suffix is
41 *
42 * * "Z" for UTC
43 * * "(-|+)HH:mm" for other timezones (note the colon!)
44 *
45 * For more information see:
46 *
47 * http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax
48 * http://www.w3.org/TR/html-markup/input.datetime.html
49 * http://tools.ietf.org/html/rfc3339
50 *
51 * An ICU ticket was created:
52 * http://icu-project.org/trac/ticket/9421
53 *
54 * It was supposedly fixed, but is not available in all PHP installations
55 * yet. To temporarily circumvent this issue, DateTimeToRfc3339Transformer
56 * is used when the format matches this constant.
57 */
58 const HTML5_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZZZZ";
59
60 private static $acceptedFormats = array(
61 \IntlDateFormatter::FULL,
62 \IntlDateFormatter::LONG,
63 \IntlDateFormatter::MEDIUM,
64 \IntlDateFormatter::SHORT,
65 );
66
67 /**
68 * {@inheritdoc}
69 */
70 public function buildForm(FormBuilderInterface $builder, array $options)
71 {
72 $parts = array('year', 'month', 'day', 'hour');
73 $dateParts = array('year', 'month', 'day');
74 $timeParts = array('hour');
75
76 if ($options['with_minutes']) {
77 $parts[] = 'minute';
78 $timeParts[] = 'minute';
79 }
80
81 if ($options['with_seconds']) {
82 $parts[] = 'second';
83 $timeParts[] = 'second';
84 }
85
86 $dateFormat = is_int($options['date_format']) ? $options['date_format'] : self::DEFAULT_DATE_FORMAT;
87 $timeFormat = self::DEFAULT_TIME_FORMAT;
88 $calendar = \IntlDateFormatter::GREGORIAN;
89 $pattern = is_string($options['format']) ? $options['format'] : null;
90
91 if (!in_array($dateFormat, self::$acceptedFormats, true)) {
92 throw new InvalidOptionsException('The "date_format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.');
93 }
94
95 if ('single_text' === $options['widget']) {
96 if (self::HTML5_FORMAT === $pattern) {
97 $builder->addViewTransformer(new DateTimeToRfc3339Transformer(
98 $options['model_timezone'],
99 $options['view_timezone']
100 ));
101 } else {
102 $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer(
103 $options['model_timezone'],
104 $options['view_timezone'],
105 $dateFormat,
106 $timeFormat,
107 $calendar,
108 $pattern
109 ));
110 }
111 } else {
112 // Only pass a subset of the options to children
113 $dateOptions = array_intersect_key($options, array_flip(array(
114 'years',
115 'months',
116 'days',
117 'empty_value',
118 'required',
119 'translation_domain',
120 )));
121
122 $timeOptions = array_intersect_key($options, array_flip(array(
123 'hours',
124 'minutes',
125 'seconds',
126 'with_minutes',
127 'with_seconds',
128 'empty_value',
129 'required',
130 'translation_domain',
131 )));
132
133 if (null !== $options['date_widget']) {
134 $dateOptions['widget'] = $options['date_widget'];
135 }
136
137 if (null !== $options['time_widget']) {
138 $timeOptions['widget'] = $options['time_widget'];
139 }
140
141 if (null !== $options['date_format']) {
142 $dateOptions['format'] = $options['date_format'];
143 }
144
145 $dateOptions['input'] = $timeOptions['input'] = 'array';
146 $dateOptions['error_bubbling'] = $timeOptions['error_bubbling'] = true;
147
148 $builder
149 ->addViewTransformer(new DataTransformerChain(array(
150 new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts),
151 new ArrayToPartsTransformer(array(
152 'date' => $dateParts,
153 'time' => $timeParts,
154 )),
155 )))
156 ->add('date', 'date', $dateOptions)
157 ->add('time', 'time', $timeOptions)
158 ;
159 }
160
161 if ('string' === $options['input']) {
162 $builder->addModelTransformer(new ReversedTransformer(
163 new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'])
164 ));
165 } elseif ('timestamp' === $options['input']) {
166 $builder->addModelTransformer(new ReversedTransformer(
167 new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone'])
168 ));
169 } elseif ('array' === $options['input']) {
170 $builder->addModelTransformer(new ReversedTransformer(
171 new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts)
172 ));
173 }
174 }
175
176 /**
177 * {@inheritdoc}
178 */
179 public function buildView(FormView $view, FormInterface $form, array $options)
180 {
181 $view->vars['widget'] = $options['widget'];
182
183 // Change the input to a HTML5 date input if
184 // * the widget is set to "single_text"
185 // * the format matches the one expected by HTML5
186 if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) {
187 $view->vars['type'] = 'datetime';
188 }
189 }
190
191 /**
192 * {@inheritdoc}
193 */
194 public function setDefaultOptions(OptionsResolverInterface $resolver)
195 {
196 $compound = function (Options $options) {
197 return $options['widget'] !== 'single_text';
198 };
199
200 // Defaults to the value of "widget"
201 $dateWidget = function (Options $options) {
202 return $options['widget'];
203 };
204
205 // Defaults to the value of "widget"
206 $timeWidget = function (Options $options) {
207 return $options['widget'];
208 };
209
210 $resolver->setDefaults(array(
211 'input' => 'datetime',
212 'model_timezone' => null,
213 'view_timezone' => null,
214 'format' => self::HTML5_FORMAT,
215 'date_format' => null,
216 'widget' => null,
217 'date_widget' => $dateWidget,
218 'time_widget' => $timeWidget,
219 'with_minutes' => true,
220 'with_seconds' => false,
221 // Don't modify \DateTime classes by reference, we treat
222 // them like immutable value objects
223 'by_reference' => false,
224 'error_bubbling' => false,
225 // If initialized with a \DateTime object, FormType initializes
226 // this option to "\DateTime". Since the internal, normalized
227 // representation is not \DateTime, but an array, we need to unset
228 // this option.
229 'data_class' => null,
230 'compound' => $compound,
231 ));
232
233 // Don't add some defaults in order to preserve the defaults
234 // set in DateType and TimeType
235 $resolver->setOptional(array(
236 'empty_value',
237 'years',
238 'months',
239 'days',
240 'hours',
241 'minutes',
242 'seconds',
243 ));
244
245 $resolver->setAllowedValues(array(
246 'input' => array(
247 'datetime',
248 'string',
249 'timestamp',
250 'array',
251 ),
252 'date_widget' => array(
253 null, // inherit default from DateType
254 'single_text',
255 'text',
256 'choice',
257 ),
258 'time_widget' => array(
259 null, // inherit default from TimeType
260 'single_text',
261 'text',
262 'choice',
263 ),
264 // This option will overwrite "date_widget" and "time_widget" options
265 'widget' => array(
266 null, // default, don't overwrite options
267 'single_text',
268 'text',
269 'choice',
270 ),
271 ));
272 }
273
274 /**
275 * {@inheritdoc}
276 */
277 public function getName()
278 {
279 return 'datetime';
280 }
281}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateType.php
new file mode 100644
index 00000000..93d3502e
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateType.php
@@ -0,0 +1,309 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormInterface;
16use Symfony\Component\Form\FormBuilderInterface;
17use Symfony\Component\Form\FormView;
18use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer;
19use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
20use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
21use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
22use Symfony\Component\Form\ReversedTransformer;
23use Symfony\Component\OptionsResolver\Options;
24use Symfony\Component\OptionsResolver\OptionsResolverInterface;
25use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
26
27class DateType extends AbstractType
28{
29 const DEFAULT_FORMAT = \IntlDateFormatter::MEDIUM;
30
31 const HTML5_FORMAT = 'yyyy-MM-dd';
32
33 private static $acceptedFormats = array(
34 \IntlDateFormatter::FULL,
35 \IntlDateFormatter::LONG,
36 \IntlDateFormatter::MEDIUM,
37 \IntlDateFormatter::SHORT,
38 );
39
40 /**
41 * {@inheritdoc}
42 */
43 public function buildForm(FormBuilderInterface $builder, array $options)
44 {
45 $dateFormat = is_int($options['format']) ? $options['format'] : self::DEFAULT_FORMAT;
46 $timeFormat = \IntlDateFormatter::NONE;
47 $calendar = \IntlDateFormatter::GREGORIAN;
48 $pattern = is_string($options['format']) ? $options['format'] : null;
49
50 if (!in_array($dateFormat, self::$acceptedFormats, true)) {
51 throw new InvalidOptionsException('The "format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.');
52 }
53
54 if (null !== $pattern && (false === strpos($pattern, 'y') || false === strpos($pattern, 'M') || false === strpos($pattern, 'd'))) {
55 throw new InvalidOptionsException(sprintf('The "format" option should contain the letters "y", "M" and "d". Its current value is "%s".', $pattern));
56 }
57
58 if ('single_text' === $options['widget']) {
59 $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer(
60 $options['model_timezone'],
61 $options['view_timezone'],
62 $dateFormat,
63 $timeFormat,
64 $calendar,
65 $pattern
66 ));
67 } else {
68 $yearOptions = $monthOptions = $dayOptions = array(
69 'error_bubbling' => true,
70 );
71
72 $formatter = new \IntlDateFormatter(
73 \Locale::getDefault(),
74 $dateFormat,
75 $timeFormat,
76 'UTC',
77 $calendar,
78 $pattern
79 );
80 $formatter->setLenient(false);
81
82 if ('choice' === $options['widget']) {
83 // Only pass a subset of the options to children
84 $yearOptions['choices'] = $this->formatTimestamps($formatter, '/y+/', $this->listYears($options['years']));
85 $yearOptions['empty_value'] = $options['empty_value']['year'];
86 $monthOptions['choices'] = $this->formatTimestamps($formatter, '/[M|L]+/', $this->listMonths($options['months']));
87 $monthOptions['empty_value'] = $options['empty_value']['month'];
88 $dayOptions['choices'] = $this->formatTimestamps($formatter, '/d+/', $this->listDays($options['days']));
89 $dayOptions['empty_value'] = $options['empty_value']['day'];
90 }
91
92 // Append generic carry-along options
93 foreach (array('required', 'translation_domain') as $passOpt) {
94 $yearOptions[$passOpt] = $monthOptions[$passOpt] = $dayOptions[$passOpt] = $options[$passOpt];
95 }
96
97 $builder
98 ->add('year', $options['widget'], $yearOptions)
99 ->add('month', $options['widget'], $monthOptions)
100 ->add('day', $options['widget'], $dayOptions)
101 ->addViewTransformer(new DateTimeToArrayTransformer(
102 $options['model_timezone'], $options['view_timezone'], array('year', 'month', 'day')
103 ))
104 ->setAttribute('formatter', $formatter)
105 ;
106 }
107
108 if ('string' === $options['input']) {
109 $builder->addModelTransformer(new ReversedTransformer(
110 new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'Y-m-d')
111 ));
112 } elseif ('timestamp' === $options['input']) {
113 $builder->addModelTransformer(new ReversedTransformer(
114 new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone'])
115 ));
116 } elseif ('array' === $options['input']) {
117 $builder->addModelTransformer(new ReversedTransformer(
118 new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], array('year', 'month', 'day'))
119 ));
120 }
121 }
122
123 /**
124 * {@inheritdoc}
125 */
126 public function finishView(FormView $view, FormInterface $form, array $options)
127 {
128 $view->vars['widget'] = $options['widget'];
129
130 // Change the input to a HTML5 date input if
131 // * the widget is set to "single_text"
132 // * the format matches the one expected by HTML5
133 if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) {
134 $view->vars['type'] = 'date';
135 }
136
137 if ($form->getConfig()->hasAttribute('formatter')) {
138 $pattern = $form->getConfig()->getAttribute('formatter')->getPattern();
139
140 // remove special characters unless the format was explicitly specified
141 if (!is_string($options['format'])) {
142 $pattern = preg_replace('/[^yMd]+/', '', $pattern);
143 }
144
145 // set right order with respect to locale (e.g.: de_DE=dd.MM.yy; en_US=M/d/yy)
146 // lookup various formats at http://userguide.icu-project.org/formatparse/datetime
147 if (preg_match('/^([yMd]+)[^yMd]*([yMd]+)[^yMd]*([yMd]+)$/', $pattern)) {
148 $pattern = preg_replace(array('/y+/', '/M+/', '/d+/'), array('{{ year }}', '{{ month }}', '{{ day }}'), $pattern);
149 } else {
150 // default fallback
151 $pattern = '{{ year }}{{ month }}{{ day }}';
152 }
153
154 $view->vars['date_pattern'] = $pattern;
155 }
156 }
157
158 /**
159 * {@inheritdoc}
160 */
161 public function setDefaultOptions(OptionsResolverInterface $resolver)
162 {
163 $compound = function (Options $options) {
164 return $options['widget'] !== 'single_text';
165 };
166
167 $emptyValue = $emptyValueDefault = function (Options $options) {
168 return $options['required'] ? null : '';
169 };
170
171 $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) {
172 if (is_array($emptyValue)) {
173 $default = $emptyValueDefault($options);
174
175 return array_merge(
176 array('year' => $default, 'month' => $default, 'day' => $default),
177 $emptyValue
178 );
179 }
180
181 return array(
182 'year' => $emptyValue,
183 'month' => $emptyValue,
184 'day' => $emptyValue
185 );
186 };
187
188 $format = function (Options $options) {
189 return $options['widget'] === 'single_text' ? DateType::HTML5_FORMAT : DateType::DEFAULT_FORMAT;
190 };
191
192 $resolver->setDefaults(array(
193 'years' => range(date('Y') - 5, date('Y') + 5),
194 'months' => range(1, 12),
195 'days' => range(1, 31),
196 'widget' => 'choice',
197 'input' => 'datetime',
198 'format' => $format,
199 'model_timezone' => null,
200 'view_timezone' => null,
201 'empty_value' => $emptyValue,
202 // Don't modify \DateTime classes by reference, we treat
203 // them like immutable value objects
204 'by_reference' => false,
205 'error_bubbling' => false,
206 // If initialized with a \DateTime object, FormType initializes
207 // this option to "\DateTime". Since the internal, normalized
208 // representation is not \DateTime, but an array, we need to unset
209 // this option.
210 'data_class' => null,
211 'compound' => $compound,
212 ));
213
214 $resolver->setNormalizers(array(
215 'empty_value' => $emptyValueNormalizer,
216 ));
217
218 $resolver->setAllowedValues(array(
219 'input' => array(
220 'datetime',
221 'string',
222 'timestamp',
223 'array',
224 ),
225 'widget' => array(
226 'single_text',
227 'text',
228 'choice',
229 ),
230 ));
231
232 $resolver->setAllowedTypes(array(
233 'format' => array('int', 'string'),
234 ));
235 }
236
237 /**
238 * {@inheritdoc}
239 */
240 public function getName()
241 {
242 return 'date';
243 }
244
245 private function formatTimestamps(\IntlDateFormatter $formatter, $regex, array $timestamps)
246 {
247 $pattern = $formatter->getPattern();
248 $timezone = $formatter->getTimezoneId();
249
250 if (version_compare(\PHP_VERSION, '5.5.0-dev', '>=')) {
251 $formatter->setTimeZone(\DateTimeZone::UTC);
252 } else {
253 $formatter->setTimeZoneId(\DateTimeZone::UTC);
254 }
255
256 if (preg_match($regex, $pattern, $matches)) {
257 $formatter->setPattern($matches[0]);
258
259 foreach ($timestamps as $key => $timestamp) {
260 $timestamps[$key] = $formatter->format($timestamp);
261 }
262
263 // I'd like to clone the formatter above, but then we get a
264 // segmentation fault, so let's restore the old state instead
265 $formatter->setPattern($pattern);
266 }
267
268 if (version_compare(\PHP_VERSION, '5.5.0-dev', '>=')) {
269 $formatter->setTimeZone($timezone);
270 } else {
271 $formatter->setTimeZoneId($timezone);
272 }
273
274 return $timestamps;
275 }
276
277 private function listYears(array $years)
278 {
279 $result = array();
280
281 foreach ($years as $year) {
282 $result[$year] = gmmktime(0, 0, 0, 6, 15, $year);
283 }
284
285 return $result;
286 }
287
288 private function listMonths(array $months)
289 {
290 $result = array();
291
292 foreach ($months as $month) {
293 $result[$month] = gmmktime(0, 0, 0, $month, 15);
294 }
295
296 return $result;
297 }
298
299 private function listDays(array $days)
300 {
301 $result = array();
302
303 foreach ($days as $day) {
304 $result[$day] = gmmktime(0, 0, 0, 5, $day);
305 }
306
307 return $result;
308 }
309}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/EmailType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/EmailType.php
new file mode 100644
index 00000000..26652ef6
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/EmailType.php
@@ -0,0 +1,33 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15
16class EmailType extends AbstractType
17{
18 /**
19 * {@inheritdoc}
20 */
21 public function getParent()
22 {
23 return 'text';
24 }
25
26 /**
27 * {@inheritdoc}
28 */
29 public function getName()
30 {
31 return 'email';
32 }
33}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FileType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FileType.php
new file mode 100644
index 00000000..2c09da6f
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FileType.php
@@ -0,0 +1,61 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormInterface;
16use Symfony\Component\Form\FormView;
17use Symfony\Component\OptionsResolver\OptionsResolverInterface;
18
19class FileType extends AbstractType
20{
21 /**
22 * {@inheritdoc}
23 */
24 public function buildView(FormView $view, FormInterface $form, array $options)
25 {
26 $view->vars = array_replace($view->vars, array(
27 'type' => 'file',
28 'value' => '',
29 ));
30 }
31
32 /**
33 * {@inheritdoc}
34 */
35 public function finishView(FormView $view, FormInterface $form, array $options)
36 {
37 $view
38 ->vars['multipart'] = true
39 ;
40 }
41
42 /**
43 * {@inheritdoc}
44 */
45 public function setDefaultOptions(OptionsResolverInterface $resolver)
46 {
47 $resolver->setDefaults(array(
48 'compound' => false,
49 'data_class' => 'Symfony\Component\HttpFoundation\File\File',
50 'empty_data' => null,
51 ));
52 }
53
54 /**
55 * {@inheritdoc}
56 */
57 public function getName()
58 {
59 return 'file';
60 }
61}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FormType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FormType.php
new file mode 100644
index 00000000..0c39d3eb
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/FormType.php
@@ -0,0 +1,214 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\FormBuilderInterface;
15use Symfony\Component\Form\FormInterface;
16use Symfony\Component\Form\FormView;
17use Symfony\Component\Form\Extension\Core\EventListener\TrimListener;
18use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
19use Symfony\Component\Form\Exception\LogicException;
20use Symfony\Component\OptionsResolver\Options;
21use Symfony\Component\OptionsResolver\OptionsResolverInterface;
22use Symfony\Component\PropertyAccess\PropertyAccess;
23use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
24
25class FormType extends BaseType
26{
27 /**
28 * @var PropertyAccessorInterface
29 */
30 private $propertyAccessor;
31
32 public function __construct(PropertyAccessorInterface $propertyAccessor = null)
33 {
34 $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor();
35 }
36
37 /**
38 * {@inheritdoc}
39 */
40 public function buildForm(FormBuilderInterface $builder, array $options)
41 {
42 parent::buildForm($builder, $options);
43
44 $builder
45 ->setRequired($options['required'])
46 ->setErrorBubbling($options['error_bubbling'])
47 ->setEmptyData($options['empty_data'])
48 ->setPropertyPath($options['property_path'])
49 ->setMapped($options['mapped'])
50 ->setByReference($options['by_reference'])
51 ->setInheritData($options['inherit_data'])
52 ->setCompound($options['compound'])
53 ->setData(isset($options['data']) ? $options['data'] : null)
54 ->setDataLocked(isset($options['data']))
55 ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null)
56 ->setMethod($options['method'])
57 ->setAction($options['action'])
58 ->setAutoInitialize($options['auto_initialize'])
59 ;
60
61 if ($options['trim']) {
62 $builder->addEventSubscriber(new TrimListener());
63 }
64 }
65
66 /**
67 * {@inheritdoc}
68 */
69 public function buildView(FormView $view, FormInterface $form, array $options)
70 {
71 parent::buildView($view, $form, $options);
72
73 $name = $form->getName();
74 $readOnly = $options['read_only'];
75
76 if ($view->parent) {
77 if ('' === $name) {
78 throw new LogicException('Form node with empty name can be used only as root form node.');
79 }
80
81 // Complex fields are read-only if they themselves or their parents are.
82 if (!$readOnly) {
83 $readOnly = $view->parent->vars['read_only'];
84 }
85 }
86
87 $view->vars = array_replace($view->vars, array(
88 'read_only' => $readOnly,
89 'errors' => $form->getErrors(),
90 'valid' => $form->isSubmitted() ? $form->isValid() : true,
91 'value' => $form->getViewData(),
92 'data' => $form->getNormData(),
93 'required' => $form->isRequired(),
94 'max_length' => $options['max_length'],
95 'pattern' => $options['pattern'],
96 'size' => null,
97 'label_attr' => $options['label_attr'],
98 'compound' => $form->getConfig()->getCompound(),
99 'method' => $form->getConfig()->getMethod(),
100 'action' => $form->getConfig()->getAction(),
101 ));
102 }
103
104 /**
105 * {@inheritdoc}
106 */
107 public function finishView(FormView $view, FormInterface $form, array $options)
108 {
109 $multipart = false;
110
111 foreach ($view->children as $child) {
112 if ($child->vars['multipart']) {
113 $multipart = true;
114 break;
115 }
116 }
117
118 $view->vars['multipart'] = $multipart;
119 }
120
121 /**
122 * {@inheritdoc}
123 */
124 public function setDefaultOptions(OptionsResolverInterface $resolver)
125 {
126 parent::setDefaultOptions($resolver);
127
128 // Derive "data_class" option from passed "data" object
129 $dataClass = function (Options $options) {
130 return isset($options['data']) && is_object($options['data']) ? get_class($options['data']) : null;
131 };
132
133 // Derive "empty_data" closure from "data_class" option
134 $emptyData = function (Options $options) {
135 $class = $options['data_class'];
136
137 if (null !== $class) {
138 return function (FormInterface $form) use ($class) {
139 return $form->isEmpty() && !$form->isRequired() ? null : new $class();
140 };
141 }
142
143 return function (FormInterface $form) {
144 return $form->getConfig()->getCompound() ? array() : '';
145 };
146 };
147
148 // For any form that is not represented by a single HTML control,
149 // errors should bubble up by default
150 $errorBubbling = function (Options $options) {
151 return $options['compound'];
152 };
153
154 // BC with old "virtual" option
155 $inheritData = function (Options $options) {
156 if (null !== $options['virtual']) {
157 // Uncomment this as soon as the deprecation note should be shown
158 // trigger_error('The form option "virtual" is deprecated since version 2.3 and will be removed in 3.0. Use "inherit_data" instead.', E_USER_DEPRECATED);
159 return $options['virtual'];
160 }
161
162 return false;
163 };
164
165 // If data is given, the form is locked to that data
166 // (independent of its value)
167 $resolver->setOptional(array(
168 'data',
169 ));
170
171 $resolver->setDefaults(array(
172 'data_class' => $dataClass,
173 'empty_data' => $emptyData,
174 'trim' => true,
175 'required' => true,
176 'read_only' => false,
177 'max_length' => null,
178 'pattern' => null,
179 'property_path' => null,
180 'mapped' => true,
181 'by_reference' => true,
182 'error_bubbling' => $errorBubbling,
183 'label_attr' => array(),
184 'virtual' => null,
185 'inherit_data' => $inheritData,
186 'compound' => true,
187 'method' => 'POST',
188 // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt)
189 // section 4.2., empty URIs are considered same-document references
190 'action' => '',
191 'auto_initialize' => true,
192 ));
193
194 $resolver->setAllowedTypes(array(
195 'label_attr' => 'array',
196 ));
197 }
198
199 /**
200 * {@inheritdoc}
201 */
202 public function getParent()
203 {
204 return null;
205 }
206
207 /**
208 * {@inheritdoc}
209 */
210 public function getName()
211 {
212 return 'form';
213 }
214}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/HiddenType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/HiddenType.php
new file mode 100644
index 00000000..bd4fa898
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/HiddenType.php
@@ -0,0 +1,40 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\OptionsResolver\OptionsResolverInterface;
16
17class HiddenType extends AbstractType
18{
19 /**
20 * {@inheritdoc}
21 */
22 public function setDefaultOptions(OptionsResolverInterface $resolver)
23 {
24 $resolver->setDefaults(array(
25 // hidden fields cannot have a required attribute
26 'required' => false,
27 // Pass errors to the parent
28 'error_bubbling' => true,
29 'compound' => false,
30 ));
31 }
32
33 /**
34 * {@inheritdoc}
35 */
36 public function getName()
37 {
38 return 'hidden';
39 }
40}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/IntegerType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/IntegerType.php
new file mode 100644
index 00000000..b224cac5
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/IntegerType.php
@@ -0,0 +1,68 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormBuilderInterface;
16use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer;
17use Symfony\Component\OptionsResolver\OptionsResolverInterface;
18
19class IntegerType extends AbstractType
20{
21 /**
22 * {@inheritdoc}
23 */
24 public function buildForm(FormBuilderInterface $builder, array $options)
25 {
26 $builder->addViewTransformer(
27 new IntegerToLocalizedStringTransformer(
28 $options['precision'],
29 $options['grouping'],
30 $options['rounding_mode']
31 ));
32 }
33
34 /**
35 * {@inheritdoc}
36 */
37 public function setDefaultOptions(OptionsResolverInterface $resolver)
38 {
39 $resolver->setDefaults(array(
40 // default precision is locale specific (usually around 3)
41 'precision' => null,
42 'grouping' => false,
43 // Integer cast rounds towards 0, so do the same when displaying fractions
44 'rounding_mode' => \NumberFormatter::ROUND_DOWN,
45 'compound' => false,
46 ));
47
48 $resolver->setAllowedValues(array(
49 'rounding_mode' => array(
50 \NumberFormatter::ROUND_FLOOR,
51 \NumberFormatter::ROUND_DOWN,
52 \NumberFormatter::ROUND_HALFDOWN,
53 \NumberFormatter::ROUND_HALFEVEN,
54 \NumberFormatter::ROUND_HALFUP,
55 \NumberFormatter::ROUND_UP,
56 \NumberFormatter::ROUND_CEILING,
57 ),
58 ));
59 }
60
61 /**
62 * {@inheritdoc}
63 */
64 public function getName()
65 {
66 return 'integer';
67 }
68}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LanguageType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LanguageType.php
new file mode 100644
index 00000000..37b2bf33
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LanguageType.php
@@ -0,0 +1,45 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Intl\Intl;
16use Symfony\Component\OptionsResolver\OptionsResolverInterface;
17
18class LanguageType extends AbstractType
19{
20 /**
21 * {@inheritdoc}
22 */
23 public function setDefaultOptions(OptionsResolverInterface $resolver)
24 {
25 $resolver->setDefaults(array(
26 'choices' => Intl::getLanguageBundle()->getLanguageNames(),
27 ));
28 }
29
30 /**
31 * {@inheritdoc}
32 */
33 public function getParent()
34 {
35 return 'choice';
36 }
37
38 /**
39 * {@inheritdoc}
40 */
41 public function getName()
42 {
43 return 'language';
44 }
45}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LocaleType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LocaleType.php
new file mode 100644
index 00000000..c68c561a
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/LocaleType.php
@@ -0,0 +1,46 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Intl\Intl;
16use Symfony\Component\Locale\Locale;
17use Symfony\Component\OptionsResolver\OptionsResolverInterface;
18
19class LocaleType extends AbstractType
20{
21 /**
22 * {@inheritdoc}
23 */
24 public function setDefaultOptions(OptionsResolverInterface $resolver)
25 {
26 $resolver->setDefaults(array(
27 'choices' => Intl::getLocaleBundle()->getLocaleNames(),
28 ));
29 }
30
31 /**
32 * {@inheritdoc}
33 */
34 public function getParent()
35 {
36 return 'choice';
37 }
38
39 /**
40 * {@inheritdoc}
41 */
42 public function getName()
43 {
44 return 'locale';
45 }
46}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/MoneyType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/MoneyType.php
new file mode 100644
index 00000000..9e36f9ce
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/MoneyType.php
@@ -0,0 +1,111 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormInterface;
16use Symfony\Component\Form\FormBuilderInterface;
17use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer;
18use Symfony\Component\Form\FormView;
19use Symfony\Component\OptionsResolver\OptionsResolverInterface;
20
21class MoneyType extends AbstractType
22{
23 protected static $patterns = array();
24
25 /**
26 * {@inheritdoc}
27 */
28 public function buildForm(FormBuilderInterface $builder, array $options)
29 {
30 $builder
31 ->addViewTransformer(new MoneyToLocalizedStringTransformer(
32 $options['precision'],
33 $options['grouping'],
34 null,
35 $options['divisor']
36 ))
37 ;
38 }
39
40 /**
41 * {@inheritdoc}
42 */
43 public function buildView(FormView $view, FormInterface $form, array $options)
44 {
45 $view->vars['money_pattern'] = self::getPattern($options['currency']);
46 }
47
48 /**
49 * {@inheritdoc}
50 */
51 public function setDefaultOptions(OptionsResolverInterface $resolver)
52 {
53 $resolver->setDefaults(array(
54 'precision' => 2,
55 'grouping' => false,
56 'divisor' => 1,
57 'currency' => 'EUR',
58 'compound' => false,
59 ));
60 }
61
62 /**
63 * {@inheritdoc}
64 */
65 public function getName()
66 {
67 return 'money';
68 }
69
70 /**
71 * Returns the pattern for this locale
72 *
73 * The pattern contains the placeholder "{{ widget }}" where the HTML tag should
74 * be inserted
75 */
76 protected static function getPattern($currency)
77 {
78 if (!$currency) {
79 return '{{ widget }}';
80 }
81
82 $locale = \Locale::getDefault();
83
84 if (!isset(self::$patterns[$locale])) {
85 self::$patterns[$locale] = array();
86 }
87
88 if (!isset(self::$patterns[$locale][$currency])) {
89 $format = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
90 $pattern = $format->formatCurrency('123', $currency);
91
92 // the spacings between currency symbol and number are ignored, because
93 // a single space leads to better readability in combination with input
94 // fields
95
96 // the regex also considers non-break spaces (0xC2 or 0xA0 in UTF-8)
97
98 preg_match('/^([^\s\xc2\xa0]*)[\s\xc2\xa0]*123(?:[,.]0+)?[\s\xc2\xa0]*([^\s\xc2\xa0]*)$/u', $pattern, $matches);
99
100 if (!empty($matches[1])) {
101 self::$patterns[$locale][$currency] = $matches[1].' {{ widget }}';
102 } elseif (!empty($matches[2])) {
103 self::$patterns[$locale][$currency] = '{{ widget }} '.$matches[2];
104 } else {
105 self::$patterns[$locale][$currency] = '{{ widget }}';
106 }
107 }
108
109 return self::$patterns[$locale][$currency];
110 }
111}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/NumberType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/NumberType.php
new file mode 100644
index 00000000..beb3c89a
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/NumberType.php
@@ -0,0 +1,66 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormBuilderInterface;
16use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer;
17use Symfony\Component\OptionsResolver\OptionsResolverInterface;
18
19class NumberType extends AbstractType
20{
21 /**
22 * {@inheritdoc}
23 */
24 public function buildForm(FormBuilderInterface $builder, array $options)
25 {
26 $builder->addViewTransformer(new NumberToLocalizedStringTransformer(
27 $options['precision'],
28 $options['grouping'],
29 $options['rounding_mode']
30 ));
31 }
32
33 /**
34 * {@inheritdoc}
35 */
36 public function setDefaultOptions(OptionsResolverInterface $resolver)
37 {
38 $resolver->setDefaults(array(
39 // default precision is locale specific (usually around 3)
40 'precision' => null,
41 'grouping' => false,
42 'rounding_mode' => \NumberFormatter::ROUND_HALFUP,
43 'compound' => false,
44 ));
45
46 $resolver->setAllowedValues(array(
47 'rounding_mode' => array(
48 \NumberFormatter::ROUND_FLOOR,
49 \NumberFormatter::ROUND_DOWN,
50 \NumberFormatter::ROUND_HALFDOWN,
51 \NumberFormatter::ROUND_HALFEVEN,
52 \NumberFormatter::ROUND_HALFUP,
53 \NumberFormatter::ROUND_UP,
54 \NumberFormatter::ROUND_CEILING,
55 ),
56 ));
57 }
58
59 /**
60 * {@inheritdoc}
61 */
62 public function getName()
63 {
64 return 'number';
65 }
66}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PasswordType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PasswordType.php
new file mode 100644
index 00000000..5a5b1635
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PasswordType.php
@@ -0,0 +1,57 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormInterface;
16use Symfony\Component\Form\FormView;
17use Symfony\Component\OptionsResolver\OptionsResolverInterface;
18
19class PasswordType extends AbstractType
20{
21 /**
22 * {@inheritdoc}
23 */
24 public function buildView(FormView $view, FormInterface $form, array $options)
25 {
26 if ($options['always_empty'] || !$form->isSubmitted()) {
27 $view->vars['value'] = '';
28 }
29 }
30
31 /**
32 * {@inheritdoc}
33 */
34 public function setDefaultOptions(OptionsResolverInterface $resolver)
35 {
36 $resolver->setDefaults(array(
37 'always_empty' => true,
38 'trim' => false,
39 ));
40 }
41
42 /**
43 * {@inheritdoc}
44 */
45 public function getParent()
46 {
47 return 'text';
48 }
49
50 /**
51 * {@inheritdoc}
52 */
53 public function getName()
54 {
55 return 'password';
56 }
57}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PercentType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PercentType.php
new file mode 100644
index 00000000..b1df9436
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/PercentType.php
@@ -0,0 +1,55 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormBuilderInterface;
16use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer;
17use Symfony\Component\OptionsResolver\OptionsResolverInterface;
18
19class PercentType extends AbstractType
20{
21 /**
22 * {@inheritdoc}
23 */
24 public function buildForm(FormBuilderInterface $builder, array $options)
25 {
26 $builder->addViewTransformer(new PercentToLocalizedStringTransformer($options['precision'], $options['type']));
27 }
28
29 /**
30 * {@inheritdoc}
31 */
32 public function setDefaultOptions(OptionsResolverInterface $resolver)
33 {
34 $resolver->setDefaults(array(
35 'precision' => 0,
36 'type' => 'fractional',
37 'compound' => false,
38 ));
39
40 $resolver->setAllowedValues(array(
41 'type' => array(
42 'fractional',
43 'integer',
44 ),
45 ));
46 }
47
48 /**
49 * {@inheritdoc}
50 */
51 public function getName()
52 {
53 return 'percent';
54 }
55}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RadioType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RadioType.php
new file mode 100644
index 00000000..dfa7c7d5
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RadioType.php
@@ -0,0 +1,33 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15
16class RadioType extends AbstractType
17{
18 /**
19 * {@inheritdoc}
20 */
21 public function getParent()
22 {
23 return 'checkbox';
24 }
25
26 /**
27 * {@inheritdoc}
28 */
29 public function getName()
30 {
31 return 'radio';
32 }
33}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php
new file mode 100644
index 00000000..9a3cd146
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php
@@ -0,0 +1,67 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormBuilderInterface;
16use Symfony\Component\Form\Extension\Core\DataTransformer\ValueToDuplicatesTransformer;
17use Symfony\Component\OptionsResolver\OptionsResolverInterface;
18
19class RepeatedType extends AbstractType
20{
21 /**
22 * {@inheritdoc}
23 */
24 public function buildForm(FormBuilderInterface $builder, array $options)
25 {
26 // Overwrite required option for child fields
27 $options['first_options']['required'] = $options['required'];
28 $options['second_options']['required'] = $options['required'];
29
30 if (!isset($options['options']['error_bubbling'])) {
31 $options['options']['error_bubbling'] = $options['error_bubbling'];
32 }
33
34 $builder
35 ->addViewTransformer(new ValueToDuplicatesTransformer(array(
36 $options['first_name'],
37 $options['second_name'],
38 )))
39 ->add($options['first_name'], $options['type'], array_merge($options['options'], $options['first_options']))
40 ->add($options['second_name'], $options['type'], array_merge($options['options'], $options['second_options']))
41 ;
42 }
43
44 /**
45 * {@inheritdoc}
46 */
47 public function setDefaultOptions(OptionsResolverInterface $resolver)
48 {
49 $resolver->setDefaults(array(
50 'type' => 'text',
51 'options' => array(),
52 'first_options' => array(),
53 'second_options' => array(),
54 'first_name' => 'first',
55 'second_name' => 'second',
56 'error_bubbling' => false,
57 ));
58 }
59
60 /**
61 * {@inheritdoc}
62 */
63 public function getName()
64 {
65 return 'repeated';
66 }
67}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ResetType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ResetType.php
new file mode 100644
index 00000000..cf55f7c5
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/ResetType.php
@@ -0,0 +1,39 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\ButtonTypeInterface;
16
17/**
18 * A reset button.
19 *
20 * @author Bernhard Schussek <bschussek@gmail.com>
21 */
22class ResetType extends AbstractType implements ButtonTypeInterface
23{
24 /**
25 * {@inheritdoc}
26 */
27 public function getParent()
28 {
29 return 'button';
30 }
31
32 /**
33 * {@inheritdoc}
34 */
35 public function getName()
36 {
37 return 'reset';
38 }
39}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SearchType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SearchType.php
new file mode 100644
index 00000000..bf82972d
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SearchType.php
@@ -0,0 +1,33 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15
16class SearchType extends AbstractType
17{
18 /**
19 * {@inheritdoc}
20 */
21 public function getParent()
22 {
23 return 'text';
24 }
25
26 /**
27 * {@inheritdoc}
28 */
29 public function getName()
30 {
31 return 'search';
32 }
33}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SubmitType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SubmitType.php
new file mode 100644
index 00000000..6d160b96
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/SubmitType.php
@@ -0,0 +1,46 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormInterface;
16use Symfony\Component\Form\FormView;
17use Symfony\Component\Form\SubmitButtonTypeInterface;
18
19/**
20 * A submit button.
21 *
22 * @author Bernhard Schussek <bschussek@gmail.com>
23 */
24class SubmitType extends AbstractType implements SubmitButtonTypeInterface
25{
26 public function buildView(FormView $view, FormInterface $form, array $options)
27 {
28 $view->vars['clicked'] = $form->isClicked();
29 }
30
31 /**
32 * {@inheritdoc}
33 */
34 public function getParent()
35 {
36 return 'button';
37 }
38
39 /**
40 * {@inheritdoc}
41 */
42 public function getName()
43 {
44 return 'submit';
45 }
46}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextType.php
new file mode 100644
index 00000000..11503261
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextType.php
@@ -0,0 +1,36 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\OptionsResolver\OptionsResolverInterface;
16
17class TextType extends AbstractType
18{
19 /**
20 * {@inheritdoc}
21 */
22 public function setDefaultOptions(OptionsResolverInterface $resolver)
23 {
24 $resolver->setDefaults(array(
25 'compound' => false,
26 ));
27 }
28
29 /**
30 * {@inheritdoc}
31 */
32 public function getName()
33 {
34 return 'text';
35 }
36}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextareaType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextareaType.php
new file mode 100644
index 00000000..0e749b15
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TextareaType.php
@@ -0,0 +1,43 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormView;
16use Symfony\Component\Form\FormInterface;
17
18class TextareaType extends AbstractType
19{
20 /**
21 * {@inheritdoc}
22 */
23 public function buildView(FormView $view, FormInterface $form, array $options)
24 {
25 $view->vars['pattern'] = null;
26 }
27
28 /**
29 * {@inheritdoc}
30 */
31 public function getParent()
32 {
33 return 'text';
34 }
35
36 /**
37 * {@inheritdoc}
38 */
39 public function getName()
40 {
41 return 'textarea';
42 }
43}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimeType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimeType.php
new file mode 100644
index 00000000..d7a2a9ef
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimeType.php
@@ -0,0 +1,225 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormInterface;
16use Symfony\Component\Form\FormBuilderInterface;
17use Symfony\Component\Form\ReversedTransformer;
18use Symfony\Component\Form\Exception\InvalidConfigurationException;
19use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
20use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
21use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
22use Symfony\Component\Form\FormView;
23use Symfony\Component\OptionsResolver\Options;
24use Symfony\Component\OptionsResolver\OptionsResolverInterface;
25
26class TimeType extends AbstractType
27{
28 /**
29 * {@inheritdoc}
30 */
31 public function buildForm(FormBuilderInterface $builder, array $options)
32 {
33 $parts = array('hour');
34 $format = 'H';
35
36 if ($options['with_seconds'] && !$options['with_minutes']) {
37 throw new InvalidConfigurationException('You can not disable minutes if you have enabled seconds.');
38 }
39
40 if ($options['with_minutes']) {
41 $format .= ':i';
42 $parts[] = 'minute';
43 }
44
45 if ($options['with_seconds']) {
46 $format .= ':s';
47 $parts[] = 'second';
48 }
49
50 if ('single_text' === $options['widget']) {
51 $builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format));
52 } else {
53 $hourOptions = $minuteOptions = $secondOptions = array(
54 'error_bubbling' => true,
55 );
56
57 if ('choice' === $options['widget']) {
58 $hours = $minutes = array();
59
60 foreach ($options['hours'] as $hour) {
61 $hours[$hour] = str_pad($hour, 2, '0', STR_PAD_LEFT);
62 }
63
64 // Only pass a subset of the options to children
65 $hourOptions['choices'] = $hours;
66 $hourOptions['empty_value'] = $options['empty_value']['hour'];
67
68 if ($options['with_minutes']) {
69 foreach ($options['minutes'] as $minute) {
70 $minutes[$minute] = str_pad($minute, 2, '0', STR_PAD_LEFT);
71 }
72
73 $minuteOptions['choices'] = $minutes;
74 $minuteOptions['empty_value'] = $options['empty_value']['minute'];
75 }
76
77 if ($options['with_seconds']) {
78 $seconds = array();
79
80 foreach ($options['seconds'] as $second) {
81 $seconds[$second] = str_pad($second, 2, '0', STR_PAD_LEFT);
82 }
83
84 $secondOptions['choices'] = $seconds;
85 $secondOptions['empty_value'] = $options['empty_value']['second'];
86 }
87
88 // Append generic carry-along options
89 foreach (array('required', 'translation_domain') as $passOpt) {
90 $hourOptions[$passOpt] = $options[$passOpt];
91
92 if ($options['with_minutes']) {
93 $minuteOptions[$passOpt] = $options[$passOpt];
94 }
95
96 if ($options['with_seconds']) {
97 $secondOptions[$passOpt] = $options[$passOpt];
98 }
99 }
100 }
101
102 $builder->add('hour', $options['widget'], $hourOptions);
103
104 if ($options['with_minutes']) {
105 $builder->add('minute', $options['widget'], $minuteOptions);
106 }
107
108 if ($options['with_seconds']) {
109 $builder->add('second', $options['widget'], $secondOptions);
110 }
111
112 $builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget']));
113 }
114
115 if ('string' === $options['input']) {
116 $builder->addModelTransformer(new ReversedTransformer(
117 new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'H:i:s')
118 ));
119 } elseif ('timestamp' === $options['input']) {
120 $builder->addModelTransformer(new ReversedTransformer(
121 new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone'])
122 ));
123 } elseif ('array' === $options['input']) {
124 $builder->addModelTransformer(new ReversedTransformer(
125 new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts)
126 ));
127 }
128 }
129
130 /**
131 * {@inheritdoc}
132 */
133 public function buildView(FormView $view, FormInterface $form, array $options)
134 {
135 $view->vars = array_replace($view->vars, array(
136 'widget' => $options['widget'],
137 'with_minutes' => $options['with_minutes'],
138 'with_seconds' => $options['with_seconds'],
139 ));
140
141 if ('single_text' === $options['widget']) {
142 $view->vars['type'] = 'time';
143 }
144 }
145
146 /**
147 * {@inheritdoc}
148 */
149 public function setDefaultOptions(OptionsResolverInterface $resolver)
150 {
151 $compound = function (Options $options) {
152 return $options['widget'] !== 'single_text';
153 };
154
155 $emptyValue = $emptyValueDefault = function (Options $options) {
156 return $options['required'] ? null : '';
157 };
158
159 $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) {
160 if (is_array($emptyValue)) {
161 $default = $emptyValueDefault($options);
162
163 return array_merge(
164 array('hour' => $default, 'minute' => $default, 'second' => $default),
165 $emptyValue
166 );
167 }
168
169 return array(
170 'hour' => $emptyValue,
171 'minute' => $emptyValue,
172 'second' => $emptyValue
173 );
174 };
175
176 $resolver->setDefaults(array(
177 'hours' => range(0, 23),
178 'minutes' => range(0, 59),
179 'seconds' => range(0, 59),
180 'widget' => 'choice',
181 'input' => 'datetime',
182 'with_minutes' => true,
183 'with_seconds' => false,
184 'model_timezone' => null,
185 'view_timezone' => null,
186 'empty_value' => $emptyValue,
187 // Don't modify \DateTime classes by reference, we treat
188 // them like immutable value objects
189 'by_reference' => false,
190 'error_bubbling' => false,
191 // If initialized with a \DateTime object, FormType initializes
192 // this option to "\DateTime". Since the internal, normalized
193 // representation is not \DateTime, but an array, we need to unset
194 // this option.
195 'data_class' => null,
196 'compound' => $compound,
197 ));
198
199 $resolver->setNormalizers(array(
200 'empty_value' => $emptyValueNormalizer,
201 ));
202
203 $resolver->setAllowedValues(array(
204 'input' => array(
205 'datetime',
206 'string',
207 'timestamp',
208 'array',
209 ),
210 'widget' => array(
211 'single_text',
212 'text',
213 'choice',
214 ),
215 ));
216 }
217
218 /**
219 * {@inheritdoc}
220 */
221 public function getName()
222 {
223 return 'time';
224 }
225}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php
new file mode 100644
index 00000000..cd4a2ad3
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php
@@ -0,0 +1,86 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\OptionsResolver\OptionsResolverInterface;
16
17class TimezoneType extends AbstractType
18{
19 /**
20 * Stores the available timezone choices
21 * @var array
22 */
23 private static $timezones;
24
25 /**
26 * {@inheritdoc}
27 */
28 public function setDefaultOptions(OptionsResolverInterface $resolver)
29 {
30 $resolver->setDefaults(array(
31 'choices' => self::getTimezones(),
32 ));
33 }
34
35 /**
36 * {@inheritdoc}
37 */
38 public function getParent()
39 {
40 return 'choice';
41 }
42
43 /**
44 * {@inheritdoc}
45 */
46 public function getName()
47 {
48 return 'timezone';
49 }
50
51 /**
52 * Returns the timezone choices.
53 *
54 * The choices are generated from the ICU function
55 * \DateTimeZone::listIdentifiers(). They are cached during a single request,
56 * so multiple timezone fields on the same page don't lead to unnecessary
57 * overhead.
58 *
59 * @return array The timezone choices
60 */
61 public static function getTimezones()
62 {
63 if (null === static::$timezones) {
64 static::$timezones = array();
65
66 foreach (\DateTimeZone::listIdentifiers() as $timezone) {
67 $parts = explode('/', $timezone);
68
69 if (count($parts) > 2) {
70 $region = $parts[0];
71 $name = $parts[1].' - '.$parts[2];
72 } elseif (count($parts) > 1) {
73 $region = $parts[0];
74 $name = $parts[1];
75 } else {
76 $region = 'Other';
77 $name = $parts[0];
78 }
79
80 static::$timezones[$region][$timezone] = str_replace('_', ' ', $name);
81 }
82 }
83
84 return static::$timezones;
85 }
86}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/UrlType.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/UrlType.php
new file mode 100644
index 00000000..27749b1a
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/UrlType.php
@@ -0,0 +1,54 @@
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
12namespace Symfony\Component\Form\Extension\Core\Type;
13
14use Symfony\Component\Form\AbstractType;
15use Symfony\Component\Form\FormBuilderInterface;
16use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener;
17use Symfony\Component\OptionsResolver\OptionsResolverInterface;
18
19class UrlType extends AbstractType
20{
21 /**
22 * {@inheritdoc}
23 */
24 public function buildForm(FormBuilderInterface $builder, array $options)
25 {
26 $builder->addEventSubscriber(new FixUrlProtocolListener($options['default_protocol']));
27 }
28
29 /**
30 * {@inheritdoc}
31 */
32 public function setDefaultOptions(OptionsResolverInterface $resolver)
33 {
34 $resolver->setDefaults(array(
35 'default_protocol' => 'http',
36 ));
37 }
38
39 /**
40 * {@inheritdoc}
41 */
42 public function getParent()
43 {
44 return 'text';
45 }
46
47 /**
48 * {@inheritdoc}
49 */
50 public function getName()
51 {
52 return 'url';
53 }
54}
diff --git a/vendor/symfony/form/Symfony/Component/Form/Extension/Core/View/ChoiceView.php b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/View/ChoiceView.php
new file mode 100644
index 00000000..97cdd214
--- /dev/null
+++ b/vendor/symfony/form/Symfony/Component/Form/Extension/Core/View/ChoiceView.php
@@ -0,0 +1,55 @@
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
12namespace Symfony\Component\Form\Extension\Core\View;
13
14/**
15 * Represents a choice in templates.
16 *
17 * @author Bernhard Schussek <bschussek@gmail.com>
18 */
19class ChoiceView
20{
21 /**
22 * The original choice value.
23 *
24 * @var mixed
25 */
26 public $data;
27
28 /**
29 * The view representation of the choice.
30 *
31 * @var string
32 */
33 public $value;
34
35 /**
36 * The label displayed to humans.
37 *
38 * @var string
39 */
40 public $label;
41
42 /**
43 * Creates a new ChoiceView.
44 *
45 * @param mixed $data The original choice.
46 * @param string $value The view representation of the choice.
47 * @param string $label The label displayed to humans.
48 */
49 public function __construct($data, $value, $label)
50 {
51 $this->data = $data;
52 $this->value = $value;
53 $this->label = $label;
54 }
55}