diff --git a/UPGRADE-7.4.md b/UPGRADE-7.4.md index 487bf6f5007a6..e6de8bedc4918 100644 --- a/UPGRADE-7.4.md +++ b/UPGRADE-7.4.md @@ -22,3 +22,8 @@ HttpClient ---------- * Deprecate using amphp/http-client < 5 + +Serializer +---------- + + * 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. diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 1b5c95cd39443..2e800a62af044 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.4 +--- + + * 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.3 --- diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index a136ec227a3ae..e520063531f13 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -128,7 +128,11 @@ public function denormalize(mixed $data, string $type, ?string $format = null, a } } - return new $type($data, $timezone); + $dateTimeObject = new $type($data, $timezone); + + trigger_deprecation('symfony/serializer', '7.4', \sprintf('A "%s" will be thrown when a date could not be parsed using the default format "%s".', NotNormalizableValueException::class, $defaultDateTimeFormat)); + + return $dateTimeObject; } catch (NotNormalizableValueException $e) { throw $e; } catch (\Exception $e) { diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php index 81219652b3ef1..dfe80452522ec 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.4: 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.4: 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', @@ -376,10 +385,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.4: 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 439dce056995c..fd59f97831761 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -717,7 +717,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);