From 4f5b44bd3bd490309eb2ba7b44df4769816ba729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Sat, 3 Aug 2013 19:26:54 +0200 Subject: twig implementation --- .../Form/Extension/Core/Type/DateTimeType.php | 281 +++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php (limited to 'vendor/symfony/form/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php') 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 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\Type; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormView; +use Symfony\Component\Form\ReversedTransformer; +use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain; +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer; +use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer; +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; + +class DateTimeType extends AbstractType +{ + const DEFAULT_DATE_FORMAT = \IntlDateFormatter::MEDIUM; + + const DEFAULT_TIME_FORMAT = \IntlDateFormatter::MEDIUM; + + /** + * This is not quite the HTML5 format yet, because ICU lacks the + * capability of parsing and generating RFC 3339 dates, which + * are like the below pattern but with a timezone suffix. The + * timezone suffix is + * + * * "Z" for UTC + * * "(-|+)HH:mm" for other timezones (note the colon!) + * + * For more information see: + * + * http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax + * http://www.w3.org/TR/html-markup/input.datetime.html + * http://tools.ietf.org/html/rfc3339 + * + * An ICU ticket was created: + * http://icu-project.org/trac/ticket/9421 + * + * It was supposedly fixed, but is not available in all PHP installations + * yet. To temporarily circumvent this issue, DateTimeToRfc3339Transformer + * is used when the format matches this constant. + */ + const HTML5_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"; + + private static $acceptedFormats = array( + \IntlDateFormatter::FULL, + \IntlDateFormatter::LONG, + \IntlDateFormatter::MEDIUM, + \IntlDateFormatter::SHORT, + ); + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $parts = array('year', 'month', 'day', 'hour'); + $dateParts = array('year', 'month', 'day'); + $timeParts = array('hour'); + + if ($options['with_minutes']) { + $parts[] = 'minute'; + $timeParts[] = 'minute'; + } + + if ($options['with_seconds']) { + $parts[] = 'second'; + $timeParts[] = 'second'; + } + + $dateFormat = is_int($options['date_format']) ? $options['date_format'] : self::DEFAULT_DATE_FORMAT; + $timeFormat = self::DEFAULT_TIME_FORMAT; + $calendar = \IntlDateFormatter::GREGORIAN; + $pattern = is_string($options['format']) ? $options['format'] : null; + + if (!in_array($dateFormat, self::$acceptedFormats, true)) { + 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.'); + } + + if ('single_text' === $options['widget']) { + if (self::HTML5_FORMAT === $pattern) { + $builder->addViewTransformer(new DateTimeToRfc3339Transformer( + $options['model_timezone'], + $options['view_timezone'] + )); + } else { + $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( + $options['model_timezone'], + $options['view_timezone'], + $dateFormat, + $timeFormat, + $calendar, + $pattern + )); + } + } else { + // Only pass a subset of the options to children + $dateOptions = array_intersect_key($options, array_flip(array( + 'years', + 'months', + 'days', + 'empty_value', + 'required', + 'translation_domain', + ))); + + $timeOptions = array_intersect_key($options, array_flip(array( + 'hours', + 'minutes', + 'seconds', + 'with_minutes', + 'with_seconds', + 'empty_value', + 'required', + 'translation_domain', + ))); + + if (null !== $options['date_widget']) { + $dateOptions['widget'] = $options['date_widget']; + } + + if (null !== $options['time_widget']) { + $timeOptions['widget'] = $options['time_widget']; + } + + if (null !== $options['date_format']) { + $dateOptions['format'] = $options['date_format']; + } + + $dateOptions['input'] = $timeOptions['input'] = 'array'; + $dateOptions['error_bubbling'] = $timeOptions['error_bubbling'] = true; + + $builder + ->addViewTransformer(new DataTransformerChain(array( + new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts), + new ArrayToPartsTransformer(array( + 'date' => $dateParts, + 'time' => $timeParts, + )), + ))) + ->add('date', 'date', $dateOptions) + ->add('time', 'time', $timeOptions) + ; + } + + if ('string' === $options['input']) { + $builder->addModelTransformer(new ReversedTransformer( + new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone']) + )); + } elseif ('timestamp' === $options['input']) { + $builder->addModelTransformer(new ReversedTransformer( + new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) + )); + } elseif ('array' === $options['input']) { + $builder->addModelTransformer(new ReversedTransformer( + new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts) + )); + } + } + + /** + * {@inheritdoc} + */ + public function buildView(FormView $view, FormInterface $form, array $options) + { + $view->vars['widget'] = $options['widget']; + + // Change the input to a HTML5 date input if + // * the widget is set to "single_text" + // * the format matches the one expected by HTML5 + if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { + $view->vars['type'] = 'datetime'; + } + } + + /** + * {@inheritdoc} + */ + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $compound = function (Options $options) { + return $options['widget'] !== 'single_text'; + }; + + // Defaults to the value of "widget" + $dateWidget = function (Options $options) { + return $options['widget']; + }; + + // Defaults to the value of "widget" + $timeWidget = function (Options $options) { + return $options['widget']; + }; + + $resolver->setDefaults(array( + 'input' => 'datetime', + 'model_timezone' => null, + 'view_timezone' => null, + 'format' => self::HTML5_FORMAT, + 'date_format' => null, + 'widget' => null, + 'date_widget' => $dateWidget, + 'time_widget' => $timeWidget, + 'with_minutes' => true, + 'with_seconds' => false, + // Don't modify \DateTime classes by reference, we treat + // them like immutable value objects + 'by_reference' => false, + 'error_bubbling' => false, + // If initialized with a \DateTime object, FormType initializes + // this option to "\DateTime". Since the internal, normalized + // representation is not \DateTime, but an array, we need to unset + // this option. + 'data_class' => null, + 'compound' => $compound, + )); + + // Don't add some defaults in order to preserve the defaults + // set in DateType and TimeType + $resolver->setOptional(array( + 'empty_value', + 'years', + 'months', + 'days', + 'hours', + 'minutes', + 'seconds', + )); + + $resolver->setAllowedValues(array( + 'input' => array( + 'datetime', + 'string', + 'timestamp', + 'array', + ), + 'date_widget' => array( + null, // inherit default from DateType + 'single_text', + 'text', + 'choice', + ), + 'time_widget' => array( + null, // inherit default from TimeType + 'single_text', + 'text', + 'choice', + ), + // This option will overwrite "date_widget" and "time_widget" options + 'widget' => array( + null, // default, don't overwrite options + 'single_text', + 'text', + 'choice', + ), + )); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'datetime'; + } +} -- cgit v1.2.3