diff --git a/docs/annotations/annotations-reference.md b/docs/annotations/annotations-reference.md index fc579537f..6befa36ce 100644 --- a/docs/annotations/annotations-reference.md +++ b/docs/annotations/annotations-reference.md @@ -384,6 +384,10 @@ This annotation applies on methods for classes tagged with the `@Provider` annot The resulting field is added to the root Mutation type (defined in configuration at key `overblog_graphql.definitions.schema.mutation`). The class exposing the mutation(s) must be declared as a [service](https://symfony.com/doc/current/service_container.html). +Optional attributes: + +- **targetType** : The GraphQL type to attach the field to (by default, it'll be the root Mutation type). + Example: This will add an `updateUserEmail` mutation, with as resolver `@=service('App\Graphql\MutationProvider').updateUserEmail(...)`. diff --git a/src/Annotation/Mutation.php b/src/Annotation/Mutation.php index f9094355d..7e1bedeed 100644 --- a/src/Annotation/Mutation.php +++ b/src/Annotation/Mutation.php @@ -12,4 +12,10 @@ */ final class Mutation extends Field { + /** + * The target type to attach this mutation to. + * + * @var string + */ + public $targetType; } diff --git a/src/Config/Parser/AnnotationParser.php b/src/Config/Parser/AnnotationParser.php index b63c0b794..503987572 100644 --- a/src/Config/Parser/AnnotationParser.php +++ b/src/Config/Parser/AnnotationParser.php @@ -289,8 +289,22 @@ private static function typeAnnotationToGQLConfiguration( $isRootMutation = ($rootMutationType && $gqlName === $rootMutationType); $currentValue = ($isRootQuery || $isRootMutation) ? \sprintf("service('%s')", self::formatNamespaceForExpression($reflectionEntity->getName())) : 'value'; + $queryType = $isRootMutation ? 'Mutation' : 'Query'; + + if (isset($configs['definitions']['schema'])) { + $mutationTypes = []; + + foreach ($configs['definitions']['schema'] as $key => $value) { + if (isset($configs['definitions']['schema'][$key]['mutation'])) { + $mutationTypes[] = $configs['definitions']['schema'][$key]['mutation']; + } + } + + $queryType = \in_array($gqlName, $mutationTypes) ? 'Mutation' : 'Query'; + } + $gqlConfiguration = self::graphQLTypeConfigFromAnnotation($classAnnotation, $classAnnotations, $properties, $methods, $reflectionEntity->getNamespaceName(), $currentValue); - $providerFields = self::getGraphQLFieldsFromProviders($reflectionEntity->getNamespaceName(), $isRootMutation ? 'Mutation' : 'Query', $gqlName, ($isRootQuery || $isRootMutation)); + $providerFields = self::getGraphQLFieldsFromProviders($reflectionEntity->getNamespaceName(), $queryType, $gqlName, ($isRootQuery || $isRootMutation)); $gqlConfiguration['config']['fields'] = $providerFields + $gqlConfiguration['config']['fields']; if ($classAnnotation instanceof GQL\Relay\Edge) { @@ -673,7 +687,7 @@ private static function getGraphQLFieldsFromProviders(string $namespace, string continue; } - $annotationTarget = 'Query' === $annotationName ? $annotation->targetType : null; + $annotationTarget = \in_array($annotationName, ['Query', 'Mutation']) ? $annotation->targetType : null; if (!$annotationTarget && $isRoot) { $annotationTarget = $targetType; } diff --git a/tests/Config/Parser/AnnotationParserTest.php b/tests/Config/Parser/AnnotationParserTest.php index 0f396b5f2..ea21eeee3 100644 --- a/tests/Config/Parser/AnnotationParserTest.php +++ b/tests/Config/Parser/AnnotationParserTest.php @@ -14,6 +14,7 @@ class AnnotationParserTest extends TestCase 'definitions' => [ 'schema' => [ 'default' => ['query' => 'RootQuery', 'mutation' => 'RootMutation'], + 'alternative' => ['query' => 'AlternativeQuery', 'mutation' => 'AlternativeMutation'], ], ], 'doctrine' => [ @@ -229,6 +230,30 @@ public function testProviders(): void ], ], ]); + + $this->expect('AlternativeQuery', 'object', [ + 'fields' => [ + 'planet_sortPlanets' => [ + 'type' => '[Planet]', + 'args' => ['direction' => ['type' => 'String!']], + 'resolve' => "@=call(service('Overblog\\\\GraphQLBundle\\\\Tests\\\\Config\\\\Parser\\\\fixtures\\\\annotations\\\\Repository\\\\PlanetRepository').sortPlanets, arguments({direction: \"String!\"}, args))", + 'access' => '@=default_access', + 'public' => '@=default_public', + ], + ], + ]); + + $this->expect('AlternativeMutation', 'object', [ + 'fields' => [ + 'planet_destroyPlanet' => [ + 'type' => 'Planet', + 'args' => ['planetInput' => ['type' => 'PlanetInput!']], + 'resolve' => "@=call(service('Overblog\\\\GraphQLBundle\\\\Tests\\\\Config\\\\Parser\\\\fixtures\\\\annotations\\\\Repository\\\\PlanetRepository').destroyPlanet, arguments({planetInput: \"PlanetInput!\"}, args))", + 'access' => '@=default_access', + 'public' => '@=override_public', + ], + ], + ]); } public function testFullqualifiedName(): void diff --git a/tests/Config/Parser/fixtures/annotations/Repository/PlanetRepository.php b/tests/Config/Parser/fixtures/annotations/Repository/PlanetRepository.php index 96f669110..9dddc208a 100644 --- a/tests/Config/Parser/fixtures/annotations/Repository/PlanetRepository.php +++ b/tests/Config/Parser/fixtures/annotations/Repository/PlanetRepository.php @@ -23,6 +23,16 @@ public function searchPlanet(string $keyword) return []; } + /** + * @GQL\Query(type="[Planet]", targetType="AlternativeQuery", args={ + * @GQL\Arg(type="String!", name="direction") + * }) + */ + public function sortPlanets(string $direction) + { + return []; + } + /** * @GQL\Mutation(type="Planet", args={ * @GQL\Arg(type="PlanetInput!", name="planetInput") @@ -34,6 +44,17 @@ public function createPlanet(array $planetInput) return []; } + /** + * @GQL\Mutation(type="Planet", targetType="AlternativeMutation", args={ + * @GQL\Arg(type="PlanetInput!", name="planetInput") + * }) + * @GQL\IsPublic("override_public") + */ + public function destroyPlanet(array $planetInput) + { + return []; + } + /** * @GQL\Query(type="[Planet]", targetType="Droid", name="allowedPlanets") * @GQL\Access("override_access") diff --git a/tests/Config/Parser/fixtures/annotations/Type/AlternativeMutation.php b/tests/Config/Parser/fixtures/annotations/Type/AlternativeMutation.php new file mode 100644 index 000000000..8a0937e64 --- /dev/null +++ b/tests/Config/Parser/fixtures/annotations/Type/AlternativeMutation.php @@ -0,0 +1,14 @@ +