From b78bfbc2d4c47e4cec26147462f8e42aca30c608 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 21 May 2022 16:45:39 +0200 Subject: [PATCH] deprecate using date and time types with date objects with not-matching timezones --- UPGRADE-6.4.md | 6 ++++ src/Symfony/Component/Form/CHANGELOG.md | 6 ++++ .../Form/Extension/Core/Type/DateTimeType.php | 17 +++++++++ .../Form/Extension/Core/Type/DateType.php | 17 +++++++++ .../Form/Extension/Core/Type/TimeType.php | 15 ++++++++ .../Extension/Core/Type/DateTimeTypeTest.php | 36 +++++++++++++++++-- .../Extension/Core/Type/DateTypeTest.php | 34 +++++++++++++++++- .../Extension/Core/Type/TimeTypeTest.php | 32 +++++++++++++++++ 8 files changed, 160 insertions(+), 3 deletions(-) diff --git a/UPGRADE-6.4.md b/UPGRADE-6.4.md index b0ac21e7cab95..90dde7a3849c0 100644 --- a/UPGRADE-6.4.md +++ b/UPGRADE-6.4.md @@ -8,6 +8,12 @@ DoctrineBridge * Deprecate not constructing `DoctrineDataCollector` with an instance of `DebugDataHolder` * Deprecate `DoctrineDataCollector::addLogger()`, use a `DebugDataHolder` instead +Form +---- + + * Deprecate using `DateTime` or `DateTimeImmutable` model data with a different timezone than configured with the + `model_timezone` option in `DateType`, `DateTimeType`, and `TimeType` + HttpFoundation -------------- diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 1ff39c9726070..22597f3b47215 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +6.4 +--- + + * Deprecate using `DateTime` or `DateTimeImmutable` model data with a different timezone than configured with the + `model_timezone` option in `DateType`, `DateTimeType`, and `TimeType` + 6.3 --- diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php index 32c58447cdfb2..9ec4c9cca4739 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php @@ -22,6 +22,8 @@ use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\ReversedTransformer; @@ -194,6 +196,21 @@ public function buildForm(FormBuilderInterface $builder, array $options) new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts) )); } + + if (\in_array($options['input'], ['datetime', 'datetime_immutable'], true) && null !== $options['model_timezone']) { + $builder->addEventListener(FormEvents::POST_SET_DATA, static function (FormEvent $event) use ($options): void { + $date = $event->getData(); + + if (!$date instanceof \DateTimeInterface) { + return; + } + + if ($date->getTimezone()->getName() !== $options['model_timezone']) { + trigger_deprecation('symfony/form', '6.4', sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is deprecated.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); + // throw new LogicException(sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is not supported.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); + } + }); + } } /** diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php index 80023affcb000..480afc315f2ad 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -19,6 +19,8 @@ use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\ReversedTransformer; @@ -178,6 +180,21 @@ class_exists(\IntlTimeZone::class, false) ? \IntlTimeZone::createDefault() : nul new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], ['year', 'month', 'day']) )); } + + if (\in_array($options['input'], ['datetime', 'datetime_immutable'], true) && null !== $options['model_timezone']) { + $builder->addEventListener(FormEvents::POST_SET_DATA, static function (FormEvent $event) use ($options): void { + $date = $event->getData(); + + if (!$date instanceof \DateTimeInterface) { + return; + } + + if ($date->getTimezone()->getName() !== $options['model_timezone']) { + trigger_deprecation('symfony/form', '6.4', sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is deprecated.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); + // throw new LogicException(sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is not supported.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); + } + }); + } } /** diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php index c7d5276960831..623259f17a001 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php @@ -208,6 +208,21 @@ public function buildForm(FormBuilderInterface $builder, array $options) new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts, 'text' === $options['widget'], $options['reference_date']) )); } + + if (\in_array($options['input'], ['datetime', 'datetime_immutable'], true) && null !== $options['model_timezone']) { + $builder->addEventListener(FormEvents::POST_SET_DATA, static function (FormEvent $event) use ($options): void { + $date = $event->getData(); + + if (!$date instanceof \DateTimeInterface) { + return; + } + + if ($date->getTimezone()->getName() !== $options['model_timezone']) { + trigger_deprecation('symfony/form', '6.4', sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is deprecated.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); + // throw new LogicException(sprintf('Using a "%s" instance with a timezone ("%s") not matching the configured model timezone "%s" is not supported.', $date::class, $date->getTimezone()->getName(), $options['model_timezone'])); + } + }); + } } /** 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 a2058596eeeee..71020a06b9b44 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -11,11 +11,14 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormInterface; class DateTimeTypeTest extends BaseTypeTestCase { + use ExpectDeprecationTrait; + public const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\DateTimeType'; private $defaultLocale; @@ -154,7 +157,7 @@ public function testSubmitWithoutMinutes() 'with_minutes' => false, ]); - $form->setData(new \DateTime()); + $form->setData(new \DateTime('now', new \DateTimeZone('UTC'))); $input = [ 'date' => [ @@ -184,7 +187,7 @@ public function testSubmitWithSeconds() 'with_seconds' => true, ]); - $form->setData(new \DateTime()); + $form->setData(new \DateTime('now', new \DateTimeZone('UTC'))); $input = [ 'date' => [ @@ -748,6 +751,35 @@ public function testSubmitStringWithCustomInputFormat() $this->assertSame('14/01/2018 21:29:00 +00:00', $form->getData()); } + /** + * @group legacy + */ + public function testDateTimeInputTimezoneNotMatchingModelTimezone() + { + $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); + // $this->expectException(LogicException::class); + // $this->expectExceptionMessage('Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + + $this->factory->create(static::TESTED_TYPE, new \DateTime('now', new \DateTimeZone('UTC')), [ + 'model_timezone' => 'Europe/Berlin', + ]); + } + + /** + * @group legacy + */ + public function testDateTimeImmutableInputTimezoneNotMatchingModelTimezone() + { + $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); + // $this->expectException(LogicException::class); + // $this->expectExceptionMessage('Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + + $this->factory->create(static::TESTED_TYPE, new \DateTimeImmutable('now', new \DateTimeZone('UTC')), [ + 'input' => 'datetime_immutable', + 'model_timezone' => 'Europe/Berlin', + ]); + } + protected function getTestOptions(): array { return ['widget' => 'choice']; 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 abda1a6c071f2..bb171ffe88735 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormInterface; @@ -19,6 +20,8 @@ class DateTypeTest extends BaseTypeTestCase { + use ExpectDeprecationTrait; + public const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\DateType'; private $defaultTimezone; @@ -654,7 +657,7 @@ public function testIsSynchronizedReturnsTrueIfChoiceAndCompletelyEmpty() public function testIsSynchronizedReturnsTrueIfChoiceAndCompletelyFilled() { - $form = $this->factory->create(static::TESTED_TYPE, new \DateTime(), [ + $form = $this->factory->create(static::TESTED_TYPE, new \DateTime('now', new \DateTimeZone('UTC')), [ 'model_timezone' => 'UTC', 'view_timezone' => 'UTC', 'widget' => 'choice', @@ -1112,6 +1115,35 @@ public function testSubmitStringWithCustomInputFormat() $this->assertSame('14/01/2018', $form->getData()); } + /** + * @group legacy + */ + public function testDateTimeInputTimezoneNotMatchingModelTimezone() + { + $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); + // $this->expectException(LogicException::class); + // $this->expectExceptionMessage('Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + + $this->factory->create(static::TESTED_TYPE, new \DateTime('now', new \DateTimeZone('UTC')), [ + 'model_timezone' => 'Europe/Berlin', + ]); + } + + /** + * @group legacy + */ + public function testDateTimeImmutableInputTimezoneNotMatchingModelTimezone() + { + $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); + // $this->expectException(LogicException::class); + // $this->expectExceptionMessage('Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + + $this->factory->create(static::TESTED_TYPE, new \DateTimeImmutable('now', new \DateTimeZone('UTC')), [ + 'input' => 'datetime_immutable', + 'model_timezone' => 'Europe/Berlin', + ]); + } + protected function getTestOptions(): array { return ['widget' => 'choice']; 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 4ed930bbd5381..3e8e42f4a8f7a 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Exception\LogicException; @@ -20,6 +21,8 @@ class TimeTypeTest extends BaseTypeTestCase { + use ExpectDeprecationTrait; + public const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\TimeType'; public function testSubmitDateTime() @@ -1161,6 +1164,35 @@ public static function provideEmptyData() ]; } + /** + * @group legacy + */ + public function testDateTimeInputTimezoneNotMatchingModelTimezone() + { + $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); + // $this->expectException(LogicException::class); + // $this->expectExceptionMessage('Using a "DateTime" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + + $this->factory->create(static::TESTED_TYPE, new \DateTime('now', new \DateTimeZone('UTC')), [ + 'model_timezone' => 'Europe/Berlin', + ]); + } + + /** + * @group legacy + */ + public function testDateTimeImmutableInputTimezoneNotMatchingModelTimezone() + { + $this->expectDeprecation('Since symfony/form 6.4: Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is deprecated.'); + // $this->expectException(LogicException::class); + // $this->expectExceptionMessage('Using a "DateTimeImmutable" instance with a timezone ("UTC") not matching the configured model timezone "Europe/Berlin" is not supported.'); + + $this->factory->create(static::TESTED_TYPE, new \DateTimeImmutable('now', new \DateTimeZone('UTC')), [ + 'input' => 'datetime_immutable', + 'model_timezone' => 'Europe/Berlin', + ]); + } + protected function getTestOptions(): array { return ['widget' => 'choice']; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy