From 8d60d72043afc9d7387ead935d70c87c2a2518dd Mon Sep 17 00:00:00 2001 From: James Halsall Date: Wed, 7 Sep 2016 17:10:21 +0100 Subject: [PATCH] [Form] Add support for \DateTimeImmutable to date types --- .../BaseDateTimeTransformer.php | 12 ++- .../DateTimeToArrayTransformer.php | 10 ++- .../DateTimeToLocalizedStringTransformer.php | 13 +-- .../DateTimeToRfc3339Transformer.php | 6 +- .../DateTimeToStringTransformer.php | 13 +-- .../Form/Extension/Core/Type/DateTimeType.php | 10 ++- .../Form/Extension/Core/Type/DateType.php | 7 +- .../Form/Extension/Core/Type/TimeType.php | 7 +- .../Component/Form/Test/TypeTestCase.php | 2 +- .../Extension/Core/Type/DateTimeTypeTest.php | 84 +++++++++++++++---- .../Extension/Core/Type/DateTypeTest.php | 71 +++++++++++----- .../Extension/Core/Type/TimeTypeTest.php | 58 +++++++++---- 12 files changed, 213 insertions(+), 80 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php index 309d46074e00f..595fab863c1fe 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php @@ -29,16 +29,19 @@ abstract class BaseDateTimeTransformer implements DataTransformerInterface protected $outputTimezone; + protected $immutable; + /** * Constructor. * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone + * @param bool $immutable Whether to use \DateTimeImmutable instead of \DateTime * * @throws UnexpectedTypeException if a timezone is not a string * @throws InvalidArgumentException if a timezone is not valid */ - public function __construct($inputTimezone = null, $outputTimezone = null) + public function __construct($inputTimezone = null, $outputTimezone = null, $immutable = false) { if (null !== $inputTimezone && !is_string($inputTimezone)) { throw new UnexpectedTypeException($inputTimezone, 'string'); @@ -63,5 +66,12 @@ public function __construct($inputTimezone = null, $outputTimezone = null) } catch (\Exception $e) { throw new InvalidArgumentException(sprintf('Output timezone is invalid: %s.', $this->outputTimezone), $e->getCode(), $e); } + + $this->immutable = $immutable; + } + + protected function getDateTimeClass() + { + return true === $this->immutable ? \DateTimeImmutable::class : \DateTime::class; } } diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php index 6d6a874e02862..bc81b6489f8fc 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php @@ -33,12 +33,13 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer * @param string $outputTimezone The output timezone * @param array $fields The date fields * @param bool $pad Whether to use padding + * @param bool $immutable Whether to use \DateTimeImmutable instead of \DateTime * * @throws UnexpectedTypeException if a timezone is not a string */ - public function __construct($inputTimezone = null, $outputTimezone = null, array $fields = null, $pad = false) + public function __construct($inputTimezone = null, $outputTimezone = null, array $fields = null, $pad = false, $immutable = false) { - parent::__construct($inputTimezone, $outputTimezone); + parent::__construct($inputTimezone, $outputTimezone, $immutable); if (null === $fields) { $fields = array('year', 'month', 'day', 'hour', 'minute', 'second'); @@ -108,7 +109,7 @@ public function transform($dateTime) * * @param array $value Localized date * - * @return \DateTime Normalized date + * @return \DateTimeInterface Normalized date * * @throws TransformationFailedException If the given value is not an array, * if the value could not be transformed @@ -170,7 +171,8 @@ public function reverseTransform($value) } try { - $dateTime = new \DateTime(sprintf( + $dateTimeClass = $this->getDateTimeClass(); + $dateTime = new $dateTimeClass(sprintf( '%s-%s-%s %s:%s:%s', empty($value['year']) ? '1970' : $value['year'], empty($value['month']) ? '1' : $value['month'], diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index 8434f8932bab1..359febcdd3464 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -38,12 +38,13 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer * @param int $timeFormat The time format * @param int $calendar One of the \IntlDateFormatter calendar constants * @param string $pattern A pattern to pass to \IntlDateFormatter + * @param bool $immutable Whether to use \DateTimeImmutable instead of \DateTime * * @throws UnexpectedTypeException If a format is not supported or if a timezone is not a string */ - public function __construct($inputTimezone = null, $outputTimezone = null, $dateFormat = null, $timeFormat = null, $calendar = \IntlDateFormatter::GREGORIAN, $pattern = null) + public function __construct($inputTimezone = null, $outputTimezone = null, $dateFormat = null, $timeFormat = null, $calendar = \IntlDateFormatter::GREGORIAN, $pattern = null, $immutable = false) { - parent::__construct($inputTimezone, $outputTimezone); + parent::__construct($inputTimezone, $outputTimezone, $immutable); if (null === $dateFormat) { $dateFormat = \IntlDateFormatter::MEDIUM; @@ -101,7 +102,7 @@ public function transform($dateTime) * * @param string|array $value Localized date string/array * - * @return \DateTime Normalized date + * @return \DateTimeInterface Normalized date * * @throws TransformationFailedException if the given value is not a string, * if the date could not be parsed @@ -126,14 +127,16 @@ public function reverseTransform($value) throw new TransformationFailedException(intl_get_error_message()); } + $dateTimeClass = $this->getDateTimeClass(); + try { if ($dateOnly) { // we only care about year-month-date, which has been delivered as a timestamp pointing to UTC midnight - return new \DateTime(gmdate('Y-m-d', $timestamp), new \DateTimeZone($this->inputTimezone)); + return new $dateTimeClass(gmdate('Y-m-d', $timestamp), new \DateTimeZone($this->inputTimezone)); } // read timestamp into DateTime object - the formatter delivers a timestamp - $dateTime = new \DateTime(sprintf('@%s', $timestamp)); + $dateTime = new $dateTimeClass(sprintf('@%s', $timestamp)); // set timezone separately, as it would be ignored if set via the constructor, // see http://php.net/manual/en/datetime.construct.php $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php index 550ea9b50f67e..3ce991f0ca761 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php @@ -53,7 +53,7 @@ public function transform($dateTime) * * @param string $rfc3339 Formatted string * - * @return \DateTime Normalized date + * @return \DateTimeInterface Normalized date * * @throws TransformationFailedException If the given value is not a string, * if the value could not be transformed @@ -68,8 +68,10 @@ public function reverseTransform($rfc3339) return; } + $dateTimeClass = $this->getDateTimeClass(); + try { - $dateTime = new \DateTime($rfc3339); + $dateTime = new $dateTimeClass($rfc3339); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index 7d29b6b88c1af..89c20d06b963b 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -58,12 +58,13 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer * @param string $outputTimezone The name of the output timezone * @param string $format The date format * @param bool $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format + * @param bool $immutable Whether to use \DateTimeImmutable instead of \DateTime * * @throws UnexpectedTypeException if a timezone is not a string */ - public function __construct($inputTimezone = null, $outputTimezone = null, $format = 'Y-m-d H:i:s', $parseUsingPipe = true) + public function __construct($inputTimezone = null, $outputTimezone = null, $format = 'Y-m-d H:i:s', $parseUsingPipe = true, $immutable = false) { - parent::__construct($inputTimezone, $outputTimezone); + parent::__construct($inputTimezone, $outputTimezone, $immutable); $this->generateFormat = $this->parseFormat = $format; $this->parseUsingPipe = $parseUsingPipe || null === $parseUsingPipe; @@ -115,7 +116,7 @@ public function transform($dateTime) * * @param string $value A value as produced by PHP's date() function * - * @return \DateTime An instance of \DateTime + * @return \DateTimeInterface An instance of \DateTime * * @throws TransformationFailedException If the given value is not a string, * or could not be transformed @@ -130,10 +131,12 @@ public function reverseTransform($value) throw new TransformationFailedException('Expected a string.'); } + $dateTimeClass = $this->getDateTimeClass(); + $outputTz = new \DateTimeZone($this->outputTimezone); - $dateTime = \DateTime::createFromFormat($this->parseFormat, $value, $outputTz); + $dateTime = $dateTimeClass::createFromFormat($this->parseFormat, $value, $outputTz); - $lastErrors = \DateTime::getLastErrors(); + $lastErrors = $dateTimeClass::getLastErrors(); if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) { throw new TransformationFailedException( diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php index c538c09a00737..6c323bcff35e1 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php @@ -87,6 +87,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $timeFormat = self::DEFAULT_TIME_FORMAT; $calendar = \IntlDateFormatter::GREGORIAN; $pattern = is_string($options['format']) ? $options['format'] : null; + $immutable = 'datetimeimmutable' === $options['input']; 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.'); @@ -96,7 +97,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) if (self::HTML5_FORMAT === $pattern) { $builder->addViewTransformer(new DateTimeToRfc3339Transformer( $options['model_timezone'], - $options['view_timezone'] + $options['view_timezone'], + $immutable )); } else { $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( @@ -105,7 +107,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) $dateFormat, $timeFormat, $calendar, - $pattern + $pattern, + $immutable )); } } else { @@ -155,7 +158,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder ->addViewTransformer(new DataTransformerChain(array( - new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts), + new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, false, $immutable), new ArrayToPartsTransformer(array( 'date' => $dateParts, 'time' => $timeParts, @@ -255,6 +258,7 @@ public function configureOptions(OptionsResolver $resolver) $resolver->setAllowedValues('input', array( 'datetime', + 'datetimeimmutable', 'string', 'timestamp', 'array', diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php index ca26ae572e363..3cb4cab2595c6 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -51,6 +51,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $timeFormat = \IntlDateFormatter::NONE; $calendar = \IntlDateFormatter::GREGORIAN; $pattern = is_string($options['format']) ? $options['format'] : null; + $immutable = 'datetimeimmutable' === $options['input']; if (!in_array($dateFormat, self::$acceptedFormats, true)) { throw new InvalidOptionsException('The "format" option must be one of the IntlDateFormatter constants (FULL, LONG, MEDIUM, SHORT) or a string representing a custom format.'); @@ -67,7 +68,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) $dateFormat, $timeFormat, $calendar, - $pattern + $pattern, + $immutable )); } else { $yearOptions = $monthOptions = $dayOptions = array( @@ -113,7 +115,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->add('month', self::$widgets[$options['widget']], $monthOptions) ->add('day', self::$widgets[$options['widget']], $dayOptions) ->addViewTransformer(new DateTimeToArrayTransformer( - $options['model_timezone'], $options['view_timezone'], array('year', 'month', 'day') + $options['model_timezone'], $options['view_timezone'], array('year', 'month', 'day'), false, $immutable )) ->setAttribute('formatter', $formatter) ; @@ -254,6 +256,7 @@ public function configureOptions(OptionsResolver $resolver) $resolver->setAllowedValues('input', array( 'datetime', + 'datetimeimmutable', 'string', 'timestamp', 'array', diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php index 60fbeb5826153..e9ca6cbb7658a 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php @@ -52,8 +52,10 @@ public function buildForm(FormBuilderInterface $builder, array $options) $parts[] = 'second'; } + $immutable = 'datetimeimmutable' === $options['input']; + if ('single_text' === $options['widget']) { - $builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format)); + $builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format, true, $immutable)); } else { $hourOptions = $minuteOptions = $secondOptions = array( 'error_bubbling' => true, @@ -117,7 +119,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->add('second', self::$widgets[$options['widget']], $secondOptions); } - $builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget'])); + $builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget'], $immutable)); } if ('string' === $options['input']) { @@ -239,6 +241,7 @@ public function configureOptions(OptionsResolver $resolver) $resolver->setAllowedValues('input', array( 'datetime', + 'datetimeimmutable', 'string', 'timestamp', 'array', diff --git a/src/Symfony/Component/Form/Test/TypeTestCase.php b/src/Symfony/Component/Form/Test/TypeTestCase.php index ff3f78292f5f0..6a86dedb2b5d9 100644 --- a/src/Symfony/Component/Form/Test/TypeTestCase.php +++ b/src/Symfony/Component/Form/Test/TypeTestCase.php @@ -34,7 +34,7 @@ protected function setUp() $this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory); } - public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) + public static function assertDateTimeEquals(\DateTimeInterface $expected, \DateTimeInterface $actual) { self::assertEquals($expected->format('c'), $actual->format('c')); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php index 29df5231f1320..859077dc7580a 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -23,7 +23,10 @@ protected function setUp() parent::setUp(); } - public function testSubmitDateTime() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitDateTime($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\DateTimeType', null, array( 'model_timezone' => 'UTC', @@ -31,7 +34,7 @@ public function testSubmitDateTime() 'date_widget' => 'choice', 'years' => array(2010), 'time_widget' => 'choice', - 'input' => 'datetime', + 'input' => $inputType, )); $form->submit(array( @@ -46,9 +49,11 @@ public function testSubmitDateTime() ), )); - $dateTime = new \DateTime('2010-06-02 03:04:00 UTC'); + $dateTime = new $dateTimeClass('2010-06-02 03:04:00 UTC'); + $data = $form->getData(); - $this->assertDateTimeEquals($dateTime, $form->getData()); + $this->assertInstanceOf($dateTimeClass, $data); + $this->assertDateTimeEquals($dateTime, $data); } public function testSubmitString() @@ -105,7 +110,10 @@ public function testSubmitTimestamp() $this->assertEquals($dateTime->format('U'), $form->getData()); } - public function testSubmitWithoutMinutes() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitWithoutMinutes($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\DateTimeType', null, array( 'model_timezone' => 'UTC', @@ -113,11 +121,11 @@ public function testSubmitWithoutMinutes() 'date_widget' => 'choice', 'years' => array(2010), 'time_widget' => 'choice', - 'input' => 'datetime', + 'input' => $inputType, 'with_minutes' => false, )); - $form->setData(new \DateTime()); + $form->setData(new $dateTimeClass()); $input = array( 'date' => array( @@ -132,10 +140,14 @@ public function testSubmitWithoutMinutes() $form->submit($input); - $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:00:00 UTC'), $form->getData()); + $this->assertInstanceOf($dateTimeClass, $form->getData()); + $this->assertDateTimeEquals(new $dateTimeClass('2010-06-02 03:00:00 UTC'), $form->getData()); } - public function testSubmitWithSeconds() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitWithSeconds($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\DateTimeType', null, array( 'model_timezone' => 'UTC', @@ -143,11 +155,11 @@ public function testSubmitWithSeconds() 'date_widget' => 'choice', 'years' => array(2010), 'time_widget' => 'choice', - 'input' => 'datetime', + 'input' => $inputType, 'with_seconds' => true, )); - $form->setData(new \DateTime()); + $form->setData(new $dateTimeClass()); $input = array( 'date' => array( @@ -164,7 +176,8 @@ public function testSubmitWithSeconds() $form->submit($input); - $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:04:05 UTC'), $form->getData()); + $this->assertInstanceOf($dateTimeClass, $form->getData()); + $this->assertDateTimeEquals(new $dateTimeClass('2010-06-02 03:04:05 UTC'), $form->getData()); } public function testSubmitDifferentTimezones() @@ -199,21 +212,25 @@ public function testSubmitDifferentTimezones() $this->assertEquals($dateTime->format('Y-m-d H:i:s'), $form->getData()); } - public function testSubmitDifferentTimezonesDateTime() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitDifferentTimezonesDateTime($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\DateTimeType', null, array( 'model_timezone' => 'America/New_York', 'view_timezone' => 'Pacific/Tahiti', 'widget' => 'single_text', - 'input' => 'datetime', + 'input' => $inputType, )); - $outputTime = new \DateTime('2010-06-02 03:04:00 Pacific/Tahiti'); + $outputTime = new $dateTimeClass('2010-06-02 03:04:00 Pacific/Tahiti'); $form->submit('2010-06-02T03:04:00-10:00'); $outputTime->setTimezone(new \DateTimeZone('America/New_York')); + $this->assertInstanceOf($dateTimeClass, $form->getData()); $this->assertDateTimeEquals($outputTime, $form->getData()); $this->assertEquals('2010-06-02T03:04:00-10:00', $form->getViewData()); } @@ -249,25 +266,56 @@ public function testSubmitStringSingleTextWithSeconds() $this->assertEquals('2010-06-02T03:04:05Z', $form->getViewData()); } - public function testSubmitDifferentPattern() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitDifferentPattern($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\DateTimeType', null, array( 'date_format' => 'MM*yyyy*dd', 'date_widget' => 'single_text', 'time_widget' => 'single_text', - 'input' => 'datetime', + 'input' => $inputType, )); - $dateTime = new \DateTime('2010-06-02 03:04'); + $dateTime = new $dateTimeClass('2010-06-02 03:04'); $form->submit(array( 'date' => '06*2010*02', 'time' => '03:04', )); + $this->assertInstanceOf($dateTimeClass, $form->getData()); $this->assertDateTimeEquals($dateTime, $form->getData()); } + /** + * @@dataProvider provideDateTimeClasses + */ + public function testSubmitDifferentPatternWithSingleWidget($dateTimeClass, $inputType) + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\DateTimeType', null, array( + 'format' => 'yyyy-MM-dd HH:mm', + 'widget' => 'single_text', + 'input' => $inputType, + )); + + $dateTime = new $dateTimeClass('2016-09-07 10:00'); + + $form->submit('2016-09-07 10:00'); + + $this->assertInstanceOf($dateTimeClass, $form->getData()); + $this->assertDateTimeEquals($dateTime, $form->getData()); + } + + public function provideDateTimeClasses() + { + return array( + array(\DateTime::class, 'datetime'), + array(\DateTimeImmutable::class, 'datetimeimmutable'), + ); + } + public function testInitializeWithDateTime() { // Throws an exception if "data_class" option is not explicitly set diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php index 1ee36fe0d6660..4ed7c8f25d313 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -52,22 +52,29 @@ public function testInvalidInputOption() )); } - public function testSubmitFromSingleTextDateTimeWithDefaultFormat() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitFromSingleTextDateTimeWithDefaultFormat($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\DateType', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', - 'input' => 'datetime', + 'input' => $inputType, )); $form->submit('2010-06-02'); - $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); + $this->assertInstanceOf($dateTimeClass, $form->getData()); + $this->assertDateTimeEquals(new $dateTimeClass('2010-06-02 UTC'), $form->getData()); $this->assertEquals('2010-06-02', $form->getViewData()); } - public function testSubmitFromSingleTextDateTime() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitFromSingleTextDateTime($dateTimeClass, $inputType) { // we test against "de_AT", so we need the full implementation IntlTestHelper::requireFullIntl($this); @@ -79,12 +86,13 @@ public function testSubmitFromSingleTextDateTime() 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'single_text', - 'input' => 'datetime', + 'input' => $inputType, )); $form->submit('2.6.2010'); - $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); + $this->assertInstanceOf($dateTimeClass, $form->getData()); + $this->assertDateTimeEquals(new $dateTimeClass('2010-06-02 UTC'), $form->getData()); $this->assertEquals('02.06.2010', $form->getViewData()); } @@ -159,12 +167,16 @@ public function testSubmitFromSingleTextRaw() $this->assertEquals('02.06.2010', $form->getViewData()); } - public function testSubmitFromText() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitFromText($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\DateType', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'text', + 'input' => $inputType, )); $text = array( @@ -175,19 +187,22 @@ public function testSubmitFromText() $form->submit($text); - $dateTime = new \DateTime('2010-06-02 UTC'); - - $this->assertDateTimeEquals($dateTime, $form->getData()); + $this->assertInstanceOf($dateTimeClass, $form->getData()); + $this->assertDateTimeEquals(new $dateTimeClass('2010-06-02 UTC'), $form->getData()); $this->assertEquals($text, $form->getViewData()); } - public function testSubmitFromChoice() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitFromChoice($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\DateType', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', 'years' => array(2010), + 'input' => $inputType, )); $text = array( @@ -198,9 +213,8 @@ public function testSubmitFromChoice() $form->submit($text); - $dateTime = new \DateTime('2010-06-02 UTC'); - - $this->assertDateTimeEquals($dateTime, $form->getData()); + $this->assertInstanceOf($dateTimeClass, $form->getData()); + $this->assertDateTimeEquals(new $dateTimeClass('2010-06-02 UTC'), $form->getData()); $this->assertEquals($text, $form->getViewData()); } @@ -225,19 +239,23 @@ public function testSubmitFromChoiceEmpty() $this->assertEquals($text, $form->getViewData()); } - public function testSubmitFromInputDateTimeDifferentPattern() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitFromInputDateTimeDifferentPattern($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\DateType', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', - 'input' => 'datetime', + 'input' => $inputType, )); $form->submit('06*2010*02'); - $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); + $this->assertInstanceOf($dateTimeClass, $form->getData()); + $this->assertDateTimeEquals(new $dateTimeClass('2010-06-02 UTC'), $form->getData()); $this->assertEquals('06*2010*02', $form->getViewData()); } @@ -418,7 +436,10 @@ public function testSetDataWithNegativeTimezoneOffsetStringInput() $this->assertEquals('01.06.2010', $form->getViewData()); } - public function testSetDataWithNegativeTimezoneOffsetDateTimeInput() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSetDataWithNegativeTimezoneOffsetDateTimeInput($dateTimeClass, $inputType) { // we test against "de_AT", so we need the full implementation IntlTestHelper::requireFullIntl($this); @@ -429,20 +450,30 @@ public function testSetDataWithNegativeTimezoneOffsetDateTimeInput() 'format' => \IntlDateFormatter::MEDIUM, 'model_timezone' => 'UTC', 'view_timezone' => 'America/New_York', - 'input' => 'datetime', + 'input' => $inputType, 'widget' => 'single_text', )); - $dateTime = new \DateTime('2010-06-02 UTC'); + $dateTime = new $dateTimeClass('2010-06-02 UTC'); $form->setData($dateTime); + $this->assertInstanceOf($dateTimeClass, $form->getData()); + // 2010-06-02 00:00:00 UTC // 2010-06-01 20:00:00 UTC-4 $this->assertDateTimeEquals($dateTime, $form->getData()); $this->assertEquals('01.06.2010', $form->getViewData()); } + public function provideDateTimeClasses() + { + return array( + array(\DateTime::class, 'datetime'), + array(\DateTimeImmutable::class, 'datetimeimmutable'), + ); + } + public function testYearsOption() { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\DateType', null, array( diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php index 7e10d326f89ae..c96bfd56f989c 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php @@ -17,12 +17,15 @@ class TimeTypeTest extends TestCase { - public function testSubmitDateTime() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitDateTime($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\TimeType', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', - 'input' => 'datetime', + 'input' => $inputType, )); $input = array( @@ -32,9 +35,8 @@ public function testSubmitDateTime() $form->submit($input); - $dateTime = new \DateTime('1970-01-01 03:04:00 UTC'); - - $this->assertEquals($dateTime, $form->getData()); + $this->assertInstanceOf($dateTimeClass, $form->getData()); + $this->assertEquals(new $dateTimeClass('1970-01-01 03:04:00 UTC'), $form->getData()); $this->assertEquals($input, $form->getViewData()); } @@ -97,34 +99,42 @@ public function testSubmitArray() $this->assertEquals($input, $form->getViewData()); } - public function testSubmitDatetimeSingleText() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitDatetimeSingleText($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\TimeType', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', - 'input' => 'datetime', + 'input' => $inputType, 'widget' => 'single_text', )); $form->submit('03:04'); - $this->assertEquals(new \DateTime('1970-01-01 03:04:00 UTC'), $form->getData()); + $this->assertInstanceOf($dateTimeClass, $form->getData()); + $this->assertEquals(new $dateTimeClass('1970-01-01 03:04:00 UTC'), $form->getData()); $this->assertEquals('03:04', $form->getViewData()); } - public function testSubmitDatetimeSingleTextWithoutMinutes() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSubmitDatetimeSingleTextWithoutMinutes($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\TimeType', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', - 'input' => 'datetime', + 'input' => $inputType, 'widget' => 'single_text', 'with_minutes' => false, )); $form->submit('03'); - $this->assertEquals(new \DateTime('1970-01-01 03:00:00 UTC'), $form->getData()); + $this->assertInstanceOf($dateTimeClass, $form->getData()); + $this->assertEquals(new $dateTimeClass('1970-01-01 03:00:00 UTC'), $form->getData()); $this->assertEquals('03', $form->getViewData()); } @@ -221,34 +231,48 @@ public function testSubmitStringSingleTextWithoutMinutes() $this->assertEquals('03', $form->getViewData()); } - public function testSetDataWithoutMinutes() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSetDataWithoutMinutes($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\TimeType', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', - 'input' => 'datetime', + 'input' => $inputType, 'with_minutes' => false, )); - $form->setData(new \DateTime('03:04:05 UTC')); + $form->setData(new $dateTimeClass('03:04:05 UTC')); $this->assertEquals(array('hour' => 3), $form->getViewData()); } - public function testSetDataWithSeconds() + /** + * @dataProvider provideDateTimeClasses + */ + public function testSetDataWithSeconds($dateTimeClass, $inputType) { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\TimeType', null, array( 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', - 'input' => 'datetime', + 'input' => $inputType, 'with_seconds' => true, )); - $form->setData(new \DateTime('03:04:05 UTC')); + $form->setData(new $dateTimeClass('03:04:05 UTC')); $this->assertEquals(array('hour' => 3, 'minute' => 4, 'second' => 5), $form->getViewData()); } + public function provideDateTimeClasses() + { + return array( + array(\DateTime::class, 'datetime'), + array(\DateTimeImmutable::class, 'datetimeimmutable'), + ); + } + public function testSetDataDifferentTimezones() { $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\TimeType', null, array(