diff --git a/DependencyInjection/SerializerPass.php b/DependencyInjection/SerializerPass.php index 994f6124..f5f2cc38 100644 --- a/DependencyInjection/SerializerPass.php +++ b/DependencyInjection/SerializerPass.php @@ -89,6 +89,10 @@ private function createNamedSerializerTags(ContainerBuilder $container, string $ foreach ($container->findTaggedServiceIds($tagName) as $serviceId => $tags) { $definition = $container->getDefinition($serviceId); + if (array_any($tags, $closure = fn (array $tag) => (bool) $tag)) { + $tags = array_filter($tags, $closure); + } + foreach ($tags as $tag) { $names = (array) ($tag['serializer'] ?? []); diff --git a/Tests/DependencyInjection/SerializerPassTest.php b/Tests/DependencyInjection/SerializerPassTest.php index dc8d0c75..4945eaa5 100644 --- a/Tests/DependencyInjection/SerializerPassTest.php +++ b/Tests/DependencyInjection/SerializerPassTest.php @@ -381,6 +381,62 @@ public function testMultipleNamedSerializerTagsAreResolvedCorrectly() $this->assertCount(2, $encoderDefinition->getTag('serializer.encoder.api2')); } + /** + * @dataProvider provideEmptyTagsData + */ + public function testEmptyTagsAreIgnoredWhenNonEmptyArePresent( + array $tagAttributesList, + array $expectedDefaultTags, + array $expectedApiTags, + ) { + $container = new ContainerBuilder(); + + $container->setParameter('kernel.debug', false); + $container->setParameter('.serializer.named_serializers', ['api' => []]); + + $container->register('serializer')->setArguments([null, null]); + $container->register('n0')->addTag('serializer.normalizer', ['serializer' => ['default', 'api']]); + $container->register('e0')->addTag('serializer.encoder', ['serializer' => ['default', 'api']]); + + $normalizerDefinition = $container->register('n1')->setTags(['serializer.normalizer' => $tagAttributesList]); + $encoderDefinition = $container->register('e1')->setTags(['serializer.encoder' => $tagAttributesList]); + + $serializerPass = new SerializerPass(); + $serializerPass->process($container); + + $this->assertSame($expectedDefaultTags, $normalizerDefinition->getTag('serializer.normalizer.default')); + $this->assertSame($expectedApiTags, $normalizerDefinition->getTag('serializer.normalizer.api')); + $this->assertSame($expectedDefaultTags, $encoderDefinition->getTag('serializer.encoder.default')); + $this->assertSame($expectedApiTags, $encoderDefinition->getTag('serializer.encoder.api')); + } + + public static function provideEmptyTagsData(): iterable + { + yield 'with default name' => [ + [[], ['serializer' => 'default']], + [[]], + [], + ]; + + yield 'with non-default name' => [ + [[], ['serializer' => 'api']], + [], + [[]], + ]; + + yield 'with wildcard' => [ + [[], ['serializer' => '*']], + [[]], + [[]], + ]; + + yield 'with priority and no name' => [ + [[], ['priority' => 100]], + [['priority' => 100]], + [], + ]; + } + public function testThrowExceptionWhenNoNormalizersForNamedSerializers() { $container = new ContainerBuilder(); diff --git a/Tests/Normalizer/DateTimeNormalizerTest.php b/Tests/Normalizer/DateTimeNormalizerTest.php index 81219652..eed5db06 100644 --- a/Tests/Normalizer/DateTimeNormalizerTest.php +++ b/Tests/Normalizer/DateTimeNormalizerTest.php @@ -54,9 +54,9 @@ public function testNormalizeUsingFormatPassedInConstructor() public function testNormalizeUsingTimeZonePassedInConstructor() { - $normalizer = new DateTimeNormalizer([DateTimeNormalizer::TIMEZONE_KEY => new \DateTimeZone('Japan')]); + $normalizer = new DateTimeNormalizer([DateTimeNormalizer::TIMEZONE_KEY => new \DateTimeZone('Asia/Tokyo')]); - $this->assertSame('2016-12-01T00:00:00+09:00', $normalizer->normalize(new \DateTimeImmutable('2016/12/01', new \DateTimeZone('Japan')))); + $this->assertSame('2016-12-01T00:00:00+09:00', $normalizer->normalize(new \DateTimeImmutable('2016/12/01', new \DateTimeZone('Asia/Tokyo')))); $this->assertSame('2016-12-01T09:00:00+09:00', $normalizer->normalize(new \DateTimeImmutable('2016/12/01', new \DateTimeZone('UTC')))); } @@ -73,9 +73,9 @@ public function testNormalizeUsingTimeZonePassedInContext($expected, $input, $ti public static function normalizeUsingTimeZonePassedInContextProvider() { yield ['2016-12-01T00:00:00+00:00', new \DateTimeImmutable('2016/12/01', new \DateTimeZone('UTC')), null]; - yield ['2016-12-01T00:00:00+09:00', new \DateTimeImmutable('2016/12/01', new \DateTimeZone('Japan')), new \DateTimeZone('Japan')]; - yield ['2016-12-01T09:00:00+09:00', new \DateTimeImmutable('2016/12/01', new \DateTimeZone('UTC')), new \DateTimeZone('Japan')]; - yield ['2016-12-01T09:00:00+09:00', new \DateTime('2016/12/01', new \DateTimeZone('UTC')), new \DateTimeZone('Japan')]; + yield ['2016-12-01T00:00:00+09:00', new \DateTimeImmutable('2016/12/01', new \DateTimeZone('Asia/Tokyo')), new \DateTimeZone('Asia/Tokyo')]; + yield ['2016-12-01T09:00:00+09:00', new \DateTimeImmutable('2016/12/01', new \DateTimeZone('UTC')), new \DateTimeZone('Asia/Tokyo')]; + yield ['2016-12-01T09:00:00+09:00', new \DateTime('2016/12/01', new \DateTimeZone('UTC')), new \DateTimeZone('Asia/Tokyo')]; } /** @@ -139,7 +139,7 @@ public static function normalizeUsingTimeZonePassedInContextAndExpectedFormatWit '2018-12-01T18:03:06.067634', new \DateTimeZone('UTC') ), - new \DateTimeZone('Europe/Kiev'), + new \DateTimeZone('Europe/Kyiv'), ]; yield [ @@ -253,7 +253,7 @@ public function testDenormalize() public function testDenormalizeUsingTimezonePassedInConstructor() { - $timezone = new \DateTimeZone('Japan'); + $timezone = new \DateTimeZone('Asia/Tokyo'); $expected = new \DateTimeImmutable('2016/12/01 17:35:00', $timezone); $normalizer = new DateTimeNormalizer([DateTimeNormalizer::TIMEZONE_KEY => $timezone]); @@ -286,18 +286,18 @@ 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'), + new \DateTimeImmutable('2016/12/01 17:35:00', new \DateTimeZone('Asia/Tokyo')), + new \DateTimeZone('Asia/Tokyo'), ]; yield 'with timezone as string' => [ '2016/12/01 17:35:00', - new \DateTimeImmutable('2016/12/01 17:35:00', new \DateTimeZone('Japan')), - 'Japan', + new \DateTimeImmutable('2016/12/01 17:35:00', new \DateTimeZone('Asia/Tokyo')), + 'Asia/Tokyo', ]; yield 'with format without timezone information' => [ '2016.12.01 17:35:00', - new \DateTimeImmutable('2016/12/01 17:35:00', new \DateTimeZone('Japan')), - new \DateTimeZone('Japan'), + new \DateTimeImmutable('2016/12/01 17:35:00', new \DateTimeZone('Asia/Tokyo')), + new \DateTimeZone('Asia/Tokyo'), 'Y.m.d H:i:s', ]; yield 'ignored with format with timezone information' => [ diff --git a/composer.json b/composer.json index 1c4d384b..52956625 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ "require": { "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "~1.8" + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php84": "^1.30" }, "require-dev": { "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0",