From 6b3bd7701845b724412a7128b2b156876dc3fe8b Mon Sep 17 00:00:00 2001 From: Roemer Blom Date: Sat, 28 Mar 2026 16:08:03 +0100 Subject: [PATCH 1/4] test(hydra): add test for string serialization groups in DocumentationNormalizer --- .../DocumentationNormalizerTest.php | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/Hydra/Tests/Serializer/DocumentationNormalizerTest.php b/src/Hydra/Tests/Serializer/DocumentationNormalizerTest.php index f9ca871d9e..8c6e9e8e3f 100644 --- a/src/Hydra/Tests/Serializer/DocumentationNormalizerTest.php +++ b/src/Hydra/Tests/Serializer/DocumentationNormalizerTest.php @@ -1170,4 +1170,52 @@ public function testNormalizeNoEntrypointAndHideHydraOperation(): void $this->assertEquals($expected, $documentationNormalizer->normalize($documentation, null, [ContextBuilder::HYDRA_CONTEXT_HAS_PREFIX => false])); } + + public function testNormalizeWithStringGroups(): void + { + $title = 'Test Api'; + $desc = 'test'; + $version = '0.0.0'; + $documentation = new Documentation(new ResourceNameCollection(['dummy' => 'dummy']), $title, $desc, $version); + + $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); + $propertyNameCollectionFactoryProphecy->create('dummy', Argument::type('array'))->shouldBeCalled()->willReturn(new PropertyNameCollection(['name'])); + + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + $propertyMetadataFactoryProphecy->create('dummy', 'name', Argument::type('array'))->shouldBeCalled()->willReturn( + (new ApiProperty())->withNativeType(Type::string())->withDescription('name')->withReadable(true)->withWritable(true)->withReadableLink(true)->withWritableLink(true) + ); + + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); + $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('dummy', [ + (new ApiResource()) + ->withShortName('dummy') + ->withOperations(new Operations([ + 'get' => (new Get())->withShortName('dummy'), + ])) + ->withNormalizationContext(['groups' => 'read']) + ->withDenormalizationContext(['groups' => 'write']), + ])); + + $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); + $resourceClassResolverProphecy->isResourceClass(Argument::type('string'))->willReturn(false); + + $urlGenerator = $this->prophesize(UrlGeneratorInterface::class); + $urlGenerator->generate('api_entrypoint')->willReturn('/'); + $urlGenerator->generate('api_doc', ['_format' => 'jsonld'])->willReturn('/doc'); + $urlGenerator->generate('api_doc', ['_format' => 'jsonld'], 0)->willReturn('/doc'); + + $documentationNormalizer = new DocumentationNormalizer( + $resourceMetadataFactoryProphecy->reveal(), + $propertyNameCollectionFactoryProphecy->reveal(), + $propertyMetadataFactoryProphecy->reveal(), + $resourceClassResolverProphecy->reveal(), + $urlGenerator->reveal() + ); + + $doc = $documentationNormalizer->normalize($documentation); + + $this->assertSame('#dummy', $doc['hydra:supportedClass'][0]['@id']); + $this->assertNotEmpty($doc['hydra:supportedClass'][0]['hydra:supportedProperty']); + } } From f5ade9593d25744c1427d88638dd39ffb8b80697 Mon Sep 17 00:00:00 2001 From: Roemer Blom Date: Sat, 28 Mar 2026 16:09:19 +0100 Subject: [PATCH 2/4] fix(hydra): handle string and null serialization groups in DocumentationNormalizer --- src/Hydra/Serializer/DocumentationNormalizer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Hydra/Serializer/DocumentationNormalizer.php b/src/Hydra/Serializer/DocumentationNormalizer.php index 428c6da7a9..c5007eaa74 100644 --- a/src/Hydra/Serializer/DocumentationNormalizer.php +++ b/src/Hydra/Serializer/DocumentationNormalizer.php @@ -173,8 +173,8 @@ private function getClass(string $resourceClass, ApiResource $resourceMetadata, */ private function getPropertyMetadataFactoryContext(ApiResource $resourceMetadata): array { - $normalizationGroups = $resourceMetadata->getNormalizationContext()[AbstractNormalizer::GROUPS] ?? null; - $denormalizationGroups = $resourceMetadata->getDenormalizationContext()[AbstractNormalizer::GROUPS] ?? null; + $normalizationGroups = (array)(($resourceMetadata->getNormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null); + $denormalizationGroups = (array)(($resourceMetadata->getDenormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null); $propertyContext = [ 'normalization_groups' => $normalizationGroups, 'denormalization_groups' => $denormalizationGroups, From ea08743a693ab51c143b72d5e23a9308aaeb554f Mon Sep 17 00:00:00 2001 From: Roemer Blom Date: Sat, 28 Mar 2026 16:15:42 +0100 Subject: [PATCH 3/4] style: fix cs-fixer spacing on array cast --- src/Hydra/Serializer/DocumentationNormalizer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Hydra/Serializer/DocumentationNormalizer.php b/src/Hydra/Serializer/DocumentationNormalizer.php index c5007eaa74..d405f6c4ce 100644 --- a/src/Hydra/Serializer/DocumentationNormalizer.php +++ b/src/Hydra/Serializer/DocumentationNormalizer.php @@ -173,8 +173,8 @@ private function getClass(string $resourceClass, ApiResource $resourceMetadata, */ private function getPropertyMetadataFactoryContext(ApiResource $resourceMetadata): array { - $normalizationGroups = (array)(($resourceMetadata->getNormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null); - $denormalizationGroups = (array)(($resourceMetadata->getDenormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null); + $normalizationGroups = (array) (($resourceMetadata->getNormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null); + $denormalizationGroups = (array) (($resourceMetadata->getDenormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null); $propertyContext = [ 'normalization_groups' => $normalizationGroups, 'denormalization_groups' => $denormalizationGroups, From bf0abd3ecc53193dfd4e1a6a5cc9ad9f6954ecf8 Mon Sep 17 00:00:00 2001 From: Roemer Blom Date: Sat, 28 Mar 2026 16:47:16 +0100 Subject: [PATCH 4/4] fix(hydra): use is_string check instead of array cast for serialization groups --- src/Hydra/Serializer/DocumentationNormalizer.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Hydra/Serializer/DocumentationNormalizer.php b/src/Hydra/Serializer/DocumentationNormalizer.php index d405f6c4ce..b1c06ec05c 100644 --- a/src/Hydra/Serializer/DocumentationNormalizer.php +++ b/src/Hydra/Serializer/DocumentationNormalizer.php @@ -173,8 +173,16 @@ private function getClass(string $resourceClass, ApiResource $resourceMetadata, */ private function getPropertyMetadataFactoryContext(ApiResource $resourceMetadata): array { - $normalizationGroups = (array) (($resourceMetadata->getNormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null); - $denormalizationGroups = (array) (($resourceMetadata->getDenormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null); + $normalizationGroups = ($resourceMetadata->getNormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null; + $denormalizationGroups = ($resourceMetadata->getDenormalizationContext() ?? [])[AbstractNormalizer::GROUPS] ?? null; + + if (\is_string($normalizationGroups)) { + $normalizationGroups = [$normalizationGroups]; + } + if (\is_string($denormalizationGroups)) { + $denormalizationGroups = [$denormalizationGroups]; + } + $propertyContext = [ 'normalization_groups' => $normalizationGroups, 'denormalization_groups' => $denormalizationGroups,