Skip to content

Commit 2a75c00

Browse files
committed
review
1 parent bd4076b commit 2a75c00

File tree

11 files changed

+99
-20
lines changed

11 files changed

+99
-20
lines changed

src/GraphQl/Metadata/Factory/GraphQlNestedOperationResourceMetadataFactory.php

+20-3
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,28 @@ 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+
if (class_exists($resourceClass)) {
55+
$refl = new \ReflectionClass($resourceClass);
56+
$attribute = $refl->getAttributes(ApiResource::class)[0] ?? null;
57+
$attributeInstance = $attribute?->newInstance();
58+
if ($filters = $attributeInstance?->getFilters()) {
59+
$apiResource = $apiResource->withFilters($filters);
60+
}
61+
}
62+
63+
$resourceMetadataCollection[0] = $this->addDefaultGraphQlOperations($apiResource);
64+
4865
return $resourceMetadataCollection;
4966
}
5067
}

src/GraphQl/Type/FieldsBuilder.php

+3-3
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,9 +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');
265-
dump($resourceOperation);
264+
$nestedResourceMetadataCollection = $this->graphQlNestedOperationResourceMetadataFactory->create($resourceClass);
265+
$resourceOperation = $nestedResourceMetadataCollection->getOperation($isCollectionType ? 'collection_query' : 'item_query');
266266
}
267267
}
268268

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,9 @@
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" />
162-
<argument type="service" id="api_platform.doctrine.orm.graphql_metadata.resource.metadata_collection_factory.inner" />
162+
<argument type="service" id="api_platform.doctrine_mongodb.odm.graphql_metadata.resource.metadata_collection_factory.inner" />
163163
</service>
164164
</services>
165165

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

+10-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133
<argument type="service" id="api_platform.pagination" />
134134
<argument type="service" id="api_platform.name_converter" on-invalid="ignore" />
135135
<argument>%api_platform.graphql.nesting_separator%</argument>
136-
<argument type="service" id="api_platform.graphql_metadata.resource.metadata_collection_factory" on-invalid="ignore" />
136+
<argument type="service" id="api_platform.graphql_metadata.resource.metadata_collection_factory" />
137137
</service>
138138

139139
<service id="api_platform.graphql.schema_builder" class="ApiPlatform\GraphQl\Type\SchemaBuilder" public="false">
@@ -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()])]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Tests\GraphQl\Metadata\Factory;
15+
16+
use ApiPlatform\GraphQl\Metadata\Factory\GraphQlNestedOperationResourceMetadataFactory;
17+
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
18+
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
19+
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy;
20+
use PHPUnit\Framework\TestCase;
21+
use Prophecy\PhpUnit\ProphecyTrait;
22+
23+
final class GraphQlNestedOperationResourceMetadataFactoryTest extends TestCase
24+
{
25+
use ProphecyTrait;
26+
27+
public function testCreate(): void
28+
{
29+
$decorated = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class);
30+
$decorated->create('someClass')->shouldBeCalled()->willReturn(new ResourceMetadataCollection('someClass'));
31+
32+
$metadataFactory = new GraphQlNestedOperationResourceMetadataFactory(['status' => 500], $decorated->reveal());
33+
$apiResource = $metadataFactory->create('someClass')[0];
34+
$this->assertCount(5, $apiResource->getGraphQlOperations());
35+
}
36+
37+
public function testCreateWithResource(): void
38+
{
39+
$metadataFactory = new GraphQlNestedOperationResourceMetadataFactory(['status' => 500]);
40+
$apiResource = $metadataFactory->create(RelatedDummy::class)[0];
41+
$this->assertNotEmpty($apiResource->getFilters());
42+
$this->assertEquals('RelatedDummy', $apiResource->getShortName());
43+
}
44+
}

tests/GraphQl/Type/FieldsBuilderTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class FieldsBuilderTest extends TestCase
5858
private ObjectProphecy $propertyNameCollectionFactoryProphecy;
5959
private ObjectProphecy $propertyMetadataFactoryProphecy;
6060
private ObjectProphecy $resourceMetadataCollectionFactoryProphecy;
61-
private ObjectProphecy $dynamicResourceExtractorProphecy;
61+
private ObjectProphecy $graphQlNestedOperationResourceMetadataFactoryProphecy;
6262
private ObjectProphecy $typesContainerProphecy;
6363
private ObjectProphecy $typeBuilderProphecy;
6464
private ObjectProphecy $typeConverterProphecy;

tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,8 @@ public function testGraphQlConfiguration(): void
671671
'api_platform.graphql.normalizer.validation_exception',
672672
'api_platform.graphql.normalizer.http_exception',
673673
'api_platform.graphql.normalizer.runtime_exception',
674+
'api_platform.graphql_metadata.resource.metadata_collection_factory',
675+
'api_platform.graphql_metadata.resource.metadata_collection_factory.filters'
674676
];
675677

676678
$aliases = [

0 commit comments

Comments
 (0)