diff options
Diffstat (limited to 'vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php')
-rw-r--r-- | vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php | 281 |
1 files changed, 281 insertions, 0 deletions
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 | |||
12 | namespace Symfony\Component\Form\Extension\Core\Type; | ||
13 | |||
14 | use Symfony\Component\Form\AbstractType; | ||
15 | use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; | ||
16 | use Symfony\Component\Form\FormInterface; | ||
17 | use Symfony\Component\Form\FormBuilderInterface; | ||
18 | use Symfony\Component\Form\FormView; | ||
19 | use Symfony\Component\Form\ReversedTransformer; | ||
20 | use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain; | ||
21 | use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; | ||
22 | use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; | ||
23 | use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; | ||
24 | use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; | ||
25 | use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer; | ||
26 | use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer; | ||
27 | use Symfony\Component\OptionsResolver\Options; | ||
28 | use Symfony\Component\OptionsResolver\OptionsResolverInterface; | ||
29 | |||
30 | class 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 | } | ||