Skip to content

Commit da30537

Browse files
committed
fix(graphql): use operation on serializer context builder
1 parent a932d41 commit da30537

23 files changed

+104
-156
lines changed

src/GraphQl/Resolver/Stage/DeserializeStage.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function __invoke($objectToPopulate, string $resourceClass, Operation $op
4444
return $objectToPopulate;
4545
}
4646

47-
$denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation->getName(), $context, false);
47+
$denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation, $context, false);
4848
if (null !== $objectToPopulate) {
4949
$denormalizationContext[AbstractNormalizer::OBJECT_TO_POPULATE] = $objectToPopulate;
5050
}

src/GraphQl/Resolver/Stage/ReadStage.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public function __invoke(?string $resourceClass, ?string $rootClass, Operation $
5959
}
6060

6161
$args = $context['args'];
62-
$normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation->getName(), $context, true);
62+
$normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation, $context, true);
6363

6464
if (!$context['is_collection']) {
6565
$identifier = $this->getIdentifierFromContext($context);

src/GraphQl/Resolver/Stage/SerializeStage.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public function __invoke($itemOrCollection, string $resourceClass, Operation $op
7676
return null;
7777
}
7878

79-
$normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operationName, $context, true);
79+
$normalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation, $context, true);
8080

8181
$data = null;
8282
if (!$isCollection) {

src/GraphQl/Resolver/Stage/WriteStage.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public function __invoke($data, string $resourceClass, Operation $operation, arr
4242
return $data;
4343
}
4444

45-
$denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation->getName(), $context, false);
45+
$denormalizationContext = $this->serializerContextBuilder->create($resourceClass, $operation, $context, false);
4646

4747
return $this->processor->process($data, $operation, [], ['operation' => $operation] + $denormalizationContext);
4848
}

src/GraphQl/Serializer/SerializerContextBuilder.php

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313

1414
namespace ApiPlatform\GraphQl\Serializer;
1515

16-
use ApiPlatform\Exception\OperationNotFoundException;
1716
use ApiPlatform\Metadata\GraphQl\Operation;
18-
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
1917
use GraphQL\Type\Definition\ResolveInfo;
2018
use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface;
2119
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
@@ -27,45 +25,32 @@
2725
*/
2826
final class SerializerContextBuilder implements SerializerContextBuilderInterface
2927
{
30-
private $resourceMetadataCollectionFactory;
3128
private $nameConverter;
3229

33-
public function __construct(ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, ?NameConverterInterface $nameConverter)
30+
public function __construct(?NameConverterInterface $nameConverter)
3431
{
35-
$this->resourceMetadataCollectionFactory = $resourceMetadataCollectionFactory;
3632
$this->nameConverter = $nameConverter;
3733
}
3834

39-
public function create(?string $resourceClass, string $operationName, array $resolverContext, bool $normalization): array
35+
public function create(?string $resourceClass, Operation $operation, array $resolverContext, bool $normalization): array
4036
{
41-
$context = ['resource_class' => $resourceClass, 'operation_name' => $operationName, 'graphql_operation_name' => $operationName];
42-
$operation = null;
43-
44-
if ($resourceClass) {
45-
$resourceMetadata = $this->resourceMetadataCollectionFactory->create($resourceClass);
46-
try {
47-
$operation = $resourceMetadata->getOperation($operationName);
48-
} catch (OperationNotFoundException $e) {
49-
// It's possible that the serialization context may not be tight to an existing operation
50-
try {
51-
$context['operation_name'] = $resourceMetadata->getOperation()->getName();
52-
} catch (OperationNotFoundException $e) {
53-
}
54-
}
55-
}
37+
$context = ['resource_class' => $resourceClass, 'operation_name' => $operation->getName(), 'graphql_operation_name' => $operation->getName()];
5638

5739
if (isset($resolverContext['fields'])) {
5840
$context['no_resolver_data'] = true;
5941
}
6042

61-
if ($operation) {
43+
$context['operation'] = $operation;
44+
if ($operation->getInput()) {
6245
$context['input'] = $operation->getInput();
46+
}
47+
if ($operation->getOutput()) {
6348
$context['output'] = $operation->getOutput();
64-
$context = $normalization ? array_merge($operation->getNormalizationContext() ?? [], $context) : array_merge($operation->getDenormalizationContext() ?? [], $context);
6549
}
50+
$context = $normalization ? array_merge($operation->getNormalizationContext() ?? [], $context) : array_merge($operation->getDenormalizationContext() ?? [], $context);
6651

6752
if ($normalization) {
68-
$context['attributes'] = $this->fieldsToAttributes($resourceClass, $operation instanceof Operation ? $operation : null, $resolverContext, $context);
53+
$context['attributes'] = $this->fieldsToAttributes($resourceClass, $operation, $resolverContext, $context);
6954
}
7055

7156
return $context;
@@ -74,7 +59,7 @@ public function create(?string $resourceClass, string $operationName, array $res
7459
/**
7560
* Retrieves fields, recursively replaces the "_id" key (the raw id) by "id" (the name of the property expected by the Serializer) and flattens edge and node structures (pagination).
7661
*/
77-
private function fieldsToAttributes(?string $resourceClass, ?Operation $operation, array $resolverContext, array $context): array
62+
private function fieldsToAttributes(?string $resourceClass, Operation $operation, array $resolverContext, array $context): array
7863
{
7964
if (isset($resolverContext['fields'])) {
8065
$fields = $resolverContext['fields'];
@@ -87,10 +72,6 @@ private function fieldsToAttributes(?string $resourceClass, ?Operation $operatio
8772
$attributes = $this->replaceIdKeys($fields['edges']['node'] ?? $fields['collection'] ?? $fields, $resourceClass, $context);
8873

8974
if ($resolverContext['is_mutation'] || $resolverContext['is_subscription']) {
90-
if (!$operation) {
91-
throw new \LogicException('An operation should always exist for a mutation or a subscription.');
92-
}
93-
9475
$wrapFieldName = lcfirst($operation->getShortName());
9576

9677
return $attributes[$wrapFieldName] ?? [];

src/GraphQl/Serializer/SerializerContextBuilderInterface.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313

1414
namespace ApiPlatform\GraphQl\Serializer;
1515

16+
use ApiPlatform\Metadata\GraphQl\Operation;
17+
1618
/**
1719
* Builds the context used by the Symfony Serializer.
1820
*
1921
* @author Alan Poulain <[email protected]>
2022
*/
2123
interface SerializerContextBuilderInterface
2224
{
23-
public function create(string $resourceClass, string $operationName, array $resolverContext, bool $normalization): array;
25+
public function create(string $resourceClass, Operation $operation, array $resolverContext, bool $normalization): array;
2426
}

src/GraphQl/Type/TypeBuilder.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,7 @@ public function getResourceObjectType(?string $resourceClass, ResourceMetadataCo
115115
'resolveField' => $this->defaultFieldResolver,
116116
'fields' => function () use ($resourceClass, $operation, $operationName, $resourceMetadataCollection, $input, $wrapData, $depth, $ioMetadata) {
117117
if ($wrapData) {
118-
try {
119-
$queryNormalizationContext = $operation instanceof Query ? ($resourceMetadataCollection->getOperation($operationName)->getNormalizationContext() ?? []) : [];
120-
} catch (OperationNotFoundException $e) {
121-
$queryNormalizationContext = [];
122-
}
118+
$queryNormalizationContext = $this->getQueryOperation($resourceMetadataCollection)?->getNormalizationContext() ?? [];
123119

124120
try {
125121
$mutationNormalizationContext = $operation instanceof Mutation || $operation instanceof Subscription ? ($resourceMetadataCollection->getOperation($operationName)->getNormalizationContext() ?? []) : [];
@@ -310,4 +306,18 @@ private function getPageBasedPaginationFields(GraphQLType $resourceType): array
310306
'paginationInfo' => GraphQLType::nonNull($paginationInfoObjectType),
311307
];
312308
}
309+
310+
private function getQueryOperation(ResourceMetadataCollection $resourceMetadataCollection): ?Operation
311+
{
312+
foreach ($resourceMetadataCollection as $resourceMetadata) {
313+
foreach ($resourceMetadata->getGraphQlOperations() as $operation) {
314+
// Filter the custom queries.
315+
if ($operation instanceof Query && !$operation->getResolver()) {
316+
return $operation;
317+
}
318+
}
319+
}
320+
321+
return null;
322+
}
313323
}

src/Symfony/Bundle/Resources/config/v3/graphql.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
</service>
5757

5858
<service id="api_platform.graphql.serializer.context_builder" class="ApiPlatform\GraphQl\Serializer\SerializerContextBuilder" public="false">
59-
<argument type="service" id="api_platform.metadata.resource.metadata_collection_factory" />
6059
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
6160
</service>
6261
<service id="ApiPlatform\GraphQl\Serializer\SerializerContextBuilderInterface" alias="api_platform.graphql.serializer.context_builder" />

tests/GraphQl/Resolver/Factory/CollectionResolverFactoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313

1414
namespace ApiPlatform\Tests\GraphQl\Resolver\Factory;
1515

16-
use ApiPlatform\Core\Tests\ProphecyTrait;
1716
use ApiPlatform\GraphQl\Resolver\Factory\CollectionResolverFactory;
1817
use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface;
1918
use ApiPlatform\GraphQl\Resolver\Stage\SecurityPostDenormalizeStageInterface;
2019
use ApiPlatform\GraphQl\Resolver\Stage\SecurityStageInterface;
2120
use ApiPlatform\GraphQl\Resolver\Stage\SerializeStageInterface;
2221
use ApiPlatform\Metadata\GraphQl\QueryCollection;
22+
use ApiPlatform\Tests\ProphecyTrait;
2323
use GraphQL\Type\Definition\ResolveInfo;
2424
use PHPUnit\Framework\TestCase;
2525
use Psr\Container\ContainerInterface;

tests/GraphQl/Resolver/Factory/ItemMutationResolverFactoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
namespace ApiPlatform\Tests\GraphQl\Resolver\Factory;
1515

16-
use ApiPlatform\Core\Tests\ProphecyTrait;
1716
use ApiPlatform\GraphQl\Resolver\Factory\ItemMutationResolverFactory;
1817
use ApiPlatform\GraphQl\Resolver\Stage\DeserializeStageInterface;
1918
use ApiPlatform\GraphQl\Resolver\Stage\ReadStageInterface;
@@ -25,6 +24,7 @@
2524
use ApiPlatform\GraphQl\Resolver\Stage\WriteStageInterface;
2625
use ApiPlatform\Metadata\GraphQl\Mutation;
2726
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy;
27+
use ApiPlatform\Tests\ProphecyTrait;
2828
use GraphQL\Type\Definition\ResolveInfo;
2929
use PHPUnit\Framework\TestCase;
3030
use Prophecy\Argument;

0 commit comments

Comments
 (0)