From dc6881069cb9c21e938f609691c2de84b80d4caf Mon Sep 17 00:00:00 2001 From: Antoine Bluchet Date: Thu, 3 Nov 2022 17:07:54 +0100 Subject: [PATCH] Revert "fix(graphql): use right nested operation (#5102)" This reverts commit 44337ddb3908d7b05ed75b75325b7941581f575b. --- features/graphql/collection.feature | 46 ------ features/main/default_order.feature | 36 +---- src/GraphQl/Type/FieldsBuilder.php | 75 +++++----- src/GraphQl/Type/TypeBuilder.php | 2 +- src/GraphQl/Type/TypeBuilderInterface.php | 2 +- .../Extractor/DynamicResourceExtractor.php | 50 ------- .../DynamicResourceExtractorInterface.php | 24 --- ...butesResourceMetadataCollectionFactory.php | 4 - ...actorResourceMetadataCollectionFactory.php | 27 +--- ...ltersResourceMetadataCollectionFactory.php | 4 - ...hpDocResourceMetadataCollectionFactory.php | 4 - .../Resource/ResourceMetadataCollection.php | 7 - .../Bundle/Resources/config/graphql.xml | 1 - .../Resources/config/metadata/resource.xml | 8 - tests/Behat/DoctrineContext.php | 17 +-- .../Fixtures/TestBundle/Document/FooDummy.php | 13 -- tests/Fixtures/TestBundle/Entity/FooDummy.php | 13 -- tests/Fixtures/TestBundle/Entity/SoMany.php | 3 - tests/GraphQl/Type/FieldsBuilderTest.php | 141 +++++++----------- tests/GraphQl/Type/TypeBuilderTest.php | 4 +- .../DynamicResourceExtractorTest.php | 37 ----- .../ResourceMetadataCompatibilityTest.php | 16 +- ...sResourceMetadataCollectionFactoryTest.php | 10 -- ...cResourceMetadataCollectionFactoryTest.php | 15 -- .../ApiPlatformExtensionTest.php | 2 - 25 files changed, 115 insertions(+), 446 deletions(-) delete mode 100644 src/Metadata/Extractor/DynamicResourceExtractor.php delete mode 100644 src/Metadata/Extractor/DynamicResourceExtractorInterface.php delete mode 100644 tests/Metadata/Extractor/DynamicResourceExtractorTest.php diff --git a/features/graphql/collection.feature b/features/graphql/collection.feature index 9767505171a..1540549f7d8 100644 --- a/features/graphql/collection.feature +++ b/features/graphql/collection.feature @@ -910,49 +910,3 @@ Feature: GraphQL collection support Then the response status code should be 200 And the response should be in JSON And the JSON node "data.fooDummies.collection" should have 1 element - - @createSchema - Scenario: Retrieve paginated collections using mixed pagination - Given there are 5 fooDummy objects with fake names - When I send the following GraphQL request: - """ - { - fooDummies(page: 1) { - collection { - id - name - soManies(first: 2) { - edges { - node { - content - } - cursor - } - pageInfo { - startCursor - endCursor - hasNextPage - hasPreviousPage - } - } - } - paginationInfo { - itemsPerPage - lastPage - totalCount - } - } - } - """ - Then the response status code should be 200 - And the response should be in JSON - And the JSON node "data.fooDummies.collection" should have 3 elements - And the JSON node "data.fooDummies.collection[2].id" should exist - And the JSON node "data.fooDummies.collection[2].name" should exist - And the JSON node "data.fooDummies.collection[2].soManies" should exist - And the JSON node "data.fooDummies.collection[2].soManies.edges" should have 2 elements - And the JSON node "data.fooDummies.collection[2].soManies.edges[1].node.content" should be equal to "So many 1" - And the JSON node "data.fooDummies.collection[2].soManies.pageInfo.startCursor" should be equal to "MA==" - And the JSON node "data.fooDummies.paginationInfo.itemsPerPage" should be equal to the number 3 - And the JSON node "data.fooDummies.paginationInfo.lastPage" should be equal to the number 2 - And the JSON node "data.fooDummies.paginationInfo.totalCount" should be equal to the number 5 diff --git a/features/main/default_order.feature b/features/main/default_order.feature index 7458c2456e9..91211014315 100644 --- a/features/main/default_order.feature +++ b/features/main/default_order.feature @@ -79,61 +79,35 @@ Feature: Default order "@type": "FooDummy", "id": 5, "name": "Balbo", - "dummy": "/dummies/5", - "soManies": [ - "/so_manies/13", - "/so_manies/14", - "/so_manies/15" - ] - + "dummy": "/dummies/5" }, { "@id": "/foo_dummies/3", "@type": "FooDummy", "id": 3, "name": "Sthenelus", - "dummy": "/dummies/3", - "soManies": [ - "/so_manies/7", - "/so_manies/8", - "/so_manies/9" - ] + "dummy": "/dummies/3" }, { "@id": "/foo_dummies/2", "@type": "FooDummy", "id": 2, "name": "Ephesian", - "dummy": "/dummies/2", - "soManies": [ - "/so_manies/4", - "/so_manies/5", - "/so_manies/6" - ] + "dummy": "/dummies/2" }, { "@id": "/foo_dummies/1", "@type": "FooDummy", "id": 1, "name": "Hawsepipe", - "dummy": "/dummies/1", - "soManies": [ - "/so_manies/1", - "/so_manies/2", - "/so_manies/3" - ] + "dummy": "/dummies/1" }, { "@id": "/foo_dummies/4", "@type": "FooDummy", "id": 4, "name": "Separativeness", - "dummy": "/dummies/4", - "soManies": [ - "/so_manies/10", - "/so_manies/11", - "/so_manies/12" - ] + "dummy": "/dummies/4" } ], "hydra:totalItems": 5, diff --git a/src/GraphQl/Type/FieldsBuilder.php b/src/GraphQl/Type/FieldsBuilder.php index 5d1f86e3569..8817899c8ef 100644 --- a/src/GraphQl/Type/FieldsBuilder.php +++ b/src/GraphQl/Type/FieldsBuilder.php @@ -17,10 +17,12 @@ use ApiPlatform\Exception\OperationNotFoundException; use ApiPlatform\GraphQl\Resolver\Factory\ResolverFactoryInterface; use ApiPlatform\GraphQl\Type\Definition\TypeInterface; -use ApiPlatform\Metadata\Extractor\DynamicResourceExtractorInterface; use ApiPlatform\Metadata\GraphQl\Mutation; use ApiPlatform\Metadata\GraphQl\Operation; +use ApiPlatform\Metadata\GraphQl\Query; +use ApiPlatform\Metadata\GraphQl\QueryCollection; use ApiPlatform\Metadata\GraphQl\Subscription; +use ApiPlatform\Metadata\Operation as AbstractOperation; use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; @@ -45,7 +47,7 @@ */ final class FieldsBuilder implements FieldsBuilderInterface { - public function __construct(private readonly PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, private readonly PropertyMetadataFactoryInterface $propertyMetadataFactory, private readonly ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, private readonly DynamicResourceExtractorInterface $dynamicResourceExtractor, private readonly ResourceClassResolverInterface $resourceClassResolver, private readonly TypesContainerInterface $typesContainer, private readonly TypeBuilderInterface $typeBuilder, private readonly TypeConverterInterface $typeConverter, private readonly ResolverFactoryInterface $itemResolverFactory, private readonly ResolverFactoryInterface $collectionResolverFactory, private readonly ResolverFactoryInterface $itemMutationResolverFactory, private readonly ResolverFactoryInterface $itemSubscriptionResolverFactory, private readonly ContainerInterface $filterLocator, private readonly Pagination $pagination, private readonly ?NameConverterInterface $nameConverter, private readonly string $nestingSeparator) + public function __construct(private readonly PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, private readonly PropertyMetadataFactoryInterface $propertyMetadataFactory, private readonly ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory, private readonly ResourceClassResolverInterface $resourceClassResolver, private readonly TypesContainerInterface $typesContainer, private readonly TypeBuilderInterface $typeBuilder, private readonly TypeConverterInterface $typeConverter, private readonly ResolverFactoryInterface $itemResolverFactory, private readonly ResolverFactoryInterface $collectionResolverFactory, private readonly ResolverFactoryInterface $itemMutationResolverFactory, private readonly ResolverFactoryInterface $itemSubscriptionResolverFactory, private readonly ContainerInterface $filterLocator, private readonly Pagination $pagination, private readonly ?NameConverterInterface $nameConverter, private readonly string $nestingSeparator) { } @@ -254,25 +256,7 @@ private function getResourceFieldConfiguration(?string $property, ?string $field $resourceClass = $type->getClassName(); } - $resourceOperation = $rootOperation; - if ($resourceClass && $rootOperation->getClass() && $this->resourceClassResolver->isResourceClass($resourceClass) && $rootOperation->getClass() !== $resourceClass) { - $resourceMetadataCollection = $this->resourceMetadataCollectionFactory->create($resourceClass); - try { - $resourceOperation = $resourceMetadataCollection->getOperation($isCollectionType ? 'collection_query' : 'item_query'); - } catch (OperationNotFoundException) { - // If there is no query operation for a nested resource, use a dynamic resource to get one. - $dynamicResourceMetadataCollection = $this->resourceMetadataCollectionFactory->create($this->dynamicResourceExtractor->addResource($resourceClass)); - - $resourceOperation = $dynamicResourceMetadataCollection->getOperation($isCollectionType ? 'collection_query' : 'item_query') - ->withResource($resourceMetadataCollection[0]); - } - } - - if (!$resourceOperation instanceof Operation) { - throw new \LogicException('The resource operation should be a GraphQL operation.'); - } - - $graphqlType = $this->convertType($type, $input, $resourceOperation, $rootOperation, $resourceClass ?? '', $rootResource, $property, $depth, $forceNullable); + $graphqlType = $this->convertType($type, $input, $rootOperation, $resourceClass ?? '', $rootResource, $property, $depth, $forceNullable); $graphqlWrappedType = $graphqlType instanceof WrappingType ? $graphqlType->getWrappedType(true) : $graphqlType; $isStandardGraphqlType = \in_array($graphqlWrappedType, GraphQLType::getStandardTypes(), true); @@ -287,22 +271,43 @@ private function getResourceFieldConfiguration(?string $property, ?string $field $args = []; + $resolverOperation = $rootOperation; + + if ($resourceClass && $this->resourceClassResolver->isResourceClass($resourceClass) && $rootOperation->getClass() !== $resourceClass) { + $resourceMetadataCollection = $this->resourceMetadataCollectionFactory->create($resourceClass); + $resolverOperation = $resourceMetadataCollection->getOperation(null, $isCollectionType); + + if (!$resolverOperation instanceof Operation) { + $resolverOperation = ($isCollectionType ? new QueryCollection() : new Query())->withOperation($resolverOperation); + } + } + if (!$input && !$rootOperation instanceof Mutation && !$rootOperation instanceof Subscription && !$isStandardGraphqlType && $isCollectionType) { - if ($this->pagination->isGraphQlEnabled($resourceOperation)) { - $args = $this->getGraphQlPaginationArgs($resourceOperation); + if ($this->pagination->isGraphQlEnabled($rootOperation)) { + $args = $this->getGraphQlPaginationArgs($rootOperation); + } + + // Find the collection operation to get filters, there might be a smarter way to do this + $operation = null; + if (!empty($resourceClass)) { + $resourceMetadataCollection = $this->resourceMetadataCollectionFactory->create($resourceClass); + try { + $operation = $resourceMetadataCollection->getOperation(null, true); + } catch (OperationNotFoundException) { + } } - $args = $this->getFilterArgs($args, $resourceClass, $rootResource, $resourceOperation, $rootOperation, $property, $depth); + $args = $this->getFilterArgs($args, $resourceClass, $rootResource, $rootOperation, $property, $depth, $operation); } if ($isStandardGraphqlType || $input) { $resolve = null; } elseif (($rootOperation instanceof Mutation || $rootOperation instanceof Subscription) && $depth <= 0) { - $resolve = $rootOperation instanceof Mutation ? ($this->itemMutationResolverFactory)($resourceClass, $rootResource, $resourceOperation) : ($this->itemSubscriptionResolverFactory)($resourceClass, $rootResource, $resourceOperation); + $resolve = $rootOperation instanceof Mutation ? ($this->itemMutationResolverFactory)($resourceClass, $rootResource, $resolverOperation) : ($this->itemSubscriptionResolverFactory)($resourceClass, $rootResource, $resolverOperation); } elseif ($this->typeBuilder->isCollection($type)) { - $resolve = ($this->collectionResolverFactory)($resourceClass, $rootResource, $resourceOperation); + $resolve = ($this->collectionResolverFactory)($resourceClass, $rootResource, $resolverOperation); } else { - $resolve = ($this->itemResolverFactory)($resourceClass, $rootResource, $resourceOperation); + $resolve = ($this->itemResolverFactory)($resourceClass, $rootResource, $resolverOperation); } return [ @@ -363,13 +368,13 @@ private function getGraphQlPaginationArgs(Operation $queryOperation): array return $args; } - private function getFilterArgs(array $args, ?string $resourceClass, string $rootResource, Operation $resourceOperation, Operation $rootOperation, ?string $property, int $depth): array + private function getFilterArgs(array $args, ?string $resourceClass, string $rootResource, Operation $rootOperation, ?string $property, int $depth, ?AbstractOperation $operation = null): array { - if (null === $resourceClass) { + if (null === $operation || null === $resourceClass) { return $args; } - foreach ($resourceOperation->getFilters() ?? [] as $filterId) { + foreach ($operation->getFilters() ?? [] as $filterId) { if (!$this->filterLocator->has($filterId)) { continue; } @@ -377,7 +382,7 @@ private function getFilterArgs(array $args, ?string $resourceClass, string $root foreach ($this->filterLocator->get($filterId)->getDescription($resourceClass) as $key => $value) { $nullable = isset($value['required']) ? !$value['required'] : true; $filterType = \in_array($value['type'], Type::$builtinTypes, true) ? new Type($value['type'], $nullable) : new Type('object', $nullable, $value['type']); - $graphqlFilterType = $this->convertType($filterType, false, $resourceOperation, $rootOperation, $resourceClass, $rootResource, $property, $depth); + $graphqlFilterType = $this->convertType($filterType, false, $rootOperation, $resourceClass, $rootResource, $property, $depth); if (str_ends_with($key, '[]')) { $graphqlFilterType = GraphQLType::listOf($graphqlFilterType); @@ -394,14 +399,14 @@ private function getFilterArgs(array $args, ?string $resourceClass, string $root array_walk_recursive($parsed, static function (&$value) use ($graphqlFilterType): void { $value = $graphqlFilterType; }); - $args = $this->mergeFilterArgs($args, $parsed, $resourceOperation, $key); + $args = $this->mergeFilterArgs($args, $parsed, $operation, $key); } } return $this->convertFilterArgsToTypes($args); } - private function mergeFilterArgs(array $args, array $parsed, ?Operation $operation = null, string $original = ''): array + private function mergeFilterArgs(array $args, array $parsed, ?AbstractOperation $operation = null, string $original = ''): array { foreach ($parsed as $key => $value) { // Never override keys that cannot be merged @@ -465,7 +470,7 @@ private function convertFilterArgsToTypes(array $args): array * * @throws InvalidTypeException */ - private function convertType(Type $type, bool $input, Operation $resourceOperation, Operation $rootOperation, string $resourceClass, string $rootResource, ?string $property, int $depth, bool $forceNullable = false): GraphQLType|ListOfType|NonNull + private function convertType(Type $type, bool $input, Operation $rootOperation, string $resourceClass, string $rootResource, ?string $property, int $depth, bool $forceNullable = false): GraphQLType|ListOfType|NonNull { $graphqlType = $this->typeConverter->convertType($type, $input, $rootOperation, $resourceClass, $rootResource, $property, $depth); @@ -482,7 +487,7 @@ private function convertType(Type $type, bool $input, Operation $resourceOperati } if ($this->typeBuilder->isCollection($type)) { - return $this->pagination->isGraphQlEnabled($resourceOperation) && !$input ? $this->typeBuilder->getResourcePaginatedCollectionType($graphqlType, $resourceOperation) : GraphQLType::listOf($graphqlType); + return $this->pagination->isGraphQlEnabled($rootOperation) && !$input ? $this->typeBuilder->getResourcePaginatedCollectionType($graphqlType, $resourceClass, $rootOperation) : GraphQLType::listOf($graphqlType); } return $forceNullable || !$graphqlType instanceof NullableType || $type->isNullable() || ($rootOperation instanceof Mutation && 'update' === $rootOperation->getName()) diff --git a/src/GraphQl/Type/TypeBuilder.php b/src/GraphQl/Type/TypeBuilder.php index 447897114be..acc2d9429ee 100644 --- a/src/GraphQl/Type/TypeBuilder.php +++ b/src/GraphQl/Type/TypeBuilder.php @@ -210,7 +210,7 @@ public function getNodeInterface(): InterfaceType /** * {@inheritdoc} */ - public function getResourcePaginatedCollectionType(GraphQLType $resourceType, Operation $operation): GraphQLType + public function getResourcePaginatedCollectionType(GraphQLType $resourceType, string $resourceClass, Operation $operation): GraphQLType { $shortName = $resourceType->name; $paginationType = $this->pagination->getGraphQlPaginationType($operation); diff --git a/src/GraphQl/Type/TypeBuilderInterface.php b/src/GraphQl/Type/TypeBuilderInterface.php index 386c437495d..50bb0077893 100644 --- a/src/GraphQl/Type/TypeBuilderInterface.php +++ b/src/GraphQl/Type/TypeBuilderInterface.php @@ -43,7 +43,7 @@ public function getNodeInterface(): InterfaceType; /** * Gets the type of a paginated collection of the given resource type. */ - public function getResourcePaginatedCollectionType(GraphQLType $resourceType, Operation $operation): GraphQLType; + public function getResourcePaginatedCollectionType(GraphQLType $resourceType, string $resourceClass, Operation $operation): GraphQLType; /** * Returns true if a type is a collection. diff --git a/src/Metadata/Extractor/DynamicResourceExtractor.php b/src/Metadata/Extractor/DynamicResourceExtractor.php deleted file mode 100644 index dd5c909c1b7..00000000000 --- a/src/Metadata/Extractor/DynamicResourceExtractor.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace ApiPlatform\Metadata\Extractor; - -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; - -/** - * Extracts a dynamic resource (used by GraphQL for nested resources). - * - * @author Alan Poulain - */ -final class DynamicResourceExtractor implements DynamicResourceExtractorInterface -{ - private array $dynamicResources = []; - - /** - * {@inheritdoc} - */ - public function getResources(): array - { - return $this->dynamicResources; - } - - public function addResource(string $resourceClass, array $config = []): string - { - $dynamicResourceName = $this->getDynamicResourceName($resourceClass); - - $this->dynamicResources[$dynamicResourceName] = [ - array_merge(['class' => $resourceClass], $config), - ]; - - return $dynamicResourceName; - } - - private function getDynamicResourceName(string $resourceClass): string - { - return ResourceMetadataCollection::DYNAMIC_RESOURCE_CLASS_PREFIX.$resourceClass; - } -} diff --git a/src/Metadata/Extractor/DynamicResourceExtractorInterface.php b/src/Metadata/Extractor/DynamicResourceExtractorInterface.php deleted file mode 100644 index c14e589fc63..00000000000 --- a/src/Metadata/Extractor/DynamicResourceExtractorInterface.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace ApiPlatform\Metadata\Extractor; - -/** - * Extracts a dynamic resource (used by GraphQL for nested resources). - * - * @author Alan Poulain - */ -interface DynamicResourceExtractorInterface extends ResourceExtractorInterface -{ - public function addResource(string $resourceClass, array $config = []): string; -} diff --git a/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php index ad77154eb3d..9255c236fa8 100644 --- a/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php @@ -64,10 +64,6 @@ public function create(string $resourceClass): ResourceMetadataCollection $resourceMetadataCollection = $this->decorated->create($resourceClass); } - if ($resourceMetadataCollection->isDynamic()) { - return $resourceMetadataCollection; - } - try { $reflectionClass = new \ReflectionClass($resourceClass); } catch (\ReflectionException) { diff --git a/src/Metadata/Resource/Factory/ExtractorResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/ExtractorResourceMetadataCollectionFactory.php index 711d70348da..c44358897ca 100644 --- a/src/Metadata/Resource/Factory/ExtractorResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/ExtractorResourceMetadataCollectionFactory.php @@ -19,12 +19,7 @@ use ApiPlatform\Metadata\Extractor\ResourceExtractorInterface; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\GraphQl\DeleteMutation; -use ApiPlatform\Metadata\GraphQl\Mutation; -use ApiPlatform\Metadata\GraphQl\Query; -use ApiPlatform\Metadata\GraphQl\QueryCollection; use ApiPlatform\Metadata\HttpOperation; -use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; @@ -56,7 +51,7 @@ public function create(string $resourceClass): ResourceMetadataCollection $resourceMetadataCollection = $this->decorated->create($resourceClass); } - if (!($resourceMetadataCollection->isDynamic() || class_exists($resourceClass) || interface_exists($resourceClass)) || !$resources = $this->extractor->getResources()[$resourceClass] ?? false) { + if (!(class_exists($resourceClass) || interface_exists($resourceClass)) || !$resources = $this->extractor->getResources()[$resourceClass] ?? false) { return $resourceMetadataCollection; } @@ -93,7 +88,9 @@ private function buildResources(array $nodes, string $resourceClass): array } } - $resource = $resource->withGraphQlOperations($this->buildGraphQlOperations($node['graphQlOperations'] ?? null, $resource)); + if (isset($node['graphQlOperations'])) { + $resource = $resource->withGraphQlOperations($this->buildGraphQlOperations($node['graphQlOperations'], $resource)); + } $resources[] = $resource->withOperations(new Operations($this->buildOperations($node['operations'] ?? null, $resource))); } @@ -151,20 +148,6 @@ private function buildGraphQlOperations(?array $data, ApiResource $resource): ar { $operations = []; - if (null === $data) { - foreach ([new QueryCollection(), new Query(), (new Mutation())->withName('update'), (new DeleteMutation())->withName('delete'), (new Mutation())->withName('create')] as $operation) { - $operation = $this->getOperationWithDefaults($resource, $operation); - - if ($operation instanceof Mutation) { - $operation = $operation->withDescription(ucfirst("{$operation->getName()}s a {$resource->getShortName()}.")); - } - - $operations[$operation->getName()] = $operation; - } - - return $operations; - } - foreach ($data as $attributes) { /** @var HttpOperation $operation */ $operation = (new $attributes['graphql_operation_class']())->withShortName($resource->getShortName()); @@ -192,7 +175,7 @@ private function buildGraphQlOperations(?array $data, ApiResource $resource): ar return $operations; } - private function getOperationWithDefaults(ApiResource $resource, Operation $operation): Operation + private function getOperationWithDefaults(ApiResource $resource, HttpOperation $operation): HttpOperation { foreach (($this->defaults['attributes'] ?? []) as $key => $value) { $key = $this->camelCaseToSnakeCaseNameConverter->denormalize($key); diff --git a/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php index ef72c3b1799..bb68448c4c2 100644 --- a/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/FiltersResourceMetadataCollectionFactory.php @@ -41,10 +41,6 @@ public function create(string $resourceClass): ResourceMetadataCollection $resourceMetadataCollection = $this->decorated->create($resourceClass); } - if ($resourceMetadataCollection->isDynamic()) { - return $resourceMetadataCollection; - } - try { $reflectionClass = new \ReflectionClass($resourceClass); } catch (\ReflectionException) { diff --git a/src/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactory.php b/src/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactory.php index 57b862f76b7..b94e6bffdf1 100644 --- a/src/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactory.php +++ b/src/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactory.php @@ -42,10 +42,6 @@ public function create(string $resourceClass): ResourceMetadataCollection { $resourceMetadataCollection = $this->decorated->create($resourceClass); - if ($resourceMetadataCollection->isDynamic()) { - return $resourceMetadataCollection; - } - foreach ($resourceMetadataCollection as $key => $resourceMetadata) { if (null !== $resourceMetadata->getDescription()) { continue; diff --git a/src/Metadata/Resource/ResourceMetadataCollection.php b/src/Metadata/Resource/ResourceMetadataCollection.php index 28eff63c2f0..2921635706b 100644 --- a/src/Metadata/Resource/ResourceMetadataCollection.php +++ b/src/Metadata/Resource/ResourceMetadataCollection.php @@ -24,8 +24,6 @@ */ final class ResourceMetadataCollection extends \ArrayObject { - public const DYNAMIC_RESOURCE_CLASS_PREFIX = 'Dynamic#'; - private array $operationCache = []; public function __construct(private readonly string $resourceClass, array $input = []) @@ -88,11 +86,6 @@ public function getOperation(?string $operationName = null, bool $forceCollectio $this->handleNotFound($operationName, $metadata); } - public function isDynamic(): bool - { - return str_starts_with($this->resourceClass, self::DYNAMIC_RESOURCE_CLASS_PREFIX); - } - /** * @throws OperationNotFoundException */ diff --git a/src/Symfony/Bundle/Resources/config/graphql.xml b/src/Symfony/Bundle/Resources/config/graphql.xml index 154dd90783a..b5a8e4e80e5 100644 --- a/src/Symfony/Bundle/Resources/config/graphql.xml +++ b/src/Symfony/Bundle/Resources/config/graphql.xml @@ -121,7 +121,6 @@ - diff --git a/src/Symfony/Bundle/Resources/config/metadata/resource.xml b/src/Symfony/Bundle/Resources/config/metadata/resource.xml index 31bb563593b..91d5d1a669a 100644 --- a/src/Symfony/Bundle/Resources/config/metadata/resource.xml +++ b/src/Symfony/Bundle/Resources/config/metadata/resource.xml @@ -23,14 +23,6 @@ %api_platform.defaults% - - - - - - %api_platform.defaults% - - diff --git a/tests/Behat/DoctrineContext.php b/tests/Behat/DoctrineContext.php index 37aaa67205b..5e02353fcfb 100644 --- a/tests/Behat/DoctrineContext.php +++ b/tests/Behat/DoctrineContext.php @@ -286,10 +286,10 @@ public function thereArePaginationEntities(int $nb): void public function thereAreOfTheseSoManyObjects(int $nb): void { for ($i = 1; $i <= $nb; ++$i) { - $soMany = $this->buildSoMany(); - $soMany->content = 'Many #'.$i; + $dummy = $this->isOrm() ? new SoMany() : new SoManyDocument(); + $dummy->content = 'Many #'.$i; - $this->manager->persist($soMany); + $this->manager->persist($dummy); } $this->manager->flush(); @@ -340,12 +340,6 @@ public function thereAreFooDummyObjectsWithFakeNames($nb): void $foo = $this->buildFooDummy(); $foo->setName($names[$i]); $foo->setDummy($dummy); - for ($j = 0; $j < 3; ++$j) { - $soMany = $this->buildSoMany(); - $soMany->content = "So many $j"; - $soMany->fooDummy = $foo; - $foo->soManies->add($soMany); - } $this->manager->persist($foo); } @@ -2206,11 +2200,6 @@ private function buildRelatedSecureDummy(): RelatedSecuredDummy|RelatedSecuredDu return $this->isOrm() ? new RelatedSecuredDummy() : new RelatedSecuredDummyDocument(); } - private function buildSoMany(): SoMany|SoManyDocument - { - return $this->isOrm() ? new SoMany() : new SoManyDocument(); - } - private function buildThirdLevel(): ThirdLevel|ThirdLevelDocument { return $this->isOrm() ? new ThirdLevel() : new ThirdLevelDocument(); diff --git a/tests/Fixtures/TestBundle/Document/FooDummy.php b/tests/Fixtures/TestBundle/Document/FooDummy.php index 8736509e855..cc9fe959f25 100644 --- a/tests/Fixtures/TestBundle/Document/FooDummy.php +++ b/tests/Fixtures/TestBundle/Document/FooDummy.php @@ -15,8 +15,6 @@ use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\QueryCollection; -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; /** @@ -44,17 +42,6 @@ class FooDummy #[ODM\ReferenceOne(targetDocument: Dummy::class, cascade: ['persist'], storeAs: 'id')] private ?Dummy $dummy = null; - /** - * @var Collection - */ - #[ODM\ReferenceMany(targetDocument: SoMany::class, cascade: ['persist'], storeAs: 'id')] - public Collection $soManies; - - public function __construct() - { - $this->soManies = new ArrayCollection(); - } - public function getId(): ?int { return $this->id; diff --git a/tests/Fixtures/TestBundle/Entity/FooDummy.php b/tests/Fixtures/TestBundle/Entity/FooDummy.php index 92596dad682..b744c0c2a55 100644 --- a/tests/Fixtures/TestBundle/Entity/FooDummy.php +++ b/tests/Fixtures/TestBundle/Entity/FooDummy.php @@ -15,8 +15,6 @@ use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GraphQl\QueryCollection; -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; /** @@ -46,17 +44,6 @@ class FooDummy #[ORM\ManyToOne(targetEntity: Dummy::class, cascade: ['persist'])] private ?Dummy $dummy = null; - /** - * @var Collection - */ - #[ORM\OneToMany(targetEntity: SoMany::class, mappedBy: 'fooDummy', cascade: ['persist'])] - public Collection $soManies; - - public function __construct() - { - $this->soManies = new ArrayCollection(); - } - public function getId(): ?int { return $this->id; diff --git a/tests/Fixtures/TestBundle/Entity/SoMany.php b/tests/Fixtures/TestBundle/Entity/SoMany.php index e3770b8007d..65a2ad93790 100644 --- a/tests/Fixtures/TestBundle/Entity/SoMany.php +++ b/tests/Fixtures/TestBundle/Entity/SoMany.php @@ -31,7 +31,4 @@ class SoMany public $id; #[ORM\Column(nullable: true)] public $content; - - #[ORM\ManyToOne] - public ?FooDummy $fooDummy; } diff --git a/tests/GraphQl/Type/FieldsBuilderTest.php b/tests/GraphQl/Type/FieldsBuilderTest.php index ab08c118efa..c7bb3ba897a 100644 --- a/tests/GraphQl/Type/FieldsBuilderTest.php +++ b/tests/GraphQl/Type/FieldsBuilderTest.php @@ -22,7 +22,6 @@ use ApiPlatform\GraphQl\Type\TypesContainerInterface; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; -use ApiPlatform\Metadata\Extractor\DynamicResourceExtractorInterface; use ApiPlatform\Metadata\GraphQl\Mutation; use ApiPlatform\Metadata\GraphQl\Operation; use ApiPlatform\Metadata\GraphQl\Query; @@ -57,18 +56,29 @@ class FieldsBuilderTest extends TestCase use ProphecyTrait; private ObjectProphecy $propertyNameCollectionFactoryProphecy; + private ObjectProphecy $propertyMetadataFactoryProphecy; + private ObjectProphecy $resourceMetadataCollectionFactoryProphecy; - private ObjectProphecy $dynamicResourceExtractorProphecy; + private ObjectProphecy $typesContainerProphecy; + private ObjectProphecy $typeBuilderProphecy; + private ObjectProphecy $typeConverterProphecy; + private ObjectProphecy $itemResolverFactoryProphecy; + private ObjectProphecy $collectionResolverFactoryProphecy; + private ObjectProphecy $itemMutationResolverFactoryProphecy; + private ObjectProphecy $itemSubscriptionResolverFactoryProphecy; + private ObjectProphecy $filterLocatorProphecy; + private ObjectProphecy $resourceClassResolverProphecy; + private FieldsBuilder $fieldsBuilder; /** @@ -79,7 +89,6 @@ protected function setUp(): void $this->propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $this->propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); $this->resourceMetadataCollectionFactoryProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $this->dynamicResourceExtractorProphecy = $this->prophesize(DynamicResourceExtractorInterface::class); $this->typesContainerProphecy = $this->prophesize(TypesContainerInterface::class); $this->typeBuilderProphecy = $this->prophesize(TypeBuilderInterface::class); $this->typeConverterProphecy = $this->prophesize(TypeConverterInterface::class); @@ -94,7 +103,7 @@ protected function setUp(): void private function buildFieldsBuilder(?AdvancedNameConverterInterface $advancedNameConverter = null): FieldsBuilder { - return new FieldsBuilder($this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->dynamicResourceExtractorProphecy->reveal(), $this->resourceClassResolverProphecy->reveal(), $this->typesContainerProphecy->reveal(), $this->typeBuilderProphecy->reveal(), $this->typeConverterProphecy->reveal(), $this->itemResolverFactoryProphecy->reveal(), $this->collectionResolverFactoryProphecy->reveal(), $this->itemMutationResolverFactoryProphecy->reveal(), $this->itemSubscriptionResolverFactoryProphecy->reveal(), $this->filterLocatorProphecy->reveal(), new Pagination(), $advancedNameConverter ?? new CustomConverter(), '__'); + return new FieldsBuilder($this->propertyNameCollectionFactoryProphecy->reveal(), $this->propertyMetadataFactoryProphecy->reveal(), $this->resourceMetadataCollectionFactoryProphecy->reveal(), $this->resourceClassResolverProphecy->reveal(), $this->typesContainerProphecy->reveal(), $this->typeBuilderProphecy->reveal(), $this->typeConverterProphecy->reveal(), $this->itemResolverFactoryProphecy->reveal(), $this->collectionResolverFactoryProphecy->reveal(), $this->itemMutationResolverFactoryProphecy->reveal(), $this->itemSubscriptionResolverFactoryProphecy->reveal(), $this->filterLocatorProphecy->reveal(), new Pagination(), $advancedNameConverter ?? new CustomConverter(), '__'); } public function testGetNodeQueryFields(): void @@ -130,6 +139,7 @@ public function testGetItemQueryFields(string $resourceClass, Operation $operati $this->typeConverterProphecy->convertType(Argument::type(Type::class), false, Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), $resourceClass, $resourceClass, null, 0)->willReturn($graphqlType); $this->typeConverterProphecy->resolveType(Argument::type('string'))->willReturn(GraphQLType::string()); $this->typeBuilderProphecy->isCollection(Argument::type(Type::class))->willReturn(false); + $this->resourceMetadataCollectionFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadataCollection($resourceClass, [(new ApiResource())->withGraphQlOperations([$operation->getName() => $operation])])); $this->itemResolverFactoryProphecy->__invoke($resourceClass, $resourceClass, $operation)->willReturn($resolver); $queryFields = $this->fieldsBuilder->getItemQueryFields($resourceClass, $operation, $configuration); @@ -140,8 +150,8 @@ public function testGetItemQueryFields(string $resourceClass, Operation $operati public function itemQueryFieldsProvider(): array { return [ - 'no resource field configuration' => ['resourceClass', (new Query())->withClass('resourceClass')->withName('action'), [], null, null, []], - 'nominal standard type case with deprecation reason and description' => ['resourceClass', (new Query())->withClass('resourceClass')->withName('action')->withShortName('ShortName')->withDeprecationReason('not useful')->withDescription('Custom description.'), [], GraphQLType::string(), null, + 'no resource field configuration' => ['resourceClass', (new Query())->withName('action'), [], null, null, []], + 'nominal standard type case with deprecation reason and description' => ['resourceClass', (new Query())->withName('action')->withShortName('ShortName')->withDeprecationReason('not useful')->withDescription('Custom description.'), [], GraphQLType::string(), null, [ 'actionShortName' => [ 'type' => GraphQLType::string(), @@ -154,7 +164,7 @@ public function itemQueryFieldsProvider(): array ], ], ], - 'nominal item case' => ['resourceClass', (new Query())->withClass('resourceClass')->withName('action')->withShortName('ShortName'), [], $graphqlType = new ObjectType(['name' => 'item']), $resolver = function (): void { + 'nominal item case' => ['resourceClass', (new Query())->withName('action')->withShortName('ShortName'), [], $graphqlType = new ObjectType(['name' => 'item']), $resolver = function (): void { }, [ 'actionShortName' => [ @@ -169,7 +179,7 @@ public function itemQueryFieldsProvider(): array ], ], 'empty overridden args and add fields' => [ - 'resourceClass', (new Query())->withClass('resourceClass')->withShortName('ShortName'), ['args' => [], 'name' => 'customActionName'], GraphQLType::string(), null, + 'resourceClass', (new Query())->withShortName('ShortName'), ['args' => [], 'name' => 'customActionName'], GraphQLType::string(), null, [ 'shortName' => [ 'type' => GraphQLType::string(), @@ -182,7 +192,7 @@ public function itemQueryFieldsProvider(): array ], ], 'override args with custom ones' => [ - 'resourceClass', (new Query())->withClass('resourceClass')->withShortName('ShortName'), ['args' => ['customArg' => ['type' => 'a type']]], GraphQLType::string(), null, + 'resourceClass', (new Query())->withShortName('ShortName'), ['args' => ['customArg' => ['type' => 'a type']]], GraphQLType::string(), null, [ 'shortName' => [ 'type' => GraphQLType::string(), @@ -209,7 +219,8 @@ public function testGetCollectionQueryFields(string $resourceClass, Operation $o $this->typeConverterProphecy->convertType(Argument::type(Type::class), false, Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), $resourceClass, $resourceClass, null, 0)->willReturn($graphqlType); $this->typeConverterProphecy->resolveType(Argument::type('string'))->willReturn(GraphQLType::string()); $this->typeBuilderProphecy->isCollection(Argument::type(Type::class))->willReturn(true); - $this->typeBuilderProphecy->getResourcePaginatedCollectionType($graphqlType, $operation)->willReturn($graphqlType); + $this->typeBuilderProphecy->getResourcePaginatedCollectionType($graphqlType, $resourceClass, $operation)->willReturn($graphqlType); + $this->resourceMetadataCollectionFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadataCollection($resourceClass, [(new ApiResource())->withGraphQlOperations([$operation->getName() => $operation])])); $this->collectionResolverFactoryProphecy->__invoke($resourceClass, $resourceClass, $operation)->willReturn($resolver); $this->filterLocatorProphecy->has('my_filter')->willReturn(true); $filterProphecy = $this->prophesize(FilterInterface::class); @@ -233,8 +244,8 @@ public function testGetCollectionQueryFields(string $resourceClass, Operation $o public function collectionQueryFieldsProvider(): array { return [ - 'no resource field configuration' => ['resourceClass', (new QueryCollection())->withClass('resourceClass')->withName('action'), [], null, null, []], - 'nominal collection case with deprecation reason and description' => ['resourceClass', (new QueryCollection())->withClass('resourceClass')->withName('action')->withShortName('ShortName')->withDeprecationReason('not useful')->withDescription('Custom description.'), [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function (): void { + 'no resource field configuration' => ['resourceClass', (new QueryCollection())->withName('action'), [], null, null, []], + 'nominal collection case with deprecation reason and description' => ['resourceClass', (new QueryCollection())->withName('action')->withShortName('ShortName')->withDeprecationReason('not useful')->withDescription('Custom description.'), [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function (): void { }, [ 'actionShortNames' => [ @@ -263,7 +274,7 @@ public function collectionQueryFieldsProvider(): array ], ], ], - 'collection with filters' => ['resourceClass', (new QueryCollection())->withClass('resourceClass')->withName('action')->withShortName('ShortName')->withFilters(['my_filter']), [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function (): void { + 'collection with filters' => ['resourceClass', (new QueryCollection())->withName('action')->withShortName('ShortName')->withFilters(['my_filter']), [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function (): void { }, [ 'actionShortNames' => [ @@ -297,7 +308,7 @@ public function collectionQueryFieldsProvider(): array ], ], 'collection empty overridden args and add fields' => [ - 'resourceClass', (new QueryCollection())->withArgs([])->withClass('resourceClass')->withName('action')->withShortName('ShortName'), ['args' => [], 'name' => 'customActionName'], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function (): void { + 'resourceClass', (new QueryCollection())->withArgs([])->withName('action')->withShortName('ShortName'), ['args' => [], 'name' => 'customActionName'], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function (): void { }, [ 'actionShortNames' => [ @@ -311,7 +322,7 @@ public function collectionQueryFieldsProvider(): array ], ], 'collection override args with custom ones' => [ - 'resourceClass', (new QueryCollection())->withClass('resourceClass')->withName('action')->withShortName('ShortName'), ['args' => ['customArg' => ['type' => 'a type']]], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function (): void { + 'resourceClass', (new QueryCollection())->withName('action')->withShortName('ShortName'), ['args' => ['customArg' => ['type' => 'a type']]], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function (): void { }, [ 'actionShortNames' => [ @@ -327,7 +338,7 @@ public function collectionQueryFieldsProvider(): array ], ], ], - 'collection with page-based pagination enabled' => ['resourceClass', (new QueryCollection())->withClass('resourceClass')->withName('action')->withShortName('ShortName')->withPaginationType('page')->withFilters(['my_filter']), [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function (): void { + 'collection with page-based pagination enabled' => ['resourceClass', (new QueryCollection())->withName('action')->withShortName('ShortName')->withPaginationType('page')->withFilters(['my_filter']), [], $graphqlType = GraphQLType::listOf(new ObjectType(['name' => 'collection'])), $resolver = function (): void { }, [ 'actionShortNames' => [ @@ -360,6 +371,8 @@ public function testGetMutationFields(string $resourceClass, Operation $operatio $this->typeConverterProphecy->convertType(Argument::type(Type::class), false, Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), $resourceClass, $resourceClass, null, 0)->willReturn($graphqlType); $this->typeConverterProphecy->convertType(Argument::type(Type::class), true, Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), $resourceClass, $resourceClass, null, 0)->willReturn($inputGraphqlType); $this->typeBuilderProphecy->isCollection(Argument::type(Type::class))->willReturn(false); + $this->typeBuilderProphecy->getResourcePaginatedCollectionType($graphqlType, $resourceClass, $operation->getName())->willReturn($graphqlType); + $this->resourceMetadataCollectionFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadataCollection($resourceClass, [(new ApiResource())->withGraphQlOperations([$operation->getName() => $operation])])); $this->itemMutationResolverFactoryProphecy->__invoke($resourceClass, $resourceClass, $operation)->willReturn($mutationResolver); $mutationFields = $this->fieldsBuilder->getMutationFields($resourceClass, $operation); @@ -370,7 +383,7 @@ public function testGetMutationFields(string $resourceClass, Operation $operatio public function mutationFieldsProvider(): array { return [ - 'nominal case with deprecation reason' => ['resourceClass', (new Mutation())->withClass('resourceClass')->withName('action')->withShortName('ShortName')->withDeprecationReason('not useful'), $graphqlType = new ObjectType(['name' => 'mutation']), $inputGraphqlType = new ObjectType(['name' => 'input']), $mutationResolver = function (): void { + 'nominal case with deprecation reason' => ['resourceClass', (new Mutation())->withName('action')->withShortName('ShortName')->withDeprecationReason('not useful'), $graphqlType = new ObjectType(['name' => 'mutation']), $inputGraphqlType = new ObjectType(['name' => 'input']), $mutationResolver = function (): void { }, [ 'actionShortName' => [ @@ -390,7 +403,7 @@ public function mutationFieldsProvider(): array ], ], ], - 'custom description' => ['resourceClass', (new Mutation())->withClass('resourceClass')->withName('action')->withShortName('ShortName')->withDescription('Custom description.'), $graphqlType = new ObjectType(['name' => 'mutation']), $inputGraphqlType = new ObjectType(['name' => 'input']), $mutationResolver = function (): void { + 'custom description' => ['resourceClass', (new Mutation())->withName('action')->withShortName('ShortName')->withDescription('Custom description.'), $graphqlType = new ObjectType(['name' => 'mutation']), $inputGraphqlType = new ObjectType(['name' => 'input']), $mutationResolver = function (): void { }, [ 'actionShortName' => [ @@ -422,6 +435,7 @@ public function testGetSubscriptionFields(string $resourceClass, Operation $oper $this->typeConverterProphecy->convertType(Argument::type(Type::class), false, Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), $resourceClass, $resourceClass, null, 0)->willReturn($graphqlType); $this->typeConverterProphecy->convertType(Argument::type(Type::class), true, Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), $resourceClass, $resourceClass, null, 0)->willReturn($inputGraphqlType); $this->typeBuilderProphecy->isCollection(Argument::type(Type::class))->willReturn(false); + $this->typeBuilderProphecy->getResourcePaginatedCollectionType($graphqlType, $resourceClass, $operation->getName())->willReturn($graphqlType); $this->resourceMetadataCollectionFactoryProphecy->create($resourceClass)->willReturn(new ResourceMetadataCollection($resourceClass, [(new ApiResource())->withGraphQlOperations([$operation->getName() => $operation])])); $this->itemSubscriptionResolverFactoryProphecy->__invoke($resourceClass, $resourceClass, $operation)->willReturn($subscriptionResolver); @@ -433,9 +447,9 @@ public function testGetSubscriptionFields(string $resourceClass, Operation $oper public function subscriptionFieldsProvider(): array { return [ - 'mercure not enabled' => ['resourceClass', (new Subscription())->withClass('resourceClass')->withName('action')->withShortName('ShortName'), new ObjectType(['name' => 'subscription']), new ObjectType(['name' => 'input']), null, [], + 'mercure not enabled' => ['resourceClass', (new Subscription())->withName('action')->withShortName('ShortName'), new ObjectType(['name' => 'subscription']), new ObjectType(['name' => 'input']), null, [], ], - 'nominal case with deprecation reason' => ['resourceClass', (new Subscription())->withClass('resourceClass')->withName('action')->withShortName('ShortName')->withMercure(true)->withDeprecationReason('not useful'), $graphqlType = new ObjectType(['name' => 'subscription']), $inputGraphqlType = new ObjectType(['name' => 'input']), $subscriptionResolver = function (): void { + 'nominal case with deprecation reason' => ['resourceClass', (new Subscription())->withName('action')->withShortName('ShortName')->withMercure(true)->withDeprecationReason('not useful'), $graphqlType = new ObjectType(['name' => 'subscription']), $inputGraphqlType = new ObjectType(['name' => 'input']), $subscriptionResolver = function (): void { }, [ 'actionShortNameSubscribe' => [ @@ -455,7 +469,7 @@ public function subscriptionFieldsProvider(): array ], ], ], - 'custom description' => ['resourceClass', (new Subscription())->withClass('resourceClass')->withName('action')->withShortName('ShortName')->withMercure(true)->withDescription('Custom description.'), $graphqlType = new ObjectType(['name' => 'subscription']), $inputGraphqlType = new ObjectType(['name' => 'input']), $subscriptionResolver = function (): void { + 'custom description' => ['resourceClass', (new Subscription())->withName('action')->withShortName('ShortName')->withMercure(true)->withDescription('Custom description.'), $graphqlType = new ObjectType(['name' => 'subscription']), $inputGraphqlType = new ObjectType(['name' => 'input']), $subscriptionResolver = function (): void { }, [ 'actionShortNameSubscribe' => [ @@ -484,8 +498,6 @@ public function subscriptionFieldsProvider(): array public function testGetResourceObjectTypeFields(string $resourceClass, Operation $operation, array $properties, bool $input, int $depth, ?array $ioMetadata, array $expectedResourceObjectTypeFields, ?AdvancedNameConverterInterface $advancedNameConverter = null): void { $this->resourceClassResolverProphecy->isResourceClass($resourceClass)->willReturn(true); - $this->resourceClassResolverProphecy->isResourceClass('nestedResourceClass')->willReturn(true); - $this->resourceClassResolverProphecy->isResourceClass('nestedResourceNoQueryClass')->willReturn(true); $this->resourceClassResolverProphecy->isResourceClass(Argument::type('string'))->willReturn(false); $this->propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection(array_keys($properties))); foreach ($properties as $propertyName => $propertyMetadata) { @@ -493,33 +505,20 @@ public function testGetResourceObjectTypeFields(string $resourceClass, Operation $this->typeConverterProphecy->convertType(new Type(Type::BUILTIN_TYPE_NULL), Argument::type('bool'), Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), '', $resourceClass, $propertyName, $depth + 1)->willReturn(null); $this->typeConverterProphecy->convertType(new Type(Type::BUILTIN_TYPE_CALLABLE), Argument::type('bool'), Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), '', $resourceClass, $propertyName, $depth + 1)->willReturn('NotRegisteredType'); $this->typeConverterProphecy->convertType(Argument::type(Type::class), Argument::type('bool'), Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), '', $resourceClass, $propertyName, $depth + 1)->willReturn(GraphQLType::string()); - $this->typeConverterProphecy->convertType(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)), Argument::type('bool'), Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), '', $resourceClass, $propertyName, $depth + 1)->willReturn(GraphQLType::nonNull(GraphQLType::listOf(GraphQLType::nonNull(GraphQLType::string())))); - if ('propertyObject' === $propertyName) { $this->typeConverterProphecy->convertType(Argument::type(Type::class), Argument::type('bool'), Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), 'objectClass', $resourceClass, $propertyName, $depth + 1)->willReturn(new ObjectType(['name' => 'objectType'])); + $this->resourceMetadataCollectionFactoryProphecy->create('objectClass')->willReturn(new ResourceMetadataCollection($resourceClass, [(new ApiResource())->withGraphQlOperations(['item_query' => new Query()])])); $this->itemResolverFactoryProphecy->__invoke('objectClass', $resourceClass, $operation)->willReturn(static function (): void { }); } - if ('propertyNestedResource' === $propertyName) { - $nestedResourceQueryOperation = new Query(); - $this->resourceMetadataCollectionFactoryProphecy->create('nestedResourceClass')->willReturn(new ResourceMetadataCollection('nestedResourceClass', [(new ApiResource())->withGraphQlOperations(['item_query' => $nestedResourceQueryOperation])])); - $this->typeConverterProphecy->convertType(Argument::type(Type::class), Argument::type('bool'), Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), 'nestedResourceClass', $resourceClass, $propertyName, $depth + 1)->willReturn(new ObjectType(['name' => 'objectType'])); - $this->itemResolverFactoryProphecy->__invoke('nestedResourceClass', $resourceClass, $nestedResourceQueryOperation)->willReturn(static function (): void { - }); - } - if ('propertyNestedResourceNoQuery' === $propertyName) { - $this->resourceMetadataCollectionFactoryProphecy->create('nestedResourceNoQueryClass')->willReturn(new ResourceMetadataCollection('nestedResourceNoQueryClass', [(new ApiResource())->withDescription('A description.')->withGraphQlOperations([])])); - $this->dynamicResourceExtractorProphecy->addResource('nestedResourceNoQueryClass')->shouldBeCalled()->willReturn('Dynamic#nestedResourceNoQueryClass'); - $dynamicResourceQueryOperation = new Query(); - $this->resourceMetadataCollectionFactoryProphecy->create('Dynamic#nestedResourceNoQueryClass')->willReturn(new ResourceMetadataCollection('nestedResourceNoQueryClass', [(new ApiResource())->withGraphQlOperations(['item_query' => $dynamicResourceQueryOperation])])); - $this->typeConverterProphecy->convertType(Argument::type(Type::class), Argument::type('bool'), Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), 'nestedResourceNoQueryClass', $resourceClass, $propertyName, $depth + 1)->willReturn(new ObjectType(['name' => 'objectType'])); - $this->itemResolverFactoryProphecy->__invoke('nestedResourceNoQueryClass', $resourceClass, $dynamicResourceQueryOperation->withDescription('A description.'))->willReturn(static function (): void { - }); - } + $this->typeConverterProphecy->convertType(Argument::type(Type::class), true, Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), 'anotherResourceClass', $propertyName, $depth + 1)->willReturn(GraphQLType::string()); + $this->typeConverterProphecy->convertType(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)), Argument::type('bool'), Argument::that(static fn (Operation $arg): bool => $arg->getName() === $operation->getName()), '', $resourceClass, $propertyName, $depth + 1)->willReturn(GraphQLType::nonNull(GraphQLType::listOf(GraphQLType::nonNull(GraphQLType::string())))); } $this->typesContainerProphecy->has('NotRegisteredType')->willReturn(false); $this->typesContainerProphecy->all()->willReturn([]); $this->typeBuilderProphecy->isCollection(Argument::type(Type::class))->willReturn(false); + $this->resourceMetadataCollectionFactoryProphecy->create('resourceClass')->willReturn(new ResourceMetadataCollection($resourceClass, [(new ApiResource())->withGraphQlOperations([$operation->getName() => $operation])])); + $this->resourceMetadataCollectionFactoryProphecy->create('anotherResourceClass')->willReturn(new ResourceMetadataCollection($resourceClass, [(new ApiResource())->withGraphQlOperations(['item_query' => new Query()])])); $fieldsBuilder = $this->fieldsBuilder; if ($advancedNameConverter) { @@ -536,7 +535,7 @@ public function resourceObjectTypeFieldsProvider(): array $advancedNameConverter->normalize('field', 'resourceClass')->willReturn('normalizedField'); return [ - 'query' => ['resourceClass', (new Query())->withClass('resourceClass'), + 'query' => ['resourceClass', new Query(), [ 'property' => new ApiProperty(), 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withReadable(true)->withWritable(false), @@ -564,7 +563,7 @@ public function resourceObjectTypeFieldsProvider(): array ], ], ], - 'query with advanced name converter' => ['resourceClass', (new Query())->withClass('resourceClass'), + 'query with advanced name converter' => ['resourceClass', new Query(), [ 'field' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_STRING)])->withReadable(true)->withWritable(false), ], @@ -583,7 +582,7 @@ public function resourceObjectTypeFieldsProvider(): array ], $advancedNameConverter->reveal(), ], - 'query input' => ['resourceClass', (new Query())->withClass('resourceClass'), + 'query input' => ['resourceClass', new Query(), [ 'property' => new ApiProperty(), 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withReadable(false)->withWritable(false), @@ -602,7 +601,7 @@ public function resourceObjectTypeFieldsProvider(): array ], ], ], - 'query with simple non-null string array property' => ['resourceClass', (new Query())->withClass('resourceClass'), + 'query with simple non-null string array property' => ['resourceClass', new Query(), [ 'property' => (new ApiProperty())->withBuiltinTypes([ new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)), @@ -622,40 +621,12 @@ public function resourceObjectTypeFieldsProvider(): array ], ], ], - 'query with nested resources' => ['resourceClass', (new Query())->withClass('resourceClass'), - [ - 'propertyNestedResource' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'nestedResourceClass')])->withReadable(true)->withWritable(true), - 'propertyNestedResourceNoQuery' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'nestedResourceNoQueryClass')])->withReadable(true)->withWritable(true), - ], - false, 0, null, - [ - 'id' => [ - 'type' => GraphQLType::nonNull(GraphQLType::id()), - ], - 'propertyNestedResource' => [ - 'type' => GraphQLType::nonNull(new ObjectType(['name' => 'objectType'])), - 'description' => null, - 'args' => [], - 'resolve' => static function (): void { - }, - 'deprecationReason' => null, - ], - 'propertyNestedResourceNoQuery' => [ - 'type' => GraphQLType::nonNull(new ObjectType(['name' => 'objectType'])), - 'description' => null, - 'args' => [], - 'resolve' => static function (): void { - }, - 'deprecationReason' => null, - ], - ], - ], - 'mutation non input' => ['resourceClass', (new Mutation())->withClass('resourceClass')->withName('mutation'), + 'mutation non input' => ['resourceClass', (new Mutation())->withName('mutation'), [ 'property' => new ApiProperty(), 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withReadable(false)->withWritable(true), 'propertyReadable' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withReadable(true)->withWritable(true), - 'propertyObject' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'objectClass')])->withReadable(true)->withWritable(true), + 'propertyObject' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL, false, 'objectClass')])->withReadable(true)->withWritable(true), ], false, 0, null, [ @@ -679,7 +650,7 @@ public function resourceObjectTypeFieldsProvider(): array ], ], ], - 'mutation input' => ['resourceClass', (new Mutation())->withClass('resourceClass')->withName('mutation'), + 'mutation input' => ['resourceClass', (new Mutation())->withName('mutation'), [ 'property' => new ApiProperty(), 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withDescription('propertyBool description')->withReadable(false)->withWritable(true)->withDeprecationReason('not useful'), @@ -715,7 +686,7 @@ public function resourceObjectTypeFieldsProvider(): array 'clientMutationId' => GraphQLType::string(), ], ], - 'mutation nested input' => ['resourceClass', (new Mutation())->withClass('resourceClass')->withName('mutation'), + 'mutation nested input' => ['resourceClass', (new Mutation())->withName('mutation'), [ 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withReadable(false)->withWritable(true), ], @@ -734,7 +705,7 @@ public function resourceObjectTypeFieldsProvider(): array 'clientMutationId' => GraphQLType::string(), ], ], - 'delete mutation input' => ['resourceClass', (new Mutation())->withClass('resourceClass')->withName('delete'), + 'delete mutation input' => ['resourceClass', (new Mutation())->withName('delete'), [ 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withReadable(false)->withWritable(true), ], @@ -746,7 +717,7 @@ public function resourceObjectTypeFieldsProvider(): array 'clientMutationId' => GraphQLType::string(), ], ], - 'create mutation input' => ['resourceClass', (new Mutation())->withClass('resourceClass')->withName('create'), + 'create mutation input' => ['resourceClass', (new Mutation())->withName('create'), [ 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withReadable(false)->withWritable(true), ], @@ -762,7 +733,7 @@ public function resourceObjectTypeFieldsProvider(): array 'clientMutationId' => GraphQLType::string(), ], ], - 'update mutation input' => ['resourceClass', (new Mutation())->withClass('resourceClass')->withName('update'), + 'update mutation input' => ['resourceClass', (new Mutation())->withName('update'), [ 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withReadable(false)->withWritable(true), ], @@ -781,7 +752,7 @@ public function resourceObjectTypeFieldsProvider(): array 'clientMutationId' => GraphQLType::string(), ], ], - 'subscription non input' => ['resourceClass', (new Subscription())->withClass('resourceClass'), + 'subscription non input' => ['resourceClass', new Subscription(), [ 'property' => new ApiProperty(), 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withReadable(false)->withWritable(true), @@ -801,7 +772,7 @@ public function resourceObjectTypeFieldsProvider(): array ], ], ], - 'subscription input' => ['resourceClass', (new Subscription())->withClass('resourceClass'), + 'subscription input' => ['resourceClass', new Subscription(), [ 'property' => new ApiProperty(), 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withDescription('propertyBool description')->withReadable(false)->withWritable(true)->withDeprecationReason('not useful'), @@ -816,13 +787,13 @@ public function resourceObjectTypeFieldsProvider(): array 'clientSubscriptionId' => GraphQLType::string(), ], ], - 'null io metadata non input' => ['resourceClass', (new Query())->withClass('resourceClass'), + 'null io metadata non input' => ['resourceClass', new Query(), [ 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withReadable(false)->withWritable(true), ], false, 0, ['class' => null], [], ], - 'null io metadata input' => ['resourceClass', (new Query())->withClass('resourceClass'), + 'null io metadata input' => ['resourceClass', new Query(), [ 'propertyBool' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_BOOL)])->withReadable(false)->withWritable(true), ], @@ -831,7 +802,7 @@ public function resourceObjectTypeFieldsProvider(): array 'clientMutationId' => GraphQLType::string(), ], ], - 'invalid types' => ['resourceClass', (new Query())->withClass('resourceClass'), + 'invalid types' => ['resourceClass', new Query(), [ 'propertyInvalidType' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_NULL)])->withReadable(true)->withWritable(false), 'propertyNotRegisteredType' => (new ApiProperty())->withBuiltinTypes([new Type(Type::BUILTIN_TYPE_CALLABLE)])->withReadable(true)->withWritable(false), diff --git a/tests/GraphQl/Type/TypeBuilderTest.php b/tests/GraphQl/Type/TypeBuilderTest.php index 40712d7a05d..66b0e7cd855 100644 --- a/tests/GraphQl/Type/TypeBuilderTest.php +++ b/tests/GraphQl/Type/TypeBuilderTest.php @@ -483,7 +483,7 @@ public function testCursorBasedGetResourcePaginatedCollectionType(): void $this->typesContainerProphecy->set('StringPageInfo', Argument::type(ObjectType::class))->shouldBeCalled(); /** @var ObjectType $resourcePaginatedCollectionType */ - $resourcePaginatedCollectionType = $this->typeBuilder->getResourcePaginatedCollectionType(GraphQLType::string(), $operation); + $resourcePaginatedCollectionType = $this->typeBuilder->getResourcePaginatedCollectionType(GraphQLType::string(), 'StringResourceClass', $operation); $this->assertSame('StringCursorConnection', $resourcePaginatedCollectionType->name); $this->assertSame('Cursor connection for String.', $resourcePaginatedCollectionType->description); @@ -538,7 +538,7 @@ public function testPageBasedGetResourcePaginatedCollectionType(): void $this->typesContainerProphecy->set('StringPaginationInfo', Argument::type(ObjectType::class))->shouldBeCalled(); /** @var ObjectType $resourcePaginatedCollectionType */ - $resourcePaginatedCollectionType = $this->typeBuilder->getResourcePaginatedCollectionType(GraphQLType::string(), $operation); + $resourcePaginatedCollectionType = $this->typeBuilder->getResourcePaginatedCollectionType(GraphQLType::string(), 'StringResourceClass', $operation); $this->assertSame('StringPageConnection', $resourcePaginatedCollectionType->name); $this->assertSame('Page connection for String.', $resourcePaginatedCollectionType->description); diff --git a/tests/Metadata/Extractor/DynamicResourceExtractorTest.php b/tests/Metadata/Extractor/DynamicResourceExtractorTest.php deleted file mode 100644 index 088318d6743..00000000000 --- a/tests/Metadata/Extractor/DynamicResourceExtractorTest.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace ApiPlatform\Tests\Metadata\Extractor; - -use ApiPlatform\Metadata\Extractor\DynamicResourceExtractor; -use ApiPlatform\Metadata\Resource\ResourceMetadataCollection; -use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy; -use PHPUnit\Framework\TestCase; - -final class DynamicResourceExtractorTest extends TestCase -{ - public function testAddResource(): void - { - $dynamicResourceExtractor = new DynamicResourceExtractor(); - - $dynamicResourceName = $dynamicResourceExtractor->addResource(Dummy::class, ['description' => 'A description.']); - - self::assertSame(ResourceMetadataCollection::DYNAMIC_RESOURCE_CLASS_PREFIX.Dummy::class, $dynamicResourceName); - self::assertSame([ - $dynamicResourceName => [[ - 'class' => Dummy::class, - 'description' => 'A description.', - ]], - ], $dynamicResourceExtractor->getResources()); - } -} diff --git a/tests/Metadata/Extractor/ResourceMetadataCompatibilityTest.php b/tests/Metadata/Extractor/ResourceMetadataCompatibilityTest.php index 3c59cc9c12c..1cd97c28814 100644 --- a/tests/Metadata/Extractor/ResourceMetadataCompatibilityTest.php +++ b/tests/Metadata/Extractor/ResourceMetadataCompatibilityTest.php @@ -20,13 +20,10 @@ use ApiPlatform\Metadata\Extractor\YamlResourceExtractor; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; -use ApiPlatform\Metadata\GraphQl\DeleteMutation; use ApiPlatform\Metadata\GraphQl\Mutation; use ApiPlatform\Metadata\GraphQl\Query; -use ApiPlatform\Metadata\GraphQl\QueryCollection; use ApiPlatform\Metadata\GraphQl\Subscription; use ApiPlatform\Metadata\HttpOperation; -use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Operations; use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; @@ -456,16 +453,7 @@ private function buildApiResources(): array $operations[$operationName] = $this->getOperationWithDefaults($resource, $operation)->withName($operationName); } - $resource = $resource->withOperations(new Operations($operations)); - - // Build default GraphQL operations - $graphQlOperations = []; - foreach ([new QueryCollection(), new Query(), (new Mutation())->withName('update'), (new DeleteMutation())->withName('delete'), (new Mutation())->withName('create')] as $graphQlOperation) { - $description = $graphQlOperation instanceof Mutation ? ucfirst("{$graphQlOperation->getName()}s a {$resource->getShortName()}.") : null; - $graphQlOperations[$graphQlOperation->getName()] = $this->getOperationWithDefaults($resource, $graphQlOperation)->withName($graphQlOperation->getName())->withDescription($description); - } - - $resources[] = $resource->withGraphQlOperations($graphQlOperations); + $resources[] = $resource->withOperations(new Operations($operations)); continue; } @@ -603,7 +591,7 @@ private function withGraphQlOperations(array $values, ?array $fixtures): array return $operations; } - private function getOperationWithDefaults(ApiResource $resource, Operation $operation): Operation + private function getOperationWithDefaults(ApiResource $resource, HttpOperation $operation): HttpOperation { foreach (get_class_methods($resource) as $methodName) { if (!str_starts_with($methodName, 'get')) { diff --git a/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php index aa0b74b1471..a7b78bd9c8a 100644 --- a/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactoryTest.php @@ -209,14 +209,4 @@ public function testExtraProperties(): void $this->assertEquals($extraPropertiesResource[0]->getExtraProperties(), ['foo' => 'bar']); $this->assertEquals($extraPropertiesResource->getOperation('_api_ExtraPropertiesResource_get')->getExtraProperties(), ['foo' => 'bar']); } - - public function testDynamic(): void - { - $attributeResourceMetadataCollectionFactory = new AttributesResourceMetadataCollectionFactory(); - - self::assertEquals( - new ResourceMetadataCollection(ResourceMetadataCollection::DYNAMIC_RESOURCE_CLASS_PREFIX.AttributeResource::class), - $attributeResourceMetadataCollectionFactory->create(ResourceMetadataCollection::DYNAMIC_RESOURCE_CLASS_PREFIX.AttributeResource::class) - ); - } } diff --git a/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php b/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php index c297b0bbd05..dd92aa2fe80 100644 --- a/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php +++ b/tests/Metadata/Resource/Factory/PhpDocResourceMetadataCollectionFactoryTest.php @@ -58,19 +58,4 @@ public function testExtractDescription(): void $factory = new PhpDocResourceMetadataCollectionFactory($decorated); $this->assertSame('My dummy entity.', $factory->create(DummyEntity::class)[0]->getDescription()); } - - public function testDynamic(): void - { - $resourceCollection = new ResourceMetadataCollection(ResourceMetadataCollection::DYNAMIC_RESOURCE_CLASS_PREFIX.DummyEntity::class, [new ApiResource()]); - $decoratedProphecy = $this->prophesize(ResourceMetadataCollectionFactoryInterface::class); - $decoratedProphecy->create(ResourceMetadataCollection::DYNAMIC_RESOURCE_CLASS_PREFIX.DummyEntity::class)->willReturn($resourceCollection)->shouldBeCalled(); - $decorated = $decoratedProphecy->reveal(); - - $factory = new PhpDocResourceMetadataCollectionFactory($decorated); - - self::assertSame( - $resourceCollection, - $factory->create(ResourceMetadataCollection::DYNAMIC_RESOURCE_CLASS_PREFIX.DummyEntity::class) - ); - } } diff --git a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index dc997b0bee9..006ad7e788d 100644 --- a/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -367,8 +367,6 @@ public function testMetadataConfiguration(): void // metadata/resource.xml 'api_platform.metadata.resource.metadata_collection_factory.attributes', 'api_platform.metadata.resource.metadata_collection_factory.xml', - 'api_platform.metadata.resource_extractor.dynamic', - 'api_platform.metadata.resource.metadata_collection_factory.dynamic', 'api_platform.metadata.resource.metadata_collection_factory.uri_template', 'api_platform.metadata.resource.metadata_collection_factory.link', 'api_platform.metadata.resource.metadata_collection_factory.operation_name',