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\ObjectTypeDefinitionNode;
use GraphQL\Language\AST\ScalarTypeDefinitionNode;
use GraphQL\Language\AST\TypeDefinitionNode;
use GraphQL\Language\AST\SchemaDefinitionNode;
use GraphQL\Language\AST\TypeNode;
use GraphQL\Language\AST\UnionTypeDefinitionNode;
use GraphQL\Language\Parser;
@ -110,6 +110,7 @@ class BuildSchema
public function buildSchema()
{
/** @var SchemaDefinitionNode $schemaDef */
$schemaDef = null;
$typeDefs = [];
$this->nodeMap = [];
@ -141,61 +142,13 @@ class BuildSchema
}
}
$queryTypeName = null;
$mutationTypeName = null;
$subscriptionTypeName = null;
if ($schemaDef) {
foreach ($schemaDef->operationTypes as $operationType) {
$typeName = $operationType->type->name->value;
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.'
);
}
$operationTypes = $schemaDef
? $this->getOperationTypes($schemaDef)
: [
'query' => isset($this->nodeMap['Query']) ? 'Query' : null,
'mutation' => isset($this->nodeMap['Mutation']) ? 'Mutation' : null,
'subscription' => isset($this->nodeMap['Subscription']) ? 'Subscription' : null,
];
$this->innerTypeMap = [
'String' => Type::string(),
@ -237,13 +190,19 @@ class BuildSchema
$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([
'query' => $this->getObjectType($this->nodeMap[$queryTypeName]),
'mutation' => $mutationTypeName ?
$this->getObjectType($this->nodeMap[$mutationTypeName]) :
'query' => $this->getObjectType($operationTypes['query']),
'mutation' => isset($operationTypes['mutation']) ?
$this->getObjectType($operationTypes['mutation']) :
null,
'subscription' => $subscriptionTypeName ?
$this->getObjectType($this->nodeMap[$subscriptionTypeName]) :
'subscription' => isset($operationTypes['subscription']) ?
$this->getObjectType($operationTypes['subscription']) :
null,
'typeLoader' => function ($name) {
return $this->typeDefNamed($name);
@ -264,6 +223,33 @@ class BuildSchema
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)
{
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(
$type instanceof ObjectType,
'AST must provide object type.'