Skip to content

Commit ac25695

Browse files
authored
Merge pull request #4804 from soyuka/2.7
Graphql interface change
2 parents a932d41 + 7c2c3ec commit ac25695

39 files changed

+268
-268
lines changed

src/Api/IdentifiersExtractor.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ public function __construct(ResourceMetadataCollectionFactoryInterface $resource
5656
public function getIdentifiersFromItem($item, Operation $operation = null, array $context = []): array
5757
{
5858
$identifiers = [];
59+
60+
if (!$this->isResourceClass($this->getObjectClass($item))) {
61+
return ['id' => $this->propertyAccessor->getValue($item, 'id')];
62+
}
63+
5964
$resourceClass = $this->getResourceClass($item, true);
6065
$operation = $operation ?? $this->resourceMetadataFactory->create($resourceClass)->getOperation(null, false, true);
6166

@@ -76,6 +81,9 @@ public function getIdentifiersFromItem($item, Operation $operation = null, array
7681
continue;
7782
}
7883

84+
if (!$link->getParameterName()) {
85+
dd($operation);
86+
}
7987
$identifiers[$link->getParameterName()] = $this->getIdentifierValue($item, $link->getFromClass(), $link->getIdentifiers()[0], $link->getParameterName());
8088
}
8189

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/ItemNormalizer.php

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,22 +71,28 @@ public function supportsNormalization($data, $format = null, array $context = []
7171
*/
7272
public function normalize($object, $format = null, array $context = [])
7373
{
74-
if (isset($context['operation_name'])) {
75-
unset($context['operation_name']);
76-
}
74+
$resourceClass = $this->getObjectClass($object);
75+
76+
if ($outputClass = $this->getOutputClass($resourceClass, $context)) {
77+
$context['graphql_identifiers'] = [
78+
self::ITEM_RESOURCE_CLASS_KEY => $context['operation']->getClass(),
79+
self::ITEM_IDENTIFIERS_KEY => $this->identifiersExtractor->getIdentifiersFromItem($object),
80+
];
7781

78-
if (null !== $this->getOutputClass($this->getObjectClass($object), $context)) {
7982
return parent::normalize($object, $format, $context);
8083
}
8184

85+
unset($context['operation_name'], $context['operation']);
8286
$data = parent::normalize($object, $format, $context);
8387
if (!\is_array($data)) {
8488
throw new UnexpectedValueException('Expected data to be an array.');
8589
}
8690

87-
if (!($context['no_resolver_data'] ?? false)) {
88-
$data[self::ITEM_RESOURCE_CLASS_KEY] = $this->getObjectClass($object);
89-
$data[self::ITEM_IDENTIFIERS_KEY] = $this->identifiersExtractor->getIdentifiersFromItem($object);
91+
if (isset($context['graphql_identifiers'])) {
92+
$data = $data + $context['graphql_identifiers'];
93+
} elseif (!($context['no_resolver_data'] ?? false)) {
94+
$data[self::ITEM_RESOURCE_CLASS_KEY] = $resourceClass;
95+
$data[self::ITEM_IDENTIFIERS_KEY] = $this->identifiersExtractor->getIdentifiersFromItem($object, $context['operation'] ?? null);
9096
}
9197

9298
return $data;
@@ -104,7 +110,7 @@ protected function normalizeCollectionOfRelations($propertyMetadata, $attributeV
104110
/**
105111
* {@inheritdoc}
106112
*/
107-
public function supportsDenormalization($data, $type, $format = null, array $context = []): bool
113+
public function supportsDenormalization($data, $type, $format = null, array $context = [])
108114
{
109115
return self::FORMAT === $format && parent::supportsDenormalization($data, $type, $format, $context);
110116
}

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: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,8 @@ 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+
$queryOperation = $this->getQueryOperation($resourceMetadataCollection);
119+
$queryNormalizationContext = $queryOperation ? ($queryOperation->getNormalizationContext() ?? []) : [];
123120

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

src/Hal/Serializer/ItemNormalizer.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,19 @@ public function supportsNormalization($data, $format = null, array $context = []
5656
*/
5757
public function normalize($object, $format = null, array $context = [])
5858
{
59-
if (null !== $this->getOutputClass($this->getObjectClass($object), $context)) {
59+
$resourceClass = $this->getObjectClass($object);
60+
if ($this->getOutputClass($resourceClass, $context)) {
6061
return parent::normalize($object, $format, $context);
6162
}
6263

6364
if (!isset($context['cache_key'])) {
6465
$context['cache_key'] = $this->getCacheKey($format, $context);
6566
}
6667

67-
$resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null);
68+
if ($this->resourceClassResolver->isResourceClass($resourceClass)) {
69+
$resourceClass = $this->resourceClassResolver->getResourceClass($object, $context['resource_class'] ?? null);
70+
}
71+
6872
$context = $this->initContext($resourceClass, $context);
6973
$iri = $this->iriConverter instanceof LegacyIriConverterInterface ? $this->iriConverter->getIriFromItem($object) : $this->iriConverter->getIriFromResource($object);
7074
$context['iri'] = $iri;

0 commit comments

Comments
 (0)