mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-22 21:06:05 +03:00
Robust type info
There are possibilities for errors during validation if a schema is not valid when provided to TypeInfo. Most checks for validity existed, but some did not. This asks flow to make those checks required and adds the remaining ones. Important now that we allow construction of invalid schema. ref: graphql/graphql-js#1143
This commit is contained in:
parent
97e8a9e200
commit
fde7df534d
@ -4,6 +4,7 @@ namespace GraphQL\Utils;
|
|||||||
use GraphQL\Error\InvariantViolation;
|
use GraphQL\Error\InvariantViolation;
|
||||||
use GraphQL\Error\Warning;
|
use GraphQL\Error\Warning;
|
||||||
use GraphQL\Language\AST\FieldNode;
|
use GraphQL\Language\AST\FieldNode;
|
||||||
|
use GraphQL\Language\AST\ListType;
|
||||||
use GraphQL\Language\AST\ListTypeNode;
|
use GraphQL\Language\AST\ListTypeNode;
|
||||||
use GraphQL\Language\AST\NamedTypeNode;
|
use GraphQL\Language\AST\NamedTypeNode;
|
||||||
use GraphQL\Language\AST\Node;
|
use GraphQL\Language\AST\Node;
|
||||||
@ -296,6 +297,10 @@ class TypeInfo
|
|||||||
{
|
{
|
||||||
$schema = $this->schema;
|
$schema = $this->schema;
|
||||||
|
|
||||||
|
// Note: many of the types below are explicitly typed as "mixed" to drop
|
||||||
|
// any assumptions of a valid schema to ensure runtime types are properly
|
||||||
|
// checked before continuing since TypeInfo is used as part of validation
|
||||||
|
// which occurs before guarantees of schema and document validity.
|
||||||
switch ($node->kind) {
|
switch ($node->kind) {
|
||||||
case NodeKind::SELECTION_SET:
|
case NodeKind::SELECTION_SET:
|
||||||
$namedType = Type::getNamedType($this->getType());
|
$namedType = Type::getNamedType($this->getType());
|
||||||
@ -308,8 +313,12 @@ class TypeInfo
|
|||||||
if ($parentType) {
|
if ($parentType) {
|
||||||
$fieldDef = self::getFieldDefinition($schema, $parentType, $node);
|
$fieldDef = self::getFieldDefinition($schema, $parentType, $node);
|
||||||
}
|
}
|
||||||
$this->fieldDefStack[] = $fieldDef; // push
|
$fieldType = null;
|
||||||
$this->typeStack[] = $fieldDef ? $fieldDef->getType() : null; // push
|
if ($fieldDef) {
|
||||||
|
$fieldType = $fieldDef->getType();
|
||||||
|
}
|
||||||
|
$this->fieldDefStack[] = $fieldDef;
|
||||||
|
$this->typeStack[] = Type::isOutputType($fieldType) ? $fieldType : null;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind::DIRECTIVE:
|
case NodeKind::DIRECTIVE:
|
||||||
@ -325,14 +334,14 @@ class TypeInfo
|
|||||||
} else if ($node->operation === 'subscription') {
|
} else if ($node->operation === 'subscription') {
|
||||||
$type = $schema->getSubscriptionType();
|
$type = $schema->getSubscriptionType();
|
||||||
}
|
}
|
||||||
$this->typeStack[] = $type; // push
|
$this->typeStack[] = Type::isOutputType($type) ? $type : null;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind::INLINE_FRAGMENT:
|
case NodeKind::INLINE_FRAGMENT:
|
||||||
case NodeKind::FRAGMENT_DEFINITION:
|
case NodeKind::FRAGMENT_DEFINITION:
|
||||||
$typeConditionNode = $node->typeCondition;
|
$typeConditionNode = $node->typeCondition;
|
||||||
$outputType = $typeConditionNode ? self::typeFromAST($schema, $typeConditionNode) : Type::getNamedType($this->getType());
|
$outputType = $typeConditionNode ? self::typeFromAST($schema, $typeConditionNode) : Type::getNamedType($this->getType());
|
||||||
$this->typeStack[] = Type::isOutputType($outputType) ? $outputType : null; // push
|
$this->typeStack[] = Type::isOutputType($outputType) ? $outputType : null;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind::VARIABLE_DEFINITION:
|
case NodeKind::VARIABLE_DEFINITION:
|
||||||
@ -350,23 +359,28 @@ class TypeInfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->argument = $argDef;
|
$this->argument = $argDef;
|
||||||
$this->inputTypeStack[] = $argType; // push
|
$this->inputTypeStack[] = Type::isInputType($argType) ? $argType : null;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind::LST:
|
case NodeKind::LST:
|
||||||
$listType = Type::getNullableType($this->getInputType());
|
$listType = Type::getNullableType($this->getInputType());
|
||||||
$this->inputTypeStack[] = ($listType instanceof ListOfType ? $listType->getWrappedType() : null); // push
|
$itemType = null;
|
||||||
|
if ($itemType instanceof ListType) {
|
||||||
|
$itemType = $listType->getWrappedType();
|
||||||
|
}
|
||||||
|
$this->inputTypeStack[] = Type::isInputType($itemType) ? $itemType : null;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind::OBJECT_FIELD:
|
case NodeKind::OBJECT_FIELD:
|
||||||
$objectType = Type::getNamedType($this->getInputType());
|
$objectType = Type::getNamedType($this->getInputType());
|
||||||
$fieldType = null;
|
$fieldType = null;
|
||||||
|
$inputFieldType = null;
|
||||||
if ($objectType instanceof InputObjectType) {
|
if ($objectType instanceof InputObjectType) {
|
||||||
$tmp = $objectType->getFields();
|
$tmp = $objectType->getFields();
|
||||||
$inputField = isset($tmp[$node->name->value]) ? $tmp[$node->name->value] : null;
|
$inputField = isset($tmp[$node->name->value]) ? $tmp[$node->name->value] : null;
|
||||||
$fieldType = $inputField ? $inputField->getType() : null;
|
$inputFieldType = $inputField ? $inputField->getType() : null;
|
||||||
}
|
}
|
||||||
$this->inputTypeStack[] = $fieldType;
|
$this->inputTypeStack[] = Type::isInputType($inputFieldType) ? $inputFieldType : null;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind::ENUM:
|
case NodeKind::ENUM:
|
||||||
|
Loading…
Reference in New Issue
Block a user