From 66840deccfc5e6ef393496c1bed1ff057367a279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Thu, 26 Dec 2019 15:14:16 +0100 Subject: [PATCH 1/3] Adding test to showcase poor error message --- .../Controllers/InAndOutController.php | 21 ++++++++++ .../Types/InAndOut.php | 40 +++++++++++++++++++ tests/Integration/EndToEndTest.php | 13 +++++- 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 tests/Fixtures/InputOutputNameConflict/Controllers/InAndOutController.php create mode 100644 tests/Fixtures/InputOutputNameConflict/Types/InAndOut.php diff --git a/tests/Fixtures/InputOutputNameConflict/Controllers/InAndOutController.php b/tests/Fixtures/InputOutputNameConflict/Controllers/InAndOutController.php new file mode 100644 index 0000000000..77740b61e9 --- /dev/null +++ b/tests/Fixtures/InputOutputNameConflict/Controllers/InAndOutController.php @@ -0,0 +1,21 @@ +value = $value; + } + + /** + * @Field() + */ + public function getValue(): string + { + return $this->value; + } + + /** + * @Factory(name="InAndOut") + */ + public static function create(string $value): self + { + return new self($value); + } +} diff --git a/tests/Integration/EndToEndTest.php b/tests/Integration/EndToEndTest.php index 94654f7cc2..ecac6d34a1 100644 --- a/tests/Integration/EndToEndTest.php +++ b/tests/Integration/EndToEndTest.php @@ -52,6 +52,7 @@ use TheCodingMachine\GraphQLite\Containers\EmptyContainer; use TheCodingMachine\GraphQLite\Reflection\CachedDocBlockFactory; use TheCodingMachine\GraphQLite\Schema; +use TheCodingMachine\GraphQLite\SchemaFactory; use TheCodingMachine\GraphQLite\Security\AuthenticationServiceInterface; use TheCodingMachine\GraphQLite\Security\AuthorizationServiceInterface; use TheCodingMachine\GraphQLite\Security\SecurityExpressionLanguageProvider; @@ -451,7 +452,7 @@ public function testEndToEndInputType() { name: "bar" } - ] + ] } ) { name, @@ -1364,4 +1365,14 @@ public function getUser(): ?object $this->assertSame(42, $result->toArray(Debug::RETHROW_UNSAFE_EXCEPTIONS)['data']['injectedUser']); } + + public function testInputOutputNameConflict(): void + { + $schemaFactory = new SchemaFactory(new Psr16Cache(new ArrayAdapter()), new BasicAutoWiringContainer(new EmptyContainer())); + $schemaFactory->addControllerNamespace('TheCodingMachine\\GraphQLite\\Fixtures\\InputOutputNameConflict\\Controllers'); + $schemaFactory->addTypeNamespace('TheCodingMachine\\GraphQLite\\Fixtures\\InputOutputNameConflict\\Types'); + + $schema = $schemaFactory->createSchema(); + $schema->validate(); + } } From 08577d0324224e64a3d901f84a084d8b431179c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Thu, 26 Dec 2019 15:38:00 +0100 Subject: [PATCH 2/3] Improving error message if an output and an input type name are in conflict --- src/Mappers/CannotMapTypeException.php | 2 +- src/TypeRegistry.php | 18 +++++++++--------- .../Integration/Types/ContactFactory.php | 4 ++-- tests/Integration/EndToEndTest.php | 5 +++++ 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/Mappers/CannotMapTypeException.php b/src/Mappers/CannotMapTypeException.php index 5dd92097ac..680eb476e7 100644 --- a/src/Mappers/CannotMapTypeException.php +++ b/src/Mappers/CannotMapTypeException.php @@ -83,7 +83,7 @@ public static function mustBeOutputType(string $subTypeName): self public static function mustBeInputType(string $subTypeName): self { - return new self('type "' . $subTypeName . '" must be an input type.'); + return new self('type "' . $subTypeName . '" must be an input type (if you declared an input type with the name "' . $subTypeName . '", make sure that there are no output type with the same name as this is forbidden by the GraphQL spec).'); } /** diff --git a/src/TypeRegistry.php b/src/TypeRegistry.php index f9ce17fe91..21da7734b2 100644 --- a/src/TypeRegistry.php +++ b/src/TypeRegistry.php @@ -22,7 +22,7 @@ class TypeRegistry { /** @var array */ - private $outputTypes = []; + private $types = []; /** * Registers a type. @@ -33,10 +33,10 @@ class TypeRegistry */ public function registerType(NamedType $type): void { - if (isset($this->outputTypes[$type->name])) { + if (isset($this->types[$type->name])) { throw new GraphQLRuntimeException('Type "' . $type->name . '" is already registered'); } - $this->outputTypes[$type->name] = $type; + $this->types[$type->name] = $type; } /** @@ -50,17 +50,17 @@ public function registerType(NamedType $type): void */ public function getOrRegisterType(NamedType $type): NamedType { - if (isset($this->outputTypes[$type->name])) { - return $this->outputTypes[$type->name]; + if (isset($this->types[$type->name])) { + return $this->types[$type->name]; } - $this->outputTypes[$type->name] = $type; + $this->types[$type->name] = $type; return $type; } public function hasType(string $typeName): bool { - return isset($this->outputTypes[$typeName]); + return isset($this->types[$typeName]); } /** @@ -68,11 +68,11 @@ public function hasType(string $typeName): bool */ public function getType(string $typeName): NamedType { - if (! isset($this->outputTypes[$typeName])) { + if (! isset($this->types[$typeName])) { throw new GraphQLRuntimeException('Could not find type "' . $typeName . '" in registry'); } - return $this->outputTypes[$typeName]; + return $this->types[$typeName]; } public function getMutableObjectType(string $typeName): MutableObjectType diff --git a/tests/Fixtures/Integration/Types/ContactFactory.php b/tests/Fixtures/Integration/Types/ContactFactory.php index 9e1398d678..5f81fc602a 100644 --- a/tests/Fixtures/Integration/Types/ContactFactory.php +++ b/tests/Fixtures/Integration/Types/ContactFactory.php @@ -15,7 +15,7 @@ class ContactFactory { /** * @Factory() - * @UseInputType(for="$relations", inputType="[ContactRefInput!]!") + * @UseInputType(for="$relations", inputType="[ContactRef!]!") * @param string $name * @param Contact|null $manager * @param Contact[] $relations @@ -34,7 +34,7 @@ public function createContact(string $name, DateTimeInterface $birthDate, ?Uploa } /** - * @Factory(name="ContactRefInput", default=false) + * @Factory(name="ContactRef", default=false) * @return Contact */ public function getContact(string $name): Contact diff --git a/tests/Integration/EndToEndTest.php b/tests/Integration/EndToEndTest.php index ecac6d34a1..5976801098 100644 --- a/tests/Integration/EndToEndTest.php +++ b/tests/Integration/EndToEndTest.php @@ -21,6 +21,7 @@ use TheCodingMachine\GraphQLite\GraphQLRuntimeException; use TheCodingMachine\GraphQLite\InputTypeGenerator; use TheCodingMachine\GraphQLite\InputTypeUtils; +use TheCodingMachine\GraphQLite\Mappers\CannotMapTypeException; use TheCodingMachine\GraphQLite\Mappers\CompositeTypeMapper; use TheCodingMachine\GraphQLite\Mappers\GlobTypeMapper; use TheCodingMachine\GraphQLite\Mappers\Parameters\ContainerParameterHandler; @@ -1373,6 +1374,10 @@ public function testInputOutputNameConflict(): void $schemaFactory->addTypeNamespace('TheCodingMachine\\GraphQLite\\Fixtures\\InputOutputNameConflict\\Types'); $schema = $schemaFactory->createSchema(); + + $this->expectException(CannotMapTypeException::class); + $this->expectExceptionMessage('For parameter $inAndOut, in TheCodingMachine\\GraphQLite\\Fixtures\\InputOutputNameConflict\\Controllers\\InAndOutController::testInAndOut, type "InAndOut" must be an input type (if you declared an input type with the name "InAndOut", make sure that there are no output type with the same name as this is forbidden by the GraphQL spec).'); + $schema->validate(); } } From 4d92fc3a41f82506b263d203dd5d9a36693d8e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Thu, 26 Dec 2019 15:39:36 +0100 Subject: [PATCH 3/3] Adding @InjectUser to changelog --- docs/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ba93624b5b..3afd167284 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -18,6 +18,7 @@ New features: - Unauthorized access to fields can now generate GraphQL errors (rather that schema errors in GraphQLite v3) - Added fine-grained security using the `@Security` annotation. A field can now be [marked accessible or not depending on the context](fine-grained-security.md). For instance, you can restrict access to the field "viewsCount" of the type `BlogPost` only for post that the current user wrote. + - You can now inject the current logged user in any query / mutation / field using the `@InjectUser` annotation - Performance: - You can inject the [Webonyx query plan in a parameter from a resolver](query_plan.md) - You can use the [dataloader pattern to improve performance drastically via the "prefetchMethod" attribute](prefetch_method.md)