Skip to content

Commit 6c630f1

Browse files
committed
fixes
1 parent 986cf04 commit 6c630f1

File tree

9 files changed

+66
-27
lines changed

9 files changed

+66
-27
lines changed

src/GraphQl/Metadata/Factory/GraphQlNestedOperationResourceMetadataFactory.php

+18-3
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,26 @@ public function create(string $resourceClass): ResourceMetadataCollection
4040
$resourceMetadataCollection = $this->decorated->create($resourceClass);
4141
}
4242

43-
if (0 === \count($resourceMetadataCollection)) {
44-
$shortName = (false !== $pos = strrpos($resourceClass, '\\')) ? substr($resourceClass, $pos + 1) : $resourceClass;
45-
$resourceMetadataCollection[0] = $this->addDefaultGraphQlOperations(new ApiResource(class: $resourceClass, shortName: $shortName));
43+
if (0 < \count($resourceMetadataCollection)) {
44+
return $resourceMetadataCollection;
4645
}
4746

47+
$shortName = (false !== $pos = strrpos($resourceClass, '\\')) ? substr($resourceClass, $pos + 1) : $resourceClass;
48+
49+
$apiResource = new ApiResource(
50+
class: $resourceClass,
51+
shortName: $shortName
52+
);
53+
54+
$refl = new \ReflectionClass($resourceClass);
55+
$attribute = $refl->getAttributes(ApiResource::class)[0] ?? null;
56+
$attributeInstance = $attribute?->newInstance();
57+
if ($filters = $attributeInstance?->getFilters()) {
58+
$apiResource = $apiResource->withFilters($filters);
59+
}
60+
61+
$resourceMetadataCollection[0] = $this->addDefaultGraphQlOperations($apiResource);
62+
4863
return $resourceMetadataCollection;
4964
}
5065
}

src/GraphQl/Type/FieldsBuilder.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use ApiPlatform\GraphQl\Type\Definition\TypeInterface;
2020
use ApiPlatform\Metadata\GraphQl\Mutation;
2121
use ApiPlatform\Metadata\GraphQl\Operation;
22+
use ApiPlatform\Metadata\GraphQl\Query;
2223
use ApiPlatform\Metadata\GraphQl\Subscription;
2324
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
2425
use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
@@ -260,8 +261,8 @@ private function getResourceFieldConfiguration(?string $property, ?string $field
260261
$resourceOperation = $resourceMetadataCollection->getOperation($isCollectionType ? 'collection_query' : 'item_query');
261262
} catch (OperationNotFoundException) {
262263
// If there is no query operation for a nested resource we force one to exist
263-
$resourceMetadataCollection = $this->graphQlNestedOperationResourceMetadataFactory->create($resourceClass);
264-
$resourceOperation = $resourceMetadataCollection->getOperation($isCollectionType ? 'collection_query' : 'item_query');
264+
$nestedResourceMetadataCollection = $this->graphQlNestedOperationResourceMetadataFactory->create($resourceClass);
265+
$resourceOperation = $nestedResourceMetadataCollection->getOperation($isCollectionType ? 'collection_query' : 'item_query');
265266
}
266267
}
267268

src/GraphQl/Type/TypeConverter.php

+18-11
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,20 @@ private function getResourceType(Type $type, bool $input, Operation $rootOperati
130130
return null;
131131
}
132132

133-
$propertyMetadata = null;
134-
if ($property) {
135-
$context = [
136-
'normalization_groups' => $rootOperation->getNormalizationContext()['groups'] ?? null,
137-
'denormalization_groups' => $rootOperation->getDenormalizationContext()['groups'] ?? null,
138-
];
139-
$propertyMetadata = $this->propertyMetadataFactory->create($rootResource, $property, $context);
140-
}
133+
// TODO: improve this
134+
if ($input) {
135+
$propertyMetadata = null;
136+
if ($property) {
137+
$context = [
138+
'normalization_groups' => $rootOperation->getNormalizationContext()['groups'] ?? null,
139+
'denormalization_groups' => $rootOperation->getDenormalizationContext()['groups'] ?? null,
140+
];
141+
$propertyMetadata = $this->propertyMetadataFactory->create($rootResource, $property, $context);
142+
}
141143

142-
if ($input && $depth > 0 && (!$propertyMetadata || !$propertyMetadata->isWritableLink())) {
143-
return GraphQLType::string();
144+
if ($depth > 0 && (!$propertyMetadata || !$propertyMetadata->isWritableLink())) {
145+
return GraphQLType::string();
146+
}
144147
}
145148

146149
$operationName = $rootOperation->getName();
@@ -162,9 +165,13 @@ private function getResourceType(Type $type, bool $input, Operation $rootOperati
162165
/** @var Operation $operation */
163166
$operation = ($isCollection ? new QueryCollection() : new Query())
164167
->withResource($resourceMetadataCollection[0])
165-
->withName($operationName);
168+
->withName($operationName); // TODO: use GraphQlNestedOperationResourceMetadataFactory
166169
}
167170

171+
// if ($rootOperation->getExtraProperties()['_graphql_nested_operation'] ?? false) {
172+
// $operation = $operation->withExtraProperties(['_graphql_nested_operation' => true], $operation->getExtraProperties());
173+
// }
174+
168175
return $this->typeBuilder->getResourceObjectType($resourceClass, $resourceMetadataCollection, $operation, $input, false, $depth);
169176
}
170177

src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php

+7-3
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,21 @@ public function create(string $resourceClass): ResourceMetadataCollection
5050
$filters = array_keys($this->readFilterAttributes($reflectionClass));
5151

5252
foreach ($resourceMetadataCollection as $i => $resource) {
53-
foreach ($operations = $resource->getOperations() as $operationName => $operation) {
53+
foreach ($operations = $resource->getOperations() ?? [] as $operationName => $operation) {
5454
$operations->add($operationName, $operation->withFilters(array_unique(array_merge($resource->getFilters() ?? [], $operation->getFilters() ?? [], $filters))));
5555
}
5656

57-
$resourceMetadataCollection[$i] = $resource->withOperations($operations);
57+
if ($operations) {
58+
$resourceMetadataCollection[$i] = $resource->withOperations($operations);
59+
}
5860

5961
foreach ($graphQlOperations = $resource->getGraphQlOperations() ?? [] as $operationName => $operation) {
6062
$graphQlOperations[$operationName] = $operation->withFilters(array_unique(array_merge($resource->getFilters() ?? [], $operation->getFilters() ?? [], $filters)));
6163
}
6264

63-
$resourceMetadataCollection[$i] = $resource->withGraphQlOperations($graphQlOperations);
65+
if ($graphQlOperations) {
66+
$resourceMetadataCollection[$i] = $resource->withGraphQlOperations($graphQlOperations);
67+
}
6468
}
6569

6670
return $resourceMetadataCollection;

src/Symfony/Bundle/Resources/config/doctrine_mongodb_odm.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@
157157
<argument type="service" id="api_platform.doctrine_mongodb.odm.metadata.property.identifier_metadata_factory.inner"/>
158158
</service>
159159

160-
<service id="api_platform.doctrine_mongodb.odm.graphql_metadata.resource.metadata_collection_factory" class="ApiPlatform\Doctrine\Odm\Metadata\Resource\DoctrineMongoDbOdmResourceCollectionMetadataFactory" decorates="api_platform.graphql_metadata.resource.metadata_collection_factory" decoration-priority="40">
160+
<service id="api_platform.doctrine_mongodb.odm.graphql_metadata.resource.metadata_collection_factory" class="ApiPlatform\Doctrine\Odm\Metadata\Resource\DoctrineMongoDbOdmResourceCollectionMetadataFactory" decorates="api_platform.graphql_metadata.resource.metadata_collection_factory" decoration-priority="40" decoration-on-invalid="ignore">
161161
<argument type="service" id="doctrine_mongodb" />
162162
<argument type="service" id="api_platform.doctrine.orm.graphql_metadata.resource.metadata_collection_factory.inner" />
163163
</service>

src/Symfony/Bundle/Resources/config/doctrine_orm.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@
167167
<argument type="service" id="api_platform.doctrine.orm.metadata.resource.metadata_collection_factory.inner" />
168168
</service>
169169

170-
<service id="api_platform.doctrine.orm.graphql_metadata.resource.metadata_collection_factory" class="ApiPlatform\Doctrine\Orm\Metadata\Resource\DoctrineOrmResourceCollectionMetadataFactory" decorates="api_platform.graphql_metadata.resource.metadata_collection_factory" decoration-priority="40">
170+
<service id="api_platform.doctrine.orm.graphql_metadata.resource.metadata_collection_factory" class="ApiPlatform\Doctrine\Orm\Metadata\Resource\DoctrineOrmResourceCollectionMetadataFactory" decorates="api_platform.graphql_metadata.resource.metadata_collection_factory" decoration-priority="40" decoration-on-invalid="ignore">
171171
<argument type="service" id="doctrine" />
172172
<argument type="service" id="api_platform.doctrine.orm.graphql_metadata.resource.metadata_collection_factory.inner" />
173173
</service>

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

+9
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,15 @@
274274
<service id="api_platform.graphql.normalizer.runtime_exception" class="ApiPlatform\GraphQl\Serializer\Exception\RuntimeExceptionNormalizer">
275275
<tag name="serializer.normalizer" priority="-780" />
276276
</service>
277+
278+
<!-- GraphQl specific metadata factory used in the FieldsBuilder and decorated by doctrine metadata factories -->
279+
<service id="api_platform.graphql_metadata.resource.metadata_collection_factory" class="ApiPlatform\GraphQl\Metadata\Factory\GraphQlNestedOperationResourceMetadataFactory">
280+
<argument>%api_platform.defaults%</argument>
281+
</service>
282+
283+
<service id="api_platform.graphql_metadata.resource.metadata_collection_factory.filters" class="ApiPlatform\Metadata\Resource\Factory\FiltersResourceMetadataCollectionFactory" decorates="api_platform.graphql_metadata.resource.metadata_collection_factory" decoration-priority="200" public="false">
284+
<argument type="service" id="api_platform.graphql_metadata.resource.metadata_collection_factory.filters.inner" />
285+
</service>
277286
</services>
278287

279288
</container>

src/Symfony/Bundle/Resources/config/metadata/resource.xml

-5
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,5 @@
7070
<service id="api_platform.cache.metadata.resource_collection" parent="cache.system" public="false">
7171
<tag name="cache.pool" />
7272
</service>
73-
74-
<!-- GraphQl specific metadata factory used in the FieldsBuilder and decorated by doctrine metadata factories -->
75-
<service id="api_platform.graphql_metadata.resource.metadata_collection_factory" class="ApiPlatform\GraphQl\Metadata\Factory\GraphQlNestedOperationResourceMetadataFactory">
76-
<argument>%api_platform.defaults%</argument>
77-
</service>
7873
</services>
7974
</container>

tests/Fixtures/TestBundle/Entity/RelatedDummy.php

+9-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,15 @@
3535
*
3636
* @author Kévin Dunglas <[email protected]>
3737
*/
38-
#[ApiResource(graphQlOperations: [new Query(name: 'item_query'), new Mutation(name: 'update', normalizationContext: ['groups' => ['chicago', 'fakemanytomany']], denormalizationContext: ['groups' => ['friends']])], types: ['https://schema.org/Product'], normalizationContext: ['groups' => ['friends']], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'])]
38+
#[ApiResource(
39+
graphQlOperations: [
40+
new Query(name: 'item_query'),
41+
new Mutation(name: 'update', normalizationContext: ['groups' => ['chicago', 'fakemanytomany']], denormalizationContext: ['groups' => ['friends']]),
42+
],
43+
types: ['https://schema.org/Product'],
44+
normalizationContext: ['groups' => ['friends']],
45+
filters: ['related_dummy.friends', 'related_dummy.complex_sub_query']
46+
)]
3947
#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies{._format}', uriVariables: ['id' => new Link(fromClass: Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies')], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new GetCollection()])]
4048
#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}{._format}', uriVariables: ['id' => new Link(fromClass: Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])]
4149
#[ApiResource(uriTemplate: '/related_dummies/{id}/id{._format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, types: ['https://schema.org/Product'], filters: ['related_dummy.friends', 'related_dummy.complex_sub_query'], normalizationContext: ['groups' => ['friends']], operations: [new Get()])]

0 commit comments

Comments
 (0)