-
-
Notifications
You must be signed in to change notification settings - Fork 900
fix(graphql): use right nested operation #5102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(graphql): use right nested operation #5102
Conversation
85e4479
to
ee8fc86
Compare
@@ -47,7 +45,7 @@ | |||
*/ | |||
final class FieldsBuilder implements FieldsBuilderInterface | |||
{ | |||
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) | |||
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
breaks BC layer
@@ -210,7 +210,7 @@ public function getNodeInterface(): InterfaceType | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function getResourcePaginatedCollectionType(GraphQLType $resourceType, string $resourceClass, Operation $operation): GraphQLType | |||
public function getResourcePaginatedCollectionType(GraphQLType $resourceType, Operation $operation): GraphQLType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BC layer is broken
@@ -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, string $resourceClass, Operation $operation): GraphQLType; | |||
public function getResourcePaginatedCollectionType(GraphQLType $resourceType, Operation $operation): GraphQLType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't change an interface like this right?
$dynamicResourceName = $this->getDynamicResourceName($resourceClass); | ||
|
||
$this->dynamicResources[$dynamicResourceName] = [ | ||
array_merge(['class' => $resourceClass], $config), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
array_merge is quite slow for this we could just add the class to the config right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it doesn't impact performance but we can.
* | ||
* @author Alan Poulain <[email protected]> | ||
*/ | ||
interface DynamicResourceExtractorInterface extends ResourceExtractorInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really need to add a new interface? its wanted that a ResourceExtractorInterface
doesn't have an addResource
we're using a Factory to prepare resources inside it no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need an interface since this method needs to be called from the fields builder.
public function isDynamic(): bool | ||
{ | ||
return str_starts_with($this->resourceClass, self::DYNAMIC_RESOURCE_CLASS_PREFIX); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't like this graphql-specific code here, can you explain this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not GraphQL-specific. The aim is to create metadata for a resource which doesn't exist.
@@ -86,6 +88,11 @@ 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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imo resourceClass
should be a class-string
this breaks it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure but we need a way to distinguish a dynamic resource for a normal one.
* fix: update yaml extractor test file coding standard (#5068) * fix(graphql): add clearer error message when TwigBundle is disabled but graphQL clients are enabled (#5064) * fix(metadata): add class key in payload argument resolver (#5067) * fix: add class key in payload argument resolver * add null if everything else goes wrong * fix: upgrade command remove ApiSubresource attribute (#5049) Fixes #5038 * fix(doctrine): use abitrary index instead of value (#5079) * fix: uri template should respect rfc 6570 (#5080) * fix: remove @internal annotation for Operations (#5089) See #5084 * fix(metadata): define a name on a single operation (#5090) fixes #5082 * fix(metadata): deprecate when user decorates in legacy mode (#5091) fixes #5078 * fix(graphql): use right nested operation (#5102) * Revert "fix(graphql): use right nested operation (#5102)" (#5111) This reverts commit 44337dd. * fix(graphql): always allow to query nested resources (#5112) * fix(graphql): always allow to query nested resources * review Co-authored-by: Alan Poulain <[email protected]> * chore: php-cs-fixer update * fix: only alias if exists for opcache preload Fixes api-platform/api-platform#2284 (#5110) Co-authored-by: Liviu Mirea <[email protected]> * chore: php-cs-fixer update (#5118) * chore: php-cs-fixer update * chore: php-cs-fixer update * fix(metadata): upgrade script keep operation name (#5109) origin: #5105 Co-authored-by: WilliamPeralta <[email protected]> * chore: v2.7.3 changelog * chore: v3.0.3 changelog Co-authored-by: helyakin <[email protected]> Co-authored-by: ArnoudThibaut <[email protected]> Co-authored-by: davy-beauzil <[email protected]> Co-authored-by: Baptiste Leduc <[email protected]> Co-authored-by: Xavier Laviron <[email protected]> Co-authored-by: Alan Poulain <[email protected]> Co-authored-by: Liviu Cristian Mirea-Ghiban <[email protected]> Co-authored-by: Liviu Mirea <[email protected]> Co-authored-by: WilliamPeralta <[email protected]>
See #4613 (comment).
Supersedes #4930.
Fixes api-platform/api-platform#2296.
The principal issue was mainly because the root operation was used instead of the nested resource one.
This PR also improves how GraphQL handles a nested resource when the query operation does not exist.
Instead of having a fallback on the REST operation (and an exception if it does not exist), it creates a "dynamic" resource having the default operations.
This dynamic resource is created using a new
DynamicExtractor
with anaddResource
method, which can take an optional configuration array.In the future, I think this could be useful to control how a nested resource is handled by GraphQL (for instance by using the
ApiProperty
attribute).