diff --git a/src/Type/Definition/AbstractType.php b/src/Type/Definition/AbstractType.php index c646b8805..241149bd7 100644 --- a/src/Type/Definition/AbstractType.php +++ b/src/Type/Definition/AbstractType.php @@ -20,5 +20,5 @@ interface AbstractType * * @phpstan-return ResolveTypeReturn */ - public function resolveType($objectValue, $context, ResolveInfo $info); + public function resolveType(&$objectValue, $context, ResolveInfo $info); } diff --git a/src/Type/Definition/InterfaceType.php b/src/Type/Definition/InterfaceType.php index d15342c31..997319cd4 100644 --- a/src/Type/Definition/InterfaceType.php +++ b/src/Type/Definition/InterfaceType.php @@ -67,7 +67,7 @@ public static function assertInterfaceType($type): self return $type; } - public function resolveType($objectValue, $context, ResolveInfo $info) + public function resolveType(&$objectValue, $context, ResolveInfo $info) { if (isset($this->config['resolveType'])) { return ($this->config['resolveType'])($objectValue, $context, $info); diff --git a/src/Type/Definition/UnionType.php b/src/Type/Definition/UnionType.php index c5b03ebbd..af9291de3 100644 --- a/src/Type/Definition/UnionType.php +++ b/src/Type/Definition/UnionType.php @@ -106,7 +106,7 @@ public function getTypes(): array return $this->types; } - public function resolveType($objectValue, $context, ResolveInfo $info) + public function resolveType(&$objectValue, $context, ResolveInfo $info) { if (isset($this->config['resolveType'])) { return ($this->config['resolveType'])($objectValue, $context, $info); diff --git a/tests/Executor/AbstractTest.php b/tests/Executor/AbstractTest.php index 0280cb811..a2ef8d043 100644 --- a/tests/Executor/AbstractTest.php +++ b/tests/Executor/AbstractTest.php @@ -13,6 +13,7 @@ use GraphQL\Tests\Executor\TestClasses\Cat; use GraphQL\Tests\Executor\TestClasses\Dog; use GraphQL\Tests\Executor\TestClasses\Human; +use GraphQL\Tests\Executor\TestClasses\PetEntity; use GraphQL\Type\Definition\InterfaceType; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; @@ -773,4 +774,97 @@ public function testHintsOnConflictingTypeInstancesInResolveType(): void $error->getMessage() ); } + + public function testResolveTypeAllowsModifyingObjectValue(): void + { + $PetType = new InterfaceType([ + 'name' => 'Pet', + 'resolveType' => static function (PetEntity &$objectValue): string { + if ($objectValue->type === 'dog') { + $objectValue = new Dog($objectValue->name, $objectValue->woofs); + + return 'Dog'; + } + + $objectValue = new Cat($objectValue->name, $objectValue->woofs); + + return 'Cat'; + }, + 'fields' => [ + 'name' => ['type' => Type::string()], + ], + ]); + + $DogType = new ObjectType([ + 'name' => 'Dog', + 'interfaces' => [$PetType], + 'fields' => [ + 'name' => [ + 'type' => Type::string(), + 'resolve' => fn (Dog $dog) => $dog->name, + ], + 'woofs' => [ + 'type' => Type::boolean(), + 'resolve' => fn (Dog $dog) => $dog->woofs, + ], + ], + ]); + + $CatType = new ObjectType([ + 'name' => 'Cat', + 'interfaces' => [$PetType], + 'fields' => [ + 'name' => [ + 'type' => Type::string(), + 'resolve' => fn (Cat $cat) => $cat->name, + ], + 'meows' => [ + 'type' => Type::boolean(), + 'resolve' => fn (Cat $cat) => $cat->meows, + ], + ], + ]); + + $schema = new Schema([ + 'query' => new ObjectType([ + 'name' => 'Query', + 'fields' => [ + 'pets' => [ + 'type' => Type::listOf($PetType), + 'resolve' => static fn (): array => [ + new PetEntity('dog', 'Odie', true), + new PetEntity('cat', 'Garfield', false), + ], + ], + ], + ]), + 'types' => [$CatType, $DogType], + ]); + + $query = '{ + pets { + name + ... on Dog { + woofs + } + ... on Cat { + meows + } + } + }'; + + $result = GraphQL::executeQuery($schema, $query)->toArray(); + + self::assertEquals( + [ + 'data' => [ + 'pets' => [ + ['name' => 'Odie', 'woofs' => true], + ['name' => 'Garfield', 'meows' => false], + ], + ], + ], + $result + ); + } } diff --git a/tests/Executor/TestClasses/PetEntity.php b/tests/Executor/TestClasses/PetEntity.php new file mode 100644 index 000000000..28666d1d2 --- /dev/null +++ b/tests/Executor/TestClasses/PetEntity.php @@ -0,0 +1,21 @@ +type = $type; + $this->name = $name; + $this->woofs = $woofs; + } +} diff --git a/tests/Utils/SchemaExtenderTest/SomeInterfaceClassType.php b/tests/Utils/SchemaExtenderTest/SomeInterfaceClassType.php index deba5dbbc..144a5041d 100644 --- a/tests/Utils/SchemaExtenderTest/SomeInterfaceClassType.php +++ b/tests/Utils/SchemaExtenderTest/SomeInterfaceClassType.php @@ -11,7 +11,7 @@ final class SomeInterfaceClassType extends InterfaceType { public ObjectType $concrete; - public function resolveType($objectValue, $context, ResolveInfo $info): ObjectType + public function resolveType(&$objectValue, $context, ResolveInfo $info): ObjectType { return $this->concrete; } diff --git a/tests/Utils/SchemaExtenderTest/SomeUnionClassType.php b/tests/Utils/SchemaExtenderTest/SomeUnionClassType.php index 49c997369..a4a97b2cc 100644 --- a/tests/Utils/SchemaExtenderTest/SomeUnionClassType.php +++ b/tests/Utils/SchemaExtenderTest/SomeUnionClassType.php @@ -11,7 +11,7 @@ final class SomeUnionClassType extends UnionType { public ObjectType $concrete; - public function resolveType($objectValue, $context, ResolveInfo $info): ObjectType + public function resolveType(&$objectValue, $context, ResolveInfo $info): ObjectType { return $this->concrete; }