Replaced \UnexpectedValueException with GraphQL\Error\InvariantViolationException; Improved some instanceof checks

This commit is contained in:
vladar 2016-11-01 23:40:37 +07:00
parent 4a75bc6d2f
commit e56eb6e10d
9 changed files with 54 additions and 57 deletions

View File

@ -2,6 +2,7 @@
namespace GraphQL\Executor; namespace GraphQL\Executor;
use GraphQL\Error\Error; use GraphQL\Error\Error;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\Document; use GraphQL\Language\AST\Document;
use GraphQL\Language\AST\Field; use GraphQL\Language\AST\Field;
use GraphQL\Language\AST\FragmentDefinition; use GraphQL\Language\AST\FragmentDefinition;
@ -11,13 +12,12 @@ use GraphQL\Language\AST\SelectionSet;
use GraphQL\Schema; use GraphQL\Schema;
use GraphQL\Type\Definition\AbstractType; use GraphQL\Type\Definition\AbstractType;
use GraphQL\Type\Definition\Directive; use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\FieldDefinition; use GraphQL\Type\Definition\FieldDefinition;
use GraphQL\Type\Definition\LeafType;
use GraphQL\Type\Definition\ListOfType; use GraphQL\Type\Definition\ListOfType;
use GraphQL\Type\Definition\NonNull; use GraphQL\Type\Definition\NonNull;
use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\Type;
use GraphQL\Type\DefinitionContainer; use GraphQL\Type\DefinitionContainer;
use GraphQL\Type\Introspection; use GraphQL\Type\Introspection;
@ -619,7 +619,7 @@ class Executor
$result $result
); );
if ($completed === null) { if ($completed === null) {
throw new \UnexpectedValueException( throw new InvariantViolation(
'Cannot return null for non-nullable field ' . $info->parentType . '.' . $info->fieldName . '.' '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 // If field type is Scalar or Enum, serialize to a valid value, returning
// null if serialization is not possible. // null if serialization is not possible.
if ($returnType instanceof ScalarType || if ($returnType instanceof LeafType) {
$returnType instanceof EnumType) {
return self::completeLeafValue($returnType, $result); return self::completeLeafValue($returnType, $result);
} }
@ -745,6 +744,7 @@ class Executor
$runtimeType = $exeContext->schema->getType($runtimeType); $runtimeType = $exeContext->schema->getType($runtimeType);
} }
// FIXME: Executor should never face with DefinitionContainer - it should be unwrapped in Schema
if ($runtimeType instanceof DefinitionContainer) { if ($runtimeType instanceof DefinitionContainer) {
$runtimeType = $runtimeType->getDefinition(); $runtimeType = $runtimeType->getDefinition();
} }
@ -801,19 +801,18 @@ class Executor
* Complete a Scalar or Enum by serializing to a valid value, returning * Complete a Scalar or Enum by serializing to a valid value, returning
* null if serialization is not possible. * null if serialization is not possible.
* *
* @param Type $returnType * @param LeafType $returnType
* @param $result * @param $result
* @return mixed * @return mixed
* @throws \Exception * @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); $serializedResult = $returnType->serialize($result);
if ($serializedResult === null) { if ($serializedResult === null) {
throw new \UnexpectedValueException( throw new InvariantViolation(
'Expected a value of type "'. $returnType . '" but received: ' . Utils::printSafe($result) 'Expected a value of type "'. Utils::printSafe($returnType) . '" but received: ' . Utils::printSafe($result)
); );
} }
return $serializedResult; return $serializedResult;

View File

@ -3,6 +3,7 @@ namespace GraphQL\Executor;
use GraphQL\Error\Error; use GraphQL\Error\Error;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\Argument; use GraphQL\Language\AST\Argument;
use GraphQL\Language\AST\VariableDefinition; use GraphQL\Language\AST\VariableDefinition;
use GraphQL\Language\Printer; use GraphQL\Language\Printer;
@ -11,6 +12,7 @@ use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\FieldArgument; use GraphQL\Type\Definition\FieldArgument;
use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\InputType; use GraphQL\Type\Definition\InputType;
use GraphQL\Type\Definition\LeafType;
use GraphQL\Type\Definition\ListOfType; use GraphQL\Type\Definition\ListOfType;
use GraphQL\Type\Definition\NonNull; use GraphQL\Type\Definition\NonNull;
use GraphQL\Type\Definition\ScalarType; use GraphQL\Type\Definition\ScalarType;
@ -199,22 +201,20 @@ class Values
return $errors; return $errors;
} }
Utils::invariant( if ($type instanceof LeafType) {
$type instanceof ScalarType || $type instanceof EnumType, // Scalar/Enum input checks to ensure the type can parse the value to
'Must be input type' // a non-null value.
); $parseResult = $type->parseValue($value);
if (null === $parseResult) {
// Scalar/Enum input checks to ensure the type can parse the value to $v = json_encode($value);
// a non-null value. return [
$parseResult = $type->parseValue($value); "Expected type \"{$type->name}\", found $v."
if (null === $parseResult) { ];
$v = json_encode($value); }
return [ return [];
"Expected type \"{$type->name}\", found $v."
];
} }
return []; throw new InvariantViolation('Must be input type');
} }
/** /**

View File

@ -1,6 +1,7 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\FloatValue; use GraphQL\Language\AST\FloatValue;
use GraphQL\Language\AST\IntValue; use GraphQL\Language\AST\IntValue;
use GraphQL\Utils; use GraphQL\Utils;
@ -49,14 +50,14 @@ values as specified by
private function coerceFloat($value) private function coerceFloat($value)
{ {
if ($value === '') { if ($value === '') {
throw new \UnexpectedValueException( throw new InvariantViolation(
'Float cannot represent non numeric value: (empty string)' 'Float cannot represent non numeric value: (empty string)'
); );
} }
if (is_numeric($value) || $value === true || $value === false) { if (is_numeric($value) || $value === true || $value === false) {
return (float)$value; return (float)$value;
} }
throw new \UnexpectedValueException('Float cannot represent non numeric value: ' . Utils::printSafe($value)); throw new InvariantViolation('Float cannot represent non numeric value: ' . Utils::printSafe($value));
} }
/** /**

View File

@ -1,6 +1,7 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\IntValue; use GraphQL\Language\AST\IntValue;
use GraphQL\Language\AST\Value; use GraphQL\Language\AST\Value;
use GraphQL\Utils; use GraphQL\Utils;
@ -56,7 +57,7 @@ values. Int can represent values between -(2^31) and 2^31 - 1. ';
private function coerceInt($value) private function coerceInt($value)
{ {
if ($value === '') { if ($value === '') {
throw new \UnexpectedValueException( throw new InvariantViolation(
'Int cannot represent non 32-bit signed integer value: (empty string)' 'Int cannot represent non 32-bit signed integer value: (empty string)'
); );
} }
@ -66,7 +67,7 @@ values. Int can represent values between -(2^31) and 2^31 - 1. ';
if (is_numeric($value) && $value <= self::MAX_INT && $value >= self::MIN_INT) { if (is_numeric($value) && $value <= self::MAX_INT && $value >= self::MIN_INT) {
return (int) $value; return (int) $value;
} }
throw new \UnexpectedValueException( throw new InvariantViolation(
'Int cannot represent non 32-bit signed integer value: ' . Utils::printSafe($value) 'Int cannot represent non 32-bit signed integer value: ' . Utils::printSafe($value)
); );
} }

View File

@ -33,7 +33,8 @@ class ListOfType extends Type implements WrappingType, OutputType, InputType
*/ */
public function toString() 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 . ']'; return '[' . $str . ']';
} }

View File

@ -187,7 +187,6 @@ abstract class Type
/** /**
* @param $type * @param $type
* @deprecated in favor of defining ObjectType 'fields' as closure (vs defining closure per field type)
* @return mixed * @return mixed
*/ */
public static function resolve($type) public static function resolve($type)

View File

@ -156,7 +156,7 @@ class TypeInfo
return $innerType ? new NonNull($innerType) : null; 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); return $schema->getType($inputTypeAst->name->value);
} }
@ -180,11 +180,7 @@ class TypeInfo
return $typeMeta; return $typeMeta;
} }
$typeNameMeta = Introspection::typeNameMetaFieldDef(); $typeNameMeta = Introspection::typeNameMetaFieldDef();
if ($name === $typeNameMeta->name && if ($name === $typeNameMeta->name && $parentType instanceof CompositeType) {
($parentType instanceof ObjectType ||
$parentType instanceof InterfaceType ||
$parentType instanceof UnionType)
) {
return $typeNameMeta; return $typeNameMeta;
} }
if ($parentType instanceof ObjectType || if ($parentType instanceof ObjectType ||

View File

@ -2,6 +2,7 @@
namespace GraphQL\Validator; namespace GraphQL\Validator;
use GraphQL\Error\Error; use GraphQL\Error\Error;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\ListValue; use GraphQL\Language\AST\ListValue;
use GraphQL\Language\AST\Document; use GraphQL\Language\AST\Document;
use GraphQL\Language\AST\FragmentSpread; use GraphQL\Language\AST\FragmentSpread;
@ -12,12 +13,11 @@ use GraphQL\Language\Printer;
use GraphQL\Language\Visitor; use GraphQL\Language\Visitor;
use GraphQL\Language\VisitorOperation; use GraphQL\Language\VisitorOperation;
use GraphQL\Schema; use GraphQL\Schema;
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\InputType; use GraphQL\Type\Definition\InputType;
use GraphQL\Type\Definition\LeafType;
use GraphQL\Type\Definition\ListOfType; use GraphQL\Type\Definition\ListOfType;
use GraphQL\Type\Definition\NonNull; use GraphQL\Type\Definition\NonNull;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\Type;
use GraphQL\Utils; use GraphQL\Utils;
use GraphQL\Utils\TypeInfo; use GraphQL\Utils\TypeInfo;
@ -228,21 +228,20 @@ class DocumentValidator
return $errors; return $errors;
} }
Utils::invariant( if ($type instanceof LeafType) {
$type instanceof ScalarType || $type instanceof EnumType, // Scalar/Enum input checks to ensure the type can parse the value to
'Must be input type' // a non-null value.
); $parseResult = $type->parseLiteral($valueAST);
// Scalar/Enum input checks to ensure the type can parse the value to if (null === $parseResult) {
// a non-null value. $printed = Printer::doPrint($valueAST);
$parseResult = $type->parseLiteral($valueAST); return [ "Expected type \"{$type->name}\", found $printed." ];
}
if (null === $parseResult) { return [];
$printed = Printer::doPrint($valueAST);
return [ "Expected type \"{$type->name}\", found $printed." ];
} }
return []; throw new InvariantViolation('Must be input type');
} }
/** /**

View File

@ -1,6 +1,7 @@
<?php <?php
namespace GraphQL\Tests\Type; namespace GraphQL\Tests\Type;
use GraphQL\Error\InvariantViolation;
use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\Type;
class ScalarSerializationTest extends \PHPUnit_Framework_TestCase class ScalarSerializationTest extends \PHPUnit_Framework_TestCase
@ -27,28 +28,28 @@ class ScalarSerializationTest extends \PHPUnit_Framework_TestCase
try { try {
$intType->serialize(9876504321); $intType->serialize(9876504321);
$this->fail('Expected exception was not thrown'); $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()); $this->assertEquals('Int cannot represent non 32-bit signed integer value: 9876504321', $e->getMessage());
} }
try { try {
$intType->serialize(-9876504321); $intType->serialize(-9876504321);
$this->fail('Expected exception was not thrown'); $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()); $this->assertEquals('Int cannot represent non 32-bit signed integer value: -9876504321', $e->getMessage());
} }
try { try {
$intType->serialize(1e100); $intType->serialize(1e100);
$this->fail('Expected exception was not thrown'); $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()); $this->assertEquals('Int cannot represent non 32-bit signed integer value: 1.0E+100', $e->getMessage());
} }
try { try {
$intType->serialize(-1e100); $intType->serialize(-1e100);
$this->fail('Expected exception was not thrown'); $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()); $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 { try {
$intType->serialize('one'); $intType->serialize('one');
$this->fail('Expected exception was not thrown'); $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()); $this->assertEquals('Int cannot represent non 32-bit signed integer value: one', $e->getMessage());
} }
try { try {
$intType->serialize(''); $intType->serialize('');
$this->fail('Expected exception was not thrown'); $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()); $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 { try {
$floatType->serialize('one'); $floatType->serialize('one');
$this->fail('Expected exception was not thrown'); $this->fail('Expected exception was not thrown');
} catch (\UnexpectedValueException $e) { } catch (InvariantViolation $e) {
$this->assertEquals('Float cannot represent non numeric value: one', $e->getMessage()); $this->assertEquals('Float cannot represent non numeric value: one', $e->getMessage());
} }
try { try {
$floatType->serialize(''); $floatType->serialize('');
$this->fail('Expected exception was not thrown'); $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()); $this->assertEquals('Float cannot represent non numeric value: (empty string)', $e->getMessage());
} }