From 8f367a30f7fef5f41871932ab300484e8efff5e0 Mon Sep 17 00:00:00 2001 From: David ALLIX Date: Thu, 8 Sep 2022 16:33:21 +0200 Subject: [PATCH 1/5] fix(graphql): link relations requires the property --- src/Doctrine/Common/State/LinksHandlerTrait.php | 13 +++++++------ src/GraphQl/Resolver/Stage/ReadStage.php | 1 + .../LinkResourceMetadataCollectionFactory.php | 10 +++++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Doctrine/Common/State/LinksHandlerTrait.php b/src/Doctrine/Common/State/LinksHandlerTrait.php index 2033ac76241..025d97ea418 100644 --- a/src/Doctrine/Common/State/LinksHandlerTrait.php +++ b/src/Doctrine/Common/State/LinksHandlerTrait.php @@ -35,10 +35,11 @@ private function getLinks(string $resourceClass, Operation $operation, array $co } $newLinks = []; + $linkProperty = $context['linkProperty']; foreach ($links as $link) { - if ($linkClass === $link->getFromClass()) { - $newLinks[] = $link; + if (($linkClass === $link->getFromClass()) && ($linkProperty === $link->getFromProperty())) { + $newLinks[$linkClass][$linkProperty] = $link; } } @@ -62,16 +63,16 @@ private function getLinks(string $resourceClass, Operation $operation, array $co } foreach ($this->getOperationLinks($linkedOperation ?? null) as $link) { - if ($resourceClass === $link->getToClass()) { - $newLinks[] = $link; + if (($resourceClass === $link->getToClass()) && ($linkProperty === $link->getFromProperty())) { + $newLinks[$linkClass][$linkProperty] = $link; } } - if (!$newLinks) { + if ([] === $newLinks) { throw new RuntimeException(sprintf('The class "%s" cannot be retrieved from "%s".', $resourceClass, $linkClass)); } - return $newLinks; + return array_values(...array_values($newLinks)); } private function getIdentifierValue(array &$identifiers, string $name = null) diff --git a/src/GraphQl/Resolver/Stage/ReadStage.php b/src/GraphQl/Resolver/Stage/ReadStage.php index 139c211454e..a13b21b2da7 100644 --- a/src/GraphQl/Resolver/Stage/ReadStage.php +++ b/src/GraphQl/Resolver/Stage/ReadStage.php @@ -92,6 +92,7 @@ public function __invoke(?string $resourceClass, ?string $rootClass, Operation $ if (isset($source[$info->fieldName], $source[ItemNormalizer::ITEM_IDENTIFIERS_KEY], $source[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY])) { $uriVariables = $source[ItemNormalizer::ITEM_IDENTIFIERS_KEY]; $normalizationContext['linkClass'] = $source[ItemNormalizer::ITEM_RESOURCE_CLASS_KEY]; + $normalizationContext['linkProperty'] = $info->fieldName; } return $this->provider->provide($operation, $uriVariables, $normalizationContext); diff --git a/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php index befcd6d5bd4..40289f55395 100644 --- a/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php @@ -71,18 +71,18 @@ private function mergeLinks(array $links, array $toMergeLinks): array { $classLinks = []; foreach ($links as $link) { - $classLinks[$link->getToClass()] = $link; + $classLinks[$link->getToClass()][$link->getFromProperty()] = $link; } foreach ($toMergeLinks as $link) { - if (isset($classLinks[$link->getToClass()])) { - $classLinks[$link->getToClass()] = $classLinks[$link->getToClass()]->withLink($link); + if (null !== $prevLink = $classLinks[$link->getToClass()][$link->getFromProperty()] ?? null) { + $classLinks[$link->getToClass()][$link->getFromProperty()] = $prevLink->withLink($link); continue; } - $classLinks[$link->getToClass()] = $link; + $classLinks[$link->getToClass()][$link->getFromProperty()] = $link; } - return array_values($classLinks); + return array_values(array_merge(...array_values($classLinks))); } } From 6ffb5dfdaff1f9e9bce0c7640bbd46ef5c34cc77 Mon Sep 17 00:00:00 2001 From: David ALLIX Date: Thu, 8 Sep 2022 19:15:03 +0200 Subject: [PATCH 2/5] fix(graphql): operation with disabled pagination --- src/Doctrine/Common/State/LinksHandlerTrait.php | 12 +++++++----- .../LinkResourceMetadataCollectionFactory.php | 6 +++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Doctrine/Common/State/LinksHandlerTrait.php b/src/Doctrine/Common/State/LinksHandlerTrait.php index 025d97ea418..aced9536f14 100644 --- a/src/Doctrine/Common/State/LinksHandlerTrait.php +++ b/src/Doctrine/Common/State/LinksHandlerTrait.php @@ -34,12 +34,13 @@ private function getLinks(string $resourceClass, Operation $operation, array $co return $links; } - $newLinks = []; + $newLink = null; $linkProperty = $context['linkProperty']; foreach ($links as $link) { if (($linkClass === $link->getFromClass()) && ($linkProperty === $link->getFromProperty())) { - $newLinks[$linkClass][$linkProperty] = $link; + $newLink = $link; + break; } } @@ -64,15 +65,16 @@ private function getLinks(string $resourceClass, Operation $operation, array $co foreach ($this->getOperationLinks($linkedOperation ?? null) as $link) { if (($resourceClass === $link->getToClass()) && ($linkProperty === $link->getFromProperty())) { - $newLinks[$linkClass][$linkProperty] = $link; + $newLink = $link; + break; } } - if ([] === $newLinks) { + if (null === $newLink) { throw new RuntimeException(sprintf('The class "%s" cannot be retrieved from "%s".', $resourceClass, $linkClass)); } - return array_values(...array_values($newLinks)); + return [$newLink]; } private function getIdentifierValue(array &$identifiers, string $name = null) diff --git a/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php index 40289f55395..aee0e203578 100644 --- a/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php @@ -83,6 +83,10 @@ private function mergeLinks(array $links, array $toMergeLinks): array $classLinks[$link->getToClass()][$link->getFromProperty()] = $link; } - return array_values(array_merge(...array_values($classLinks))); + // return array_values(array_merge(...array_values($classLinks))); (branch 3.0) + + return array_reduce($classLinks, function(array $carry, array $item) { + return array_merge($carry, array_values($item)); + }, []); } } From 233275cdf4563b8f9e2a0ee6ec21b270ad330697 Mon Sep 17 00:00:00 2001 From: David ALLIX Date: Thu, 8 Sep 2022 19:15:13 +0200 Subject: [PATCH 3/5] test(graphql): fixes --- tests/GraphQl/Resolver/Stage/ReadStageTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/GraphQl/Resolver/Stage/ReadStageTest.php b/tests/GraphQl/Resolver/Stage/ReadStageTest.php index b90f3ee131d..d0d3fa89741 100644 --- a/tests/GraphQl/Resolver/Stage/ReadStageTest.php +++ b/tests/GraphQl/Resolver/Stage/ReadStageTest.php @@ -210,7 +210,7 @@ public function testApplyCollection(array $args, ?string $rootClass, ?array $sou $this->serializerContextBuilderProphecy->create($resourceClass, $operation, $context, true)->shouldBeCalled()->willReturn($normalizationContext); $this->providerProphecy->provide($operation, [], $normalizationContext + ['filters' => $expectedFilters])->willReturn([]); - $this->providerProphecy->provide($operation, ['id' => 3], $normalizationContext + ['filters' => $expectedFilters, 'linkClass' => 'myResource'])->willReturn(['subresource']); + $this->providerProphecy->provide($operation, ['id' => 3], $normalizationContext + ['filters' => $expectedFilters, 'linkClass' => 'myResource', 'linkProperty' => 'subresource'])->willReturn(['subresource']); $result = ($this->readStage)($resourceClass, $rootClass, $operation, $context); From f759784279f2c9ef1e9dd1175de5e73909930681 Mon Sep 17 00:00:00 2001 From: David ALLIX Date: Thu, 8 Sep 2022 19:21:05 +0200 Subject: [PATCH 4/5] fix(graphql): operation with disabled pagination --- .../Resource/Factory/LinkResourceMetadataCollectionFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php index aee0e203578..2b2fc536e85 100644 --- a/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactory.php @@ -85,7 +85,7 @@ private function mergeLinks(array $links, array $toMergeLinks): array // return array_values(array_merge(...array_values($classLinks))); (branch 3.0) - return array_reduce($classLinks, function(array $carry, array $item) { + return array_reduce($classLinks, function (array $carry, array $item) { return array_merge($carry, array_values($item)); }, []); } From 683bed49055cb4dc0f7fe14ee1dce4e87f4252fc Mon Sep 17 00:00:00 2001 From: David ALLIX Date: Thu, 8 Sep 2022 19:47:34 +0200 Subject: [PATCH 5/5] test(graphql): fixes --- .../Factory/LinkResourceMetadataCollectionFactoryTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php index 0b28987a8e3..b6ac53677af 100644 --- a/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/LinkResourceMetadataCollectionFactoryTest.php @@ -84,6 +84,7 @@ class: AttributeResource::class, class: AttributeResource::class, graphQlOperations: [ 'item_query' => (new Query(shortName: 'AttributeResource', class: AttributeResource::class))->withLinks([ + (new Link())->withFromProperty('foo')->withFromClass(AttributeResource::class)->withToClass(Dummy::class)->withIdentifiers(['id']), (new Link())->withFromProperty('foo2')->withFromClass(AttributeResource::class)->withToClass(Dummy::class)->withIdentifiers(['id']), (new Link())->withFromProperty('bar')->withFromClass(AttributeResource::class)->withToClass(RelatedDummy::class)->withIdentifiers(['id']), ]),