diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 1052841..3872fd8 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -2,6 +2,7 @@ namespace GraphQL\Executor; use GraphQL\Error\Error; +use GraphQL\Error\InvariantViolation; use GraphQL\Language\AST\Document; use GraphQL\Language\AST\Field; use GraphQL\Language\AST\FragmentDefinition; @@ -11,13 +12,12 @@ use GraphQL\Language\AST\SelectionSet; use GraphQL\Schema; use GraphQL\Type\Definition\AbstractType; use GraphQL\Type\Definition\Directive; -use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\FieldDefinition; +use GraphQL\Type\Definition\LeafType; use GraphQL\Type\Definition\ListOfType; use GraphQL\Type\Definition\NonNull; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ResolveInfo; -use GraphQL\Type\Definition\ScalarType; use GraphQL\Type\Definition\Type; use GraphQL\Type\DefinitionContainer; use GraphQL\Type\Introspection; @@ -619,7 +619,7 @@ class Executor $result ); if ($completed === null) { - throw new \UnexpectedValueException( + throw new InvariantViolation( 'Cannot return null for non-nullable field ' . $info->parentType . '.' . $info->fieldName . '.' ); } @@ -638,8 +638,7 @@ class Executor // If field type is Scalar or Enum, serialize to a valid value, returning // null if serialization is not possible. - if ($returnType instanceof ScalarType || - $returnType instanceof EnumType) { + if ($returnType instanceof LeafType) { return self::completeLeafValue($returnType, $result); } @@ -745,6 +744,7 @@ class Executor $runtimeType = $exeContext->schema->getType($runtimeType); } + // FIXME: Executor should never face with DefinitionContainer - it should be unwrapped in Schema if ($runtimeType instanceof DefinitionContainer) { $runtimeType = $runtimeType->getDefinition(); } @@ -801,19 +801,18 @@ class Executor * Complete a Scalar or Enum by serializing to a valid value, returning * null if serialization is not possible. * - * @param Type $returnType + * @param LeafType $returnType * @param $result * @return mixed * @throws \Exception */ - private static function completeLeafValue(Type $returnType, &$result) + private static function completeLeafValue(LeafType $returnType, &$result) { - Utils::invariant(method_exists($returnType, 'serialize'), 'Missing serialize method on type'); $serializedResult = $returnType->serialize($result); if ($serializedResult === null) { - throw new \UnexpectedValueException( - 'Expected a value of type "'. $returnType . '" but received: ' . Utils::printSafe($result) + throw new InvariantViolation( + 'Expected a value of type "'. Utils::printSafe($returnType) . '" but received: ' . Utils::printSafe($result) ); } return $serializedResult; diff --git a/src/Executor/Values.php b/src/Executor/Values.php index b43e82a..e6b2986 100644 --- a/src/Executor/Values.php +++ b/src/Executor/Values.php @@ -3,6 +3,7 @@ namespace GraphQL\Executor; use GraphQL\Error\Error; +use GraphQL\Error\InvariantViolation; use GraphQL\Language\AST\Argument; use GraphQL\Language\AST\VariableDefinition; use GraphQL\Language\Printer; @@ -11,6 +12,7 @@ use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\FieldArgument; use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InputType; +use GraphQL\Type\Definition\LeafType; use GraphQL\Type\Definition\ListOfType; use GraphQL\Type\Definition\NonNull; use GraphQL\Type\Definition\ScalarType; @@ -199,22 +201,20 @@ class Values return $errors; } - Utils::invariant( - $type instanceof ScalarType || $type instanceof EnumType, - 'Must be input type' - ); - - // Scalar/Enum input checks to ensure the type can parse the value to - // a non-null value. - $parseResult = $type->parseValue($value); - if (null === $parseResult) { - $v = json_encode($value); - return [ - "Expected type \"{$type->name}\", found $v." - ]; + if ($type instanceof LeafType) { + // Scalar/Enum input checks to ensure the type can parse the value to + // a non-null value. + $parseResult = $type->parseValue($value); + if (null === $parseResult) { + $v = json_encode($value); + return [ + "Expected type \"{$type->name}\", found $v." + ]; + } + return []; } - return []; + throw new InvariantViolation('Must be input type'); } /** diff --git a/src/Type/Definition/FloatType.php b/src/Type/Definition/FloatType.php index 522d507..ddc1ece 100644 --- a/src/Type/Definition/FloatType.php +++ b/src/Type/Definition/FloatType.php @@ -1,6 +1,7 @@ = self::MIN_INT) { return (int) $value; } - throw new \UnexpectedValueException( + throw new InvariantViolation( 'Int cannot represent non 32-bit signed integer value: ' . Utils::printSafe($value) ); } diff --git a/src/Type/Definition/ListOfType.php b/src/Type/Definition/ListOfType.php index 3e37a54..f4f892f 100644 --- a/src/Type/Definition/ListOfType.php +++ b/src/Type/Definition/ListOfType.php @@ -33,7 +33,8 @@ class ListOfType extends Type implements WrappingType, OutputType, InputType */ public function toString() { - $str = $this->ofType instanceof Type ? $this->ofType->toString() : (string) $this->ofType; + $type = Type::resolve($this->ofType); + $str = $type instanceof Type ? $type->toString() : (string) $type; return '[' . $str . ']'; } diff --git a/src/Type/Definition/Type.php b/src/Type/Definition/Type.php index 4349b78..52a1f63 100644 --- a/src/Type/Definition/Type.php +++ b/src/Type/Definition/Type.php @@ -187,7 +187,6 @@ abstract class Type /** * @param $type - * @deprecated in favor of defining ObjectType 'fields' as closure (vs defining closure per field type) * @return mixed */ public static function resolve($type) diff --git a/src/Utils/TypeInfo.php b/src/Utils/TypeInfo.php index 740b1e6..e7bd67f 100644 --- a/src/Utils/TypeInfo.php +++ b/src/Utils/TypeInfo.php @@ -156,7 +156,7 @@ class TypeInfo return $innerType ? new NonNull($innerType) : null; } - Utils::invariant($inputTypeAst && $inputTypeAst->kind === Node::NAMED_TYPE, 'Must be a named type'); + Utils::invariant($inputTypeAst && $inputTypeAst instanceof NamedType, 'Must be a named type'); return $schema->getType($inputTypeAst->name->value); } @@ -180,11 +180,7 @@ class TypeInfo return $typeMeta; } $typeNameMeta = Introspection::typeNameMetaFieldDef(); - if ($name === $typeNameMeta->name && - ($parentType instanceof ObjectType || - $parentType instanceof InterfaceType || - $parentType instanceof UnionType) - ) { + if ($name === $typeNameMeta->name && $parentType instanceof CompositeType) { return $typeNameMeta; } if ($parentType instanceof ObjectType || diff --git a/src/Validator/DocumentValidator.php b/src/Validator/DocumentValidator.php index 1566344..c55a5b0 100644 --- a/src/Validator/DocumentValidator.php +++ b/src/Validator/DocumentValidator.php @@ -2,6 +2,7 @@ namespace GraphQL\Validator; use GraphQL\Error\Error; +use GraphQL\Error\InvariantViolation; use GraphQL\Language\AST\ListValue; use GraphQL\Language\AST\Document; use GraphQL\Language\AST\FragmentSpread; @@ -12,12 +13,11 @@ use GraphQL\Language\Printer; use GraphQL\Language\Visitor; use GraphQL\Language\VisitorOperation; use GraphQL\Schema; -use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InputType; +use GraphQL\Type\Definition\LeafType; use GraphQL\Type\Definition\ListOfType; use GraphQL\Type\Definition\NonNull; -use GraphQL\Type\Definition\ScalarType; use GraphQL\Type\Definition\Type; use GraphQL\Utils; use GraphQL\Utils\TypeInfo; @@ -228,21 +228,20 @@ class DocumentValidator return $errors; } - Utils::invariant( - $type instanceof ScalarType || $type instanceof EnumType, - 'Must be input type' - ); + if ($type instanceof LeafType) { + // Scalar/Enum input checks to ensure the type can parse the value to + // a non-null value. + $parseResult = $type->parseLiteral($valueAST); - // Scalar/Enum input checks to ensure the type can parse the value to - // a non-null value. - $parseResult = $type->parseLiteral($valueAST); + if (null === $parseResult) { + $printed = Printer::doPrint($valueAST); + return [ "Expected type \"{$type->name}\", found $printed." ]; + } - if (null === $parseResult) { - $printed = Printer::doPrint($valueAST); - return [ "Expected type \"{$type->name}\", found $printed." ]; + return []; } - return []; + throw new InvariantViolation('Must be input type'); } /** diff --git a/tests/Type/ScalarSerializationTest.php b/tests/Type/ScalarSerializationTest.php index cd95daf..e0be2fa 100644 --- a/tests/Type/ScalarSerializationTest.php +++ b/tests/Type/ScalarSerializationTest.php @@ -1,6 +1,7 @@ serialize(9876504321); $this->fail('Expected exception was not thrown'); - } catch (\UnexpectedValueException $e) { + } catch (InvariantViolation $e) { $this->assertEquals('Int cannot represent non 32-bit signed integer value: 9876504321', $e->getMessage()); } try { $intType->serialize(-9876504321); $this->fail('Expected exception was not thrown'); - } catch (\UnexpectedValueException $e) { + } catch (InvariantViolation $e) { $this->assertEquals('Int cannot represent non 32-bit signed integer value: -9876504321', $e->getMessage()); } try { $intType->serialize(1e100); $this->fail('Expected exception was not thrown'); - } catch (\UnexpectedValueException $e) { + } catch (InvariantViolation $e) { $this->assertEquals('Int cannot represent non 32-bit signed integer value: 1.0E+100', $e->getMessage()); } try { $intType->serialize(-1e100); $this->fail('Expected exception was not thrown'); - } catch (\UnexpectedValueException $e) { + } catch (InvariantViolation $e) { $this->assertEquals('Int cannot represent non 32-bit signed integer value: -1.0E+100', $e->getMessage()); } @@ -57,14 +58,14 @@ class ScalarSerializationTest extends \PHPUnit_Framework_TestCase try { $intType->serialize('one'); $this->fail('Expected exception was not thrown'); - } catch (\UnexpectedValueException $e) { + } catch (InvariantViolation $e) { $this->assertEquals('Int cannot represent non 32-bit signed integer value: one', $e->getMessage()); } try { $intType->serialize(''); $this->fail('Expected exception was not thrown'); - } catch (\UnexpectedValueException $e) { + } catch (InvariantViolation $e) { $this->assertEquals('Int cannot represent non 32-bit signed integer value: (empty string)', $e->getMessage()); } @@ -91,14 +92,14 @@ class ScalarSerializationTest extends \PHPUnit_Framework_TestCase try { $floatType->serialize('one'); $this->fail('Expected exception was not thrown'); - } catch (\UnexpectedValueException $e) { + } catch (InvariantViolation $e) { $this->assertEquals('Float cannot represent non numeric value: one', $e->getMessage()); } try { $floatType->serialize(''); $this->fail('Expected exception was not thrown'); - } catch (\UnexpectedValueException $e) { + } catch (InvariantViolation $e) { $this->assertEquals('Float cannot represent non numeric value: (empty string)', $e->getMessage()); }