From 87de08af8896cc3219166730e2d7a648c73f6d33 Mon Sep 17 00:00:00 2001 From: Benedikt Franke Date: Fri, 26 May 2023 11:10:32 +0200 Subject: [PATCH] Allow default model class resolution for `union` types --- CHANGELOG.md | 6 +++ src/Schema/AST/ASTHelper.php | 5 +- src/Schema/Directives/BaseDirective.php | 7 +-- .../Schema/Directives/BaseDirectiveTest.php | 52 ++++++++++++++++++- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ea5804d78..f156e4e210 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ You can find and compare releases at the [GitHub release page](https://github.co ## Unreleased +## v6.10.0 + +### Added + +- Allow default model class resolution for `union` types + ## v6.9.2 ### Fixed diff --git a/src/Schema/AST/ASTHelper.php b/src/Schema/AST/ASTHelper.php index b071ed5b81..e1bd4c8fa3 100644 --- a/src/Schema/AST/ASTHelper.php +++ b/src/Schema/AST/ASTHelper.php @@ -355,7 +355,10 @@ public static function modelName(Node $definitionNode): ?string $definitionNode = static::underlyingType($definitionNode); } - if ($definitionNode instanceof ObjectTypeDefinitionNode || $definitionNode instanceof InterfaceTypeDefinitionNode) { + if ($definitionNode instanceof ObjectTypeDefinitionNode + || $definitionNode instanceof InterfaceTypeDefinitionNode + || $definitionNode instanceof UnionTypeDefinitionNode + ) { return ModelDirective::modelClass($definitionNode) ?? $definitionNode->name->value; } diff --git a/src/Schema/Directives/BaseDirective.php b/src/Schema/Directives/BaseDirective.php index 22605726b1..8a59cbd124 100644 --- a/src/Schema/Directives/BaseDirective.php +++ b/src/Schema/Directives/BaseDirective.php @@ -146,11 +146,8 @@ protected function directiveArgValue(string $name, mixed $default = null): mixed */ protected function getModelClass(string $argumentName = 'model'): string { - $model = $this->directiveArgValue($argumentName, ASTHelper::modelName($this->definitionNode)); - - if (! $model) { - throw new DefinitionException("Could not determine a model name for the '@{$this->name()}' directive on '{$this->nodeName()}."); - } + $model = $this->directiveArgValue($argumentName, ASTHelper::modelName($this->definitionNode)) + ?? throw new DefinitionException("Could not determine a model name for the '@{$this->name()}' directive on '{$this->nodeName()}'."); return $this->namespaceModelClass($model); } diff --git a/tests/Unit/Schema/Directives/BaseDirectiveTest.php b/tests/Unit/Schema/Directives/BaseDirectiveTest.php index 4f515e9c4c..b28a7909e4 100644 --- a/tests/Unit/Schema/Directives/BaseDirectiveTest.php +++ b/tests/Unit/Schema/Directives/BaseDirectiveTest.php @@ -39,7 +39,7 @@ public function testGetsModelClassFromDirective(): void ); } - public function testDefaultsToFieldTypeForTheModelClass(): void + public function testDefaultsToFieldTypeForTheModelClassIfObject(): void { $this->schema .= /** @lang GraphQL */ ' type User { @@ -55,6 +55,56 @@ public function testDefaultsToFieldTypeForTheModelClass(): void ); } + public function testDefaultsToFieldTypeForTheModelClassIfInterface(): void + { + $this->schema .= /** @lang GraphQL */ ' + interface User { + id: ID + } + '; + + $directive = $this->constructFieldDirective('foo: User @dummy'); + + $this->assertSame( + User::class, + $directive->getModelClass(), + ); + } + + public function testDefaultsToFieldTypeForTheModelClassIfUnion(): void + { + $this->schema .= /** @lang GraphQL */ ' + union User = Admin | Member + + type Admin { + id: ID + } + + type Member { + id: ID + } + '; + + $directive = $this->constructFieldDirective('foo: User @dummy'); + + $this->assertSame( + User::class, + $directive->getModelClass(), + ); + } + + public function testDoesntDefaultToFieldTypeForTheModelClassIfScalar(): void + { + $this->schema .= /** @lang GraphQL */ ' + scalar User + '; + + $directive = $this->constructFieldDirective('foo: User @dummy'); + + $this->expectException(DefinitionException::class); + $directive->getModelClass(); + } + public function testThrowsIfTheClassIsNotInTheSchema(): void { $directive = $this->constructFieldDirective('foo: UnknownType @dummy');