diff --git a/src/Mappers/Parameters/TypeHandler.php b/src/Mappers/Parameters/TypeHandler.php index 5a85b682fc..28e85f3b3a 100644 --- a/src/Mappers/Parameters/TypeHandler.php +++ b/src/Mappers/Parameters/TypeHandler.php @@ -27,6 +27,7 @@ use ReflectionParameter; use ReflectionProperty; use ReflectionType; +use ReflectionUnionType; use TheCodingMachine\GraphQLite\Annotations\HideParameter; use TheCodingMachine\GraphQLite\Annotations\ParameterAnnotations; use TheCodingMachine\GraphQLite\Annotations\UseInputType; @@ -42,6 +43,7 @@ use TheCodingMachine\GraphQLite\Types\TypeResolver; use Webmozart\Assert\Assert; +use function array_map; use function array_merge; use function array_unique; use function assert; @@ -408,17 +410,36 @@ private function appendTypes(Type $type, ?Type $docBlockType): Type */ private function reflectionTypeToPhpDocType(ReflectionType $type, ReflectionClass $reflectionClass): Type { - assert($type instanceof ReflectionNamedType); - $phpdocType = $this->phpDocumentorTypeResolver->resolve($type->getName()); - Assert::notNull($phpdocType); + assert($type instanceof ReflectionNamedType || $type instanceof ReflectionUnionType); + if ($type instanceof ReflectionNamedType) { + $phpdocType = $this->phpDocumentorTypeResolver->resolve($type->getName()); + Assert::notNull($phpdocType); - $phpdocType = $this->resolveSelf($phpdocType, $reflectionClass); + $phpdocType = $this->resolveSelf($phpdocType, $reflectionClass); - if ($type->allowsNull()) { - $phpdocType = new Nullable($phpdocType); - } + if ($type->allowsNull()) { + $phpdocType = new Nullable($phpdocType); + } - return $phpdocType; + return $phpdocType; + } + return new Compound( + array_map( + function ($namedType) use ($reflectionClass): Type { + \assert($namedType instanceof ReflectionNamedType); + $phpdocType = $this->phpDocumentorTypeResolver->resolve($namedType->getName()); + Assert::notNull($phpdocType); + + $phpdocType = $this->resolveSelf($phpdocType, $reflectionClass); + + if ($namedType->allowsNull()) { + $phpdocType = new Nullable($phpdocType); + } + return $phpdocType; + }, + $type->getTypes() + ) + ); } /** diff --git a/tests/Fixtures80/UnionOutputType.php b/tests/Fixtures80/UnionOutputType.php new file mode 100644 index 0000000000..b3d4161a70 --- /dev/null +++ b/tests/Fixtures80/UnionOutputType.php @@ -0,0 +1,15 @@ +mapReturnType($refMethod, $docBlockObj); } + /** + * @requires PHP >= 8.0 + */ + public function testMapObjectUnionWorks(): void + { + $typeMapper = new TypeHandler($this->getArgumentResolver(), $this->getRootTypeMapper(), $this->getTypeResolver()); + + $cachedDocBlockFactory = new CachedDocBlockFactory(new Psr16Cache(new ArrayAdapter())); + + $refMethod = new ReflectionMethod(UnionOutputType::class, 'objectUnion'); + $docBlockObj = $cachedDocBlockFactory->getDocBlock($refMethod); + + $gqType = $typeMapper->mapReturnType($refMethod, $docBlockObj); + $this->assertInstanceOf(NonNull::class, $gqType); + assert($gqType instanceof NonNull); + $memberType = $gqType->getOfType(); + $this->assertInstanceOf(UnionType::class, $memberType); + assert($memberType instanceof UnionType); + $unionTypes = $memberType->getTypes(); + $this->assertEquals('TestObject', $unionTypes[0]->name); + $this->assertEquals('TestObject2', $unionTypes[1]->name); + } + public function testHideParameter(): void { $typeMapper = new TypeHandler($this->getArgumentResolver(), $this->getRootTypeMapper(), $this->getTypeResolver());