Skip to content

Commit

Permalink
Merge branch '6.4' into 7.0
Browse files Browse the repository at this point in the history
* 6.4:
  Add missing return types and enforce return types on all methods
  [ErrorHandler] Do not use ContextAwareNormalizerInterface anymore
  [6.4] Fix various `@psalm-return` annotations
  [WebProfilerBundle] Split and refactor all the JavaScript code
  [HttpClient] Allow custom working directory in TestHttpServer
  Remove ExpectDeprecationTrait where it is not used
  Remove BC layer for HttpFoundation < 6.1
  [Routing] Prevent duplicated methods and schemes in Route
  [DependencyInjection] Add `defined` prefix for env var processor
  🐛 (kernel) when configuring the container add services with php ext
  deprecate using date and time types with date objects with not-matching timezones
  • Loading branch information
nicolas-grekas committed Jun 30, 2023
2 parents 3a4453e + f7783d2 commit 950852a
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 5 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
---

Expand Down
17 changes: 17 additions & 0 deletions Extension/Core/Type/DateTimeType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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']));
}
});
}
}

/**
Expand Down
17 changes: 17 additions & 0 deletions Extension/Core/Type/DateType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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']));
}
});
}
}

/**
Expand Down
15 changes: 15 additions & 0 deletions Extension/Core/Type/TimeType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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']));
}
});
}
}

/**
Expand Down
4 changes: 2 additions & 2 deletions Extension/DataCollector/FormDataCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ protected function getCasters(): array
];
}

private function &recursiveBuildPreliminaryFormTree(FormInterface $form, array &$outputByHash)
private function &recursiveBuildPreliminaryFormTree(FormInterface $form, array &$outputByHash): array
{
$hash = spl_object_hash($form);

Expand All @@ -259,7 +259,7 @@ private function &recursiveBuildPreliminaryFormTree(FormInterface $form, array &
return $output;
}

private function &recursiveBuildFinalFormTree(FormInterface $form = null, FormView $view, array &$outputByHash)
private function &recursiveBuildFinalFormTree(FormInterface $form = null, FormView $view, array &$outputByHash): array
{
$viewHash = spl_object_hash($view);
$formHash = null;
Expand Down
36 changes: 34 additions & 2 deletions Tests/Extension/Core/Type/DateTimeTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -154,7 +157,7 @@ public function testSubmitWithoutMinutes()
'with_minutes' => false,
]);

$form->setData(new \DateTime());
$form->setData(new \DateTime('now', new \DateTimeZone('UTC')));

$input = [
'date' => [
Expand Down Expand Up @@ -184,7 +187,7 @@ public function testSubmitWithSeconds()
'with_seconds' => true,
]);

$form->setData(new \DateTime());
$form->setData(new \DateTime('now', new \DateTimeZone('UTC')));

$input = [
'date' => [
Expand Down Expand Up @@ -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'];
Expand Down
34 changes: 33 additions & 1 deletion Tests/Extension/Core/Type/DateTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -19,6 +20,8 @@

class DateTypeTest extends BaseTypeTestCase
{
use ExpectDeprecationTrait;

public const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\DateType';

private $defaultTimezone;
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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'];
Expand Down
32 changes: 32 additions & 0 deletions Tests/Extension/Core/Type/TimeTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,6 +21,8 @@

class TimeTypeTest extends BaseTypeTestCase
{
use ExpectDeprecationTrait;

public const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\TimeType';

public function testSubmitDateTime()
Expand Down Expand Up @@ -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'];
Expand Down

0 comments on commit 950852a

Please sign in to comment.