diff --git a/CHANGELOG.md b/CHANGELOG.md index e7a322f8c..90b20041e 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 +## v15.9.1 + +### Fixed + +- Allow enum instances in `PhpEnumType::parseValue()` https://github.com/webonyx/graphql-php/pull/1519 + ## v15.9.0 ### Added diff --git a/src/Type/Definition/PhpEnumType.php b/src/Type/Definition/PhpEnumType.php index fafe27d6c..fa92ae643 100644 --- a/src/Type/Definition/PhpEnumType.php +++ b/src/Type/Definition/PhpEnumType.php @@ -47,7 +47,7 @@ public function __construct(string $enum, string $name = null) public function serialize($value): string { - if (! is_a($value, $this->enumClass)) { + if (! ($value instanceof $this->enumClass)) { $notEnum = Utils::printSafe($value); throw new SerializationError("Cannot serialize value as enum: {$notEnum}, expected instance of {$this->enumClass}."); } @@ -55,6 +55,16 @@ public function serialize($value): string return $value->name; } + public function parseValue($value) + { + // Can happen when variable values undergo a serialization cycle before execution + if ($value instanceof $this->enumClass) { + return $value; + } + + return parent::parseValue($value); + } + /** @param class-string $class */ protected function baseName(string $class): string { diff --git a/tests/Type/PhpEnumTypeTest.php b/tests/Type/PhpEnumTypeTest.php index 4545a332f..c9c2b4c97 100644 --- a/tests/Type/PhpEnumTypeTest.php +++ b/tests/Type/PhpEnumTypeTest.php @@ -14,6 +14,7 @@ use GraphQL\Tests\Type\PhpEnumType\PhpEnum; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\PhpEnumType; +use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; use GraphQL\Type\Schema; use GraphQL\Utils\SchemaPrinter; @@ -135,6 +136,62 @@ public function testExecutesWithEnumTypeFromPhpEnum(): void ], GraphQL::executeQuery($schema, '{ foo(bar: A) }')->toArray()); } + public function testAcceptsEnumFromVariableValues(): void + { + $enumType = new PhpEnumType(PhpEnum::class); + + $schema = null; + $schema = new Schema([ + 'query' => new ObjectType([ + 'name' => 'Query', + 'fields' => [ + 'foo' => [ + 'type' => Type::nonNull($enumType), + 'args' => [ + 'bar' => [ + 'type' => Type::nonNull($enumType), + ], + ], + 'resolve' => static function (bool $executeAgain, array $args, $context, ResolveInfo $resolveInfo) use (&$schema): PhpEnum { + $bar = $args['bar']; + assert($bar === PhpEnum::A); + + if ($executeAgain) { + $executionResult = GraphQL::executeQuery( + $schema, + 'query ($bar: PhpEnum!) { foo(bar: $bar) }', + false, + null, + $resolveInfo->variableValues + ); + self::assertSame([ + 'data' => [ + 'foo' => 'A', + ], + ], $executionResult->toArray(DebugFlag::RETHROW_INTERNAL_EXCEPTIONS)); + } + + return $bar; + }, + ], + ], + ]), + ]); + + $executionResult = GraphQL::executeQuery( + $schema, + 'query ($bar: PhpEnum!) { foo(bar: $bar) }', + true, + null, + ['bar' => 'A'] + ); + self::assertSame([ + 'data' => [ + 'foo' => 'A', + ], + ], $executionResult->toArray(DebugFlag::RETHROW_INTERNAL_EXCEPTIONS)); + } + public function testFailsToSerializeNonEnum(): void { $enumType = new PhpEnumType(PhpEnum::class);