diff --git a/UPGRADE-7.3.md b/UPGRADE-7.3.md index 61f69a3acf377..694926221fd8f 100644 --- a/UPGRADE-7.3.md +++ b/UPGRADE-7.3.md @@ -41,6 +41,7 @@ Serializer ---------- * Deprecate the `CompiledClassMetadataFactory` and `CompiledClassMetadataCacheWarmer` classes + * Deprecate datetime constructor as a fallback, in version 8.0 a `Symfony\Component\Serializer\Exception\NotNormalizableValueException` will be thrown when a date could not be parsed using the default format. VarDumper --------- diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 525651fce454e..bc9ff083c1462 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Deprecate the `CompiledClassMetadataFactory` and `CompiledClassMetadataCacheWarmer` classes + * Deprecate datetime constructor as a fallback, in version 8.0 a `Symfony\Component\Serializer\Exception\NotNormalizableValueException` will be thrown when a date could not be parsed using the default format 7.2 --- diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index dfc498c19f194..cae01c3ed859e 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -126,6 +126,8 @@ public function denormalize(mixed $data, string $type, ?string $format = null, a if (false !== $object = $type::createFromFormat($defaultDateTimeFormat, $data, $timezone)) { return $object; } + + trigger_deprecation('symfony/serializer', '7.3', \sprintf('A "%s" will be thrown when a date could not be parsed using the default format "%s".', NotNormalizableValueException::class, $defaultDateTimeFormat)); } return new $type($data, $timezone); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php index 81219652b3ef1..899e0a09b1efa 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Serializer\Tests\Normalizer; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; @@ -21,6 +22,8 @@ */ class DateTimeNormalizerTest extends TestCase { + use ExpectDeprecationTrait; + private DateTimeNormalizer $normalizer; protected function setUp(): void @@ -242,15 +245,25 @@ public function testDenormalize() $this->assertEquals(new \DateTimeImmutable('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016-01-01T00:00:00+00:00', \DateTimeInterface::class)); $this->assertEquals(new \DateTimeImmutable('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016-01-01T00:00:00+00:00', \DateTimeImmutable::class)); $this->assertEquals(new \DateTime('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016-01-01T00:00:00+00:00', \DateTime::class)); - $this->assertEquals(new \DateTime('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize(' 2016-01-01T00:00:00+00:00 ', \DateTime::class)); $this->assertEquals(new DateTimeImmutableChild('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016-01-01T00:00:00+00:00', DateTimeImmutableChild::class)); $this->assertEquals(new DateTimeImmutableChild('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016-01-01T00:00:00+00:00', DateTimeImmutableChild::class)); $this->assertEquals(new DateTimeChild('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016-01-01T00:00:00+00:00', DateTimeChild::class)); - $this->assertEquals(new DateTimeChild('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize(' 2016-01-01T00:00:00+00:00 ', DateTimeChild::class)); $this->assertEquals(new \DateTimeImmutable('2023-05-06T17:35:34.000000+0000', new \DateTimeZone('UTC')), $this->normalizer->denormalize(1683394534, \DateTimeImmutable::class, null, [DateTimeNormalizer::FORMAT_KEY => 'U'])); $this->assertEquals(new \DateTimeImmutable('2023-05-06T17:35:34.123400+0000', new \DateTimeZone('UTC')), $this->normalizer->denormalize(1683394534.1234, \DateTimeImmutable::class, null, [DateTimeNormalizer::FORMAT_KEY => 'U.u'])); } + /** + * @group legacy + */ + public function testDenormalizeAndShowDeprecation() + { + $this->expectDeprecation('Since symfony/serializer 7.3: A "Symfony\Component\Serializer\Exception\NotNormalizableValueException" will be thrown when a date could not be parsed using the default format "Y-m-d\TH:i:sP".'); + $this->assertEquals(new \DateTime('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize(' 2016-01-01T00:00:00+00:00 ', \DateTime::class)); + + $this->expectDeprecation('Since symfony/serializer 7.3: A "Symfony\Component\Serializer\Exception\NotNormalizableValueException" will be thrown when a date could not be parsed using the default format "Y-m-d\TH:i:sP".'); + $this->assertEquals(new DateTimeChild('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize(' 2016-01-01T00:00:00+00:00 ', DateTimeChild::class, null, [DateTimeNormalizer::FORMAT_KEY => null])); + } + public function testDenormalizeUsingTimezonePassedInConstructor() { $timezone = new \DateTimeZone('Japan'); @@ -284,15 +297,11 @@ public function testDenormalizeUsingTimezonePassedInContext($input, $expected, $ public static function denormalizeUsingTimezonePassedInContextProvider() { - yield 'with timezone' => [ - '2016/12/01 17:35:00', - new \DateTimeImmutable('2016/12/01 17:35:00', new \DateTimeZone('Japan')), - new \DateTimeZone('Japan'), - ]; yield 'with timezone as string' => [ '2016/12/01 17:35:00', new \DateTimeImmutable('2016/12/01 17:35:00', new \DateTimeZone('Japan')), 'Japan', + 'Y/m/d H:i:s', ]; yield 'with format without timezone information' => [ '2016.12.01 17:35:00', @@ -308,8 +317,12 @@ public static function denormalizeUsingTimezonePassedInContextProvider() ]; } + /** + * @group legacy + */ public function testDenormalizeInvalidDataThrowsException() { + $this->expectDeprecation('Since symfony/serializer 7.3: A "Symfony\Component\Serializer\Exception\NotNormalizableValueException" will be thrown when a date could not be parsed using the default format "Y-m-d\TH:i:sP".'); $this->expectException(UnexpectedValueException::class); $this->normalizer->denormalize('invalid date', \DateTimeInterface::class); } @@ -376,10 +389,14 @@ public function testDenormalizeDateTimeStringWithDefaultContextFormat() $this->assertSame('01/10/2018', $denormalizedDate->format($format)); } + /** + * @group legacy + */ public function testDenormalizeDateTimeStringWithDefaultContextAllowsErrorFormat() { $format = 'd/m/Y'; // the default format $string = '2020-01-01'; // the value which is in the wrong format, but is accepted because of `new \DateTimeImmutable` in DateTimeNormalizer::denormalize + $this->expectDeprecation('Since symfony/serializer 7.3: A "Symfony\Component\Serializer\Exception\NotNormalizableValueException" will be thrown when a date could not be parsed using the default format "d/m/Y".'); $normalizer = new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => $format]); $denormalizedDate = $normalizer->denormalize($string, \DateTimeInterface::class); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index d45586b4444ee..9885d8afea00b 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -718,7 +718,7 @@ public function testDenomalizeRecursive() 'inner' => ['foo' => 'foo', 'bar' => 'bar'], 'date' => '1988/01/21', 'inners' => [['foo' => 1], ['foo' => 2]], - ], ObjectOuter::class); + ], ObjectOuter::class, null, ['datetime_format' => 'Y/m/d']); $this->assertSame('foo', $obj->getInner()->foo); $this->assertSame('bar', $obj->getInner()->bar);