Simplify operationTypes validation

ref: graphql/graphql-js#999

# Conflicts:
#	src/Utils/BuildSchema.php
This commit is contained in:
Daniel Tschinder 2018-02-09 13:49:10 +01:00
parent 1fdb3da7fb
commit 17a8c26fc9

View File

@ -13,7 +13,7 @@ use GraphQL\Language\AST\InterfaceTypeDefinitionNode;
use GraphQL\Language\AST\NodeKind; use GraphQL\Language\AST\NodeKind;
use GraphQL\Language\AST\ObjectTypeDefinitionNode; use GraphQL\Language\AST\ObjectTypeDefinitionNode;
use GraphQL\Language\AST\ScalarTypeDefinitionNode; use GraphQL\Language\AST\ScalarTypeDefinitionNode;
use GraphQL\Language\AST\TypeDefinitionNode; use GraphQL\Language\AST\SchemaDefinitionNode;
use GraphQL\Language\AST\TypeNode; use GraphQL\Language\AST\TypeNode;
use GraphQL\Language\AST\UnionTypeDefinitionNode; use GraphQL\Language\AST\UnionTypeDefinitionNode;
use GraphQL\Language\Parser; use GraphQL\Language\Parser;
@ -110,6 +110,7 @@ class BuildSchema
public function buildSchema() public function buildSchema()
{ {
/** @var SchemaDefinitionNode $schemaDef */
$schemaDef = null; $schemaDef = null;
$typeDefs = []; $typeDefs = [];
$this->nodeMap = []; $this->nodeMap = [];
@ -141,61 +142,13 @@ class BuildSchema
} }
} }
$queryTypeName = null; $operationTypes = $schemaDef
$mutationTypeName = null; ? $this->getOperationTypes($schemaDef)
$subscriptionTypeName = null; : [
if ($schemaDef) { 'query' => isset($this->nodeMap['Query']) ? 'Query' : null,
foreach ($schemaDef->operationTypes as $operationType) { 'mutation' => isset($this->nodeMap['Mutation']) ? 'Mutation' : null,
$typeName = $operationType->type->name->value; 'subscription' => isset($this->nodeMap['Subscription']) ? 'Subscription' : null,
if ($operationType->operation === 'query') { ];
if ($queryTypeName) {
throw new Error('Must provide only one query type in schema.');
}
if (!isset($this->nodeMap[$typeName])) {
throw new Error(
'Specified query type "' . $typeName . '" not found in document.'
);
}
$queryTypeName = $typeName;
} else if ($operationType->operation === 'mutation') {
if ($mutationTypeName) {
throw new Error('Must provide only one mutation type in schema.');
}
if (!isset($this->nodeMap[$typeName])) {
throw new Error(
'Specified mutation type "' . $typeName . '" not found in document.'
);
}
$mutationTypeName = $typeName;
} else if ($operationType->operation === 'subscription') {
if ($subscriptionTypeName) {
throw new Error('Must provide only one subscription type in schema.');
}
if (!isset($this->nodeMap[$typeName])) {
throw new Error(
'Specified subscription type "' . $typeName . '" not found in document.'
);
}
$subscriptionTypeName = $typeName;
}
}
} else {
if (isset($this->nodeMap['Query'])) {
$queryTypeName = 'Query';
}
if (isset($this->nodeMap['Mutation'])) {
$mutationTypeName = 'Mutation';
}
if (isset($this->nodeMap['Subscription'])) {
$subscriptionTypeName = 'Subscription';
}
}
if (!$queryTypeName) {
throw new Error(
'Must provide schema definition with query type or a type named Query.'
);
}
$this->innerTypeMap = [ $this->innerTypeMap = [
'String' => Type::string(), 'String' => Type::string(),
@ -237,13 +190,19 @@ class BuildSchema
$directives[] = Directive::deprecatedDirective(); $directives[] = Directive::deprecatedDirective();
} }
if (!isset($operationTypes['query'])) {
throw new Error(
'Must provide schema definition with query type or a type named Query.'
);
}
$schema = new Schema([ $schema = new Schema([
'query' => $this->getObjectType($this->nodeMap[$queryTypeName]), 'query' => $this->getObjectType($operationTypes['query']),
'mutation' => $mutationTypeName ? 'mutation' => isset($operationTypes['mutation']) ?
$this->getObjectType($this->nodeMap[$mutationTypeName]) : $this->getObjectType($operationTypes['mutation']) :
null, null,
'subscription' => $subscriptionTypeName ? 'subscription' => isset($operationTypes['subscription']) ?
$this->getObjectType($this->nodeMap[$subscriptionTypeName]) : $this->getObjectType($operationTypes['subscription']) :
null, null,
'typeLoader' => function ($name) { 'typeLoader' => function ($name) {
return $this->typeDefNamed($name); return $this->typeDefNamed($name);
@ -264,6 +223,33 @@ class BuildSchema
return $schema; return $schema;
} }
/**
* @param SchemaDefinitionNode $schemaDef
* @return array
* @throws Error
*/
private function getOperationTypes($schemaDef)
{
$opTypes = [];
foreach ($schemaDef->operationTypes as $operationType) {
$typeName = $operationType->type->name->value;
$operation = $operationType->operation;
if (isset($opTypes[$operation])) {
throw new Error("Must provide only one $operation type in schema.");
}
if (!isset($this->nodeMap[$typeName])) {
throw new Error("Specified $operation type \"$typeName\" not found in document.");
}
$opTypes[$operation] = $typeName;
}
return $opTypes;
}
private function getDirective(DirectiveDefinitionNode $directiveNode) private function getDirective(DirectiveDefinitionNode $directiveNode)
{ {
return new Directive([ return new Directive([
@ -277,9 +263,14 @@ class BuildSchema
]); ]);
} }
private function getObjectType(TypeDefinitionNode $typeNode) /**
* @param string $name
* @return CustomScalarType|EnumType|InputObjectType|UnionType
* @throws Error
*/
private function getObjectType($name)
{ {
$type = $this->typeDefNamed($typeNode->name->value); $type = $this->typeDefNamed($name);
Utils::invariant( Utils::invariant(
$type instanceof ObjectType, $type instanceof ObjectType,
'AST must provide object type.' 'AST must provide object type.'