mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-24 22:06:04 +03:00
Update to match SDL changes
This changes the parsing grammar and validation rules to more correctly implement the current state of the GraphQL SDL proposal (facebook/graphql#90) ref: graphql/graphl-js#1102
This commit is contained in:
parent
0c32982171
commit
d70a9a5e53
@ -374,28 +374,28 @@ public $variableValues;
|
|||||||
*/
|
*/
|
||||||
function getFieldSelection($depth = 0)
|
function getFieldSelection($depth = 0)
|
||||||
```
|
```
|
||||||
# GraphQL\Type\Definition\DirectiveLocation
|
# GraphQL\Language\DirectiveLocation
|
||||||
List of available directive locations
|
List of available directive locations
|
||||||
|
|
||||||
**Class Constants:**
|
**Class Constants:**
|
||||||
```php
|
```php
|
||||||
const IFACE = "INTERFACE";
|
|
||||||
const SUBSCRIPTION = "SUBSCRIPTION";
|
|
||||||
const FRAGMENT_SPREAD = "FRAGMENT_SPREAD";
|
|
||||||
const QUERY = "QUERY";
|
const QUERY = "QUERY";
|
||||||
const MUTATION = "MUTATION";
|
const MUTATION = "MUTATION";
|
||||||
|
const SUBSCRIPTION = "SUBSCRIPTION";
|
||||||
|
const FIELD = "FIELD";
|
||||||
const FRAGMENT_DEFINITION = "FRAGMENT_DEFINITION";
|
const FRAGMENT_DEFINITION = "FRAGMENT_DEFINITION";
|
||||||
const INPUT_OBJECT = "INPUT_OBJECT";
|
const FRAGMENT_SPREAD = "FRAGMENT_SPREAD";
|
||||||
const INLINE_FRAGMENT = "INLINE_FRAGMENT";
|
const INLINE_FRAGMENT = "INLINE_FRAGMENT";
|
||||||
const UNION = "UNION";
|
const SCHEMA = "SCHEMA";
|
||||||
const SCALAR = "SCALAR";
|
const SCALAR = "SCALAR";
|
||||||
|
const OBJECT = "OBJECT";
|
||||||
const FIELD_DEFINITION = "FIELD_DEFINITION";
|
const FIELD_DEFINITION = "FIELD_DEFINITION";
|
||||||
const ARGUMENT_DEFINITION = "ARGUMENT_DEFINITION";
|
const ARGUMENT_DEFINITION = "ARGUMENT_DEFINITION";
|
||||||
|
const IFACE = "INTERFACE";
|
||||||
|
const UNION = "UNION";
|
||||||
const ENUM = "ENUM";
|
const ENUM = "ENUM";
|
||||||
const OBJECT = "OBJECT";
|
|
||||||
const ENUM_VALUE = "ENUM_VALUE";
|
const ENUM_VALUE = "ENUM_VALUE";
|
||||||
const FIELD = "FIELD";
|
const INPUT_OBJECT = "INPUT_OBJECT";
|
||||||
const SCHEMA = "SCHEMA";
|
|
||||||
const INPUT_FIELD_DEFINITION = "INPUT_FIELD_DEFINITION";
|
const INPUT_FIELD_DEFINITION = "INPUT_FIELD_DEFINITION";
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -936,7 +936,7 @@ const UNION_TYPE_DEFINITION = "UnionTypeDefinition";
|
|||||||
const ENUM_TYPE_DEFINITION = "EnumTypeDefinition";
|
const ENUM_TYPE_DEFINITION = "EnumTypeDefinition";
|
||||||
const ENUM_VALUE_DEFINITION = "EnumValueDefinition";
|
const ENUM_VALUE_DEFINITION = "EnumValueDefinition";
|
||||||
const INPUT_OBJECT_TYPE_DEFINITION = "InputObjectTypeDefinition";
|
const INPUT_OBJECT_TYPE_DEFINITION = "InputObjectTypeDefinition";
|
||||||
const TYPE_EXTENSION_DEFINITION = "TypeExtensionDefinition";
|
const OBJECT_TYPE_EXTENSION = "ObjectTypeExtension";
|
||||||
const DIRECTIVE_DEFINITION = "DirectiveDefinition";
|
const DIRECTIVE_DEFINITION = "DirectiveDefinition";
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -35,9 +35,9 @@ In **graphql-php** custom directive is an instance of `GraphQL\Type\Definition\D
|
|||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
<?php
|
||||||
|
use GraphQL\Language\DirectiveLocation;
|
||||||
use GraphQL\Type\Definition\Type;
|
use GraphQL\Type\Definition\Type;
|
||||||
use GraphQL\Type\Definition\Directive;
|
use GraphQL\Type\Definition\Directive;
|
||||||
use GraphQL\Type\Definition\DirectiveLocation;
|
|
||||||
use GraphQL\Type\Definition\FieldArgument;
|
use GraphQL\Type\Definition\FieldArgument;
|
||||||
|
|
||||||
$trackDirective = new Directive([
|
$trackDirective = new Directive([
|
||||||
|
@ -211,11 +211,6 @@ class Executor
|
|||||||
case NodeKind::FRAGMENT_DEFINITION:
|
case NodeKind::FRAGMENT_DEFINITION:
|
||||||
$fragments[$definition->name->value] = $definition;
|
$fragments[$definition->name->value] = $definition;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
throw new Error(
|
|
||||||
"GraphQL cannot execute a request containing a {$definition->kind}.",
|
|
||||||
[$definition]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class NodeKind
|
|||||||
|
|
||||||
// Type Extensions
|
// Type Extensions
|
||||||
|
|
||||||
const TYPE_EXTENSION_DEFINITION = 'TypeExtensionDefinition';
|
const OBJECT_TYPE_EXTENSION = 'ObjectTypeExtension';
|
||||||
|
|
||||||
// Directive Definitions
|
// Directive Definitions
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ class NodeKind
|
|||||||
NodeKind::INPUT_OBJECT_TYPE_DEFINITION =>InputObjectTypeDefinitionNode::class,
|
NodeKind::INPUT_OBJECT_TYPE_DEFINITION =>InputObjectTypeDefinitionNode::class,
|
||||||
|
|
||||||
// Type Extensions
|
// Type Extensions
|
||||||
NodeKind::TYPE_EXTENSION_DEFINITION => TypeExtensionDefinitionNode::class,
|
NodeKind::OBJECT_TYPE_EXTENSION => ObjectTypeExtensionNode::class,
|
||||||
|
|
||||||
// Directive Definitions
|
// Directive Definitions
|
||||||
NodeKind::DIRECTIVE_DEFINITION => DirectiveDefinitionNode::class
|
NodeKind::DIRECTIVE_DEFINITION => DirectiveDefinitionNode::class
|
||||||
|
30
src/Language/AST/ObjectTypeExtensionNode.php
Normal file
30
src/Language/AST/ObjectTypeExtensionNode.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
namespace GraphQL\Language\AST;
|
||||||
|
|
||||||
|
class ObjectTypeExtensionNode extends Node implements TypeExtensionNode
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $kind = NodeKind::OBJECT_TYPE_EXTENSION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var NameNode
|
||||||
|
*/
|
||||||
|
public $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var NamedTypeNode[]
|
||||||
|
*/
|
||||||
|
public $interfaces = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var DirectiveNode[]
|
||||||
|
*/
|
||||||
|
public $directives;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var FieldDefinitionNode[]
|
||||||
|
*/
|
||||||
|
public $fields;
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GraphQL\Language\AST;
|
|
||||||
|
|
||||||
class TypeExtensionDefinitionNode extends Node implements TypeSystemDefinitionNode
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $kind = NodeKind::TYPE_EXTENSION_DEFINITION;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var ObjectTypeDefinitionNode
|
|
||||||
*/
|
|
||||||
public $definition;
|
|
||||||
}
|
|
10
src/Language/AST/TypeExtensionNode.php
Normal file
10
src/Language/AST/TypeExtensionNode.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
namespace GraphQL\Language\AST;
|
||||||
|
|
||||||
|
interface TypeExtensionNode extends TypeSystemDefinitionNode
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
export type TypeExtensionNode =
|
||||||
|
| ObjectTypeExtensionNode;
|
||||||
|
*/
|
||||||
|
}
|
@ -4,9 +4,10 @@ namespace GraphQL\Language\AST;
|
|||||||
interface TypeSystemDefinitionNode extends DefinitionNode
|
interface TypeSystemDefinitionNode extends DefinitionNode
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
export type TypeSystemDefinitionNode = SchemaDefinitionNode
|
export type TypeSystemDefinitionNode =
|
||||||
|
| SchemaDefinitionNode
|
||||||
| TypeDefinitionNode
|
| TypeDefinitionNode
|
||||||
| TypeExtensionDefinitionNode
|
| TypeExtensionNode
|
||||||
| DirectiveDefinitionNode
|
| DirectiveDefinitionNode
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
60
src/Language/DirectiveLocation.php
Normal file
60
src/Language/DirectiveLocation.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
namespace GraphQL\Language;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of available directive locations
|
||||||
|
*/
|
||||||
|
class DirectiveLocation
|
||||||
|
{
|
||||||
|
// Request Definitions
|
||||||
|
const QUERY = 'QUERY';
|
||||||
|
const MUTATION = 'MUTATION';
|
||||||
|
const SUBSCRIPTION = 'SUBSCRIPTION';
|
||||||
|
const FIELD = 'FIELD';
|
||||||
|
const FRAGMENT_DEFINITION = 'FRAGMENT_DEFINITION';
|
||||||
|
const FRAGMENT_SPREAD = 'FRAGMENT_SPREAD';
|
||||||
|
const INLINE_FRAGMENT = 'INLINE_FRAGMENT';
|
||||||
|
|
||||||
|
// Type System Definitions
|
||||||
|
const SCHEMA = 'SCHEMA';
|
||||||
|
const SCALAR = 'SCALAR';
|
||||||
|
const OBJECT = 'OBJECT';
|
||||||
|
const FIELD_DEFINITION = 'FIELD_DEFINITION';
|
||||||
|
const ARGUMENT_DEFINITION = 'ARGUMENT_DEFINITION';
|
||||||
|
const IFACE = 'INTERFACE';
|
||||||
|
const UNION = 'UNION';
|
||||||
|
const ENUM = 'ENUM';
|
||||||
|
const ENUM_VALUE = 'ENUM_VALUE';
|
||||||
|
const INPUT_OBJECT = 'INPUT_OBJECT';
|
||||||
|
const INPUT_FIELD_DEFINITION = 'INPUT_FIELD_DEFINITION';
|
||||||
|
|
||||||
|
private static $locations = [
|
||||||
|
self::QUERY => self::QUERY,
|
||||||
|
self::MUTATION => self::MUTATION,
|
||||||
|
self::SUBSCRIPTION => self::SUBSCRIPTION,
|
||||||
|
self::FIELD => self::FIELD,
|
||||||
|
self::FRAGMENT_DEFINITION => self::FRAGMENT_DEFINITION,
|
||||||
|
self::FRAGMENT_SPREAD => self::FRAGMENT_SPREAD,
|
||||||
|
self::INLINE_FRAGMENT => self::INLINE_FRAGMENT,
|
||||||
|
self::SCHEMA => self::SCHEMA,
|
||||||
|
self::SCALAR => self::SCALAR,
|
||||||
|
self::OBJECT => self::OBJECT,
|
||||||
|
self::FIELD_DEFINITION => self::FIELD_DEFINITION,
|
||||||
|
self::ARGUMENT_DEFINITION => self::ARGUMENT_DEFINITION,
|
||||||
|
self::IFACE => self::IFACE,
|
||||||
|
self::UNION => self::UNION,
|
||||||
|
self::ENUM => self::ENUM,
|
||||||
|
self::ENUM_VALUE => self::ENUM_VALUE,
|
||||||
|
self::INPUT_OBJECT => self::INPUT_OBJECT,
|
||||||
|
self::INPUT_FIELD_DEFINITION => self::INPUT_FIELD_DEFINITION,
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function has($name)
|
||||||
|
{
|
||||||
|
return isset(self::$locations[$name]);
|
||||||
|
}
|
||||||
|
}
|
@ -36,7 +36,8 @@ use GraphQL\Language\AST\ScalarTypeDefinitionNode;
|
|||||||
use GraphQL\Language\AST\SchemaDefinitionNode;
|
use GraphQL\Language\AST\SchemaDefinitionNode;
|
||||||
use GraphQL\Language\AST\SelectionSetNode;
|
use GraphQL\Language\AST\SelectionSetNode;
|
||||||
use GraphQL\Language\AST\StringValueNode;
|
use GraphQL\Language\AST\StringValueNode;
|
||||||
use GraphQL\Language\AST\TypeExtensionDefinitionNode;
|
use GraphQL\Language\AST\ObjectTypeExtensionNode;
|
||||||
|
use GraphQL\Language\AST\TypeExtensionNode;
|
||||||
use GraphQL\Language\AST\TypeSystemDefinitionNode;
|
use GraphQL\Language\AST\TypeSystemDefinitionNode;
|
||||||
use GraphQL\Language\AST\UnionTypeDefinitionNode;
|
use GraphQL\Language\AST\UnionTypeDefinitionNode;
|
||||||
use GraphQL\Language\AST\VariableNode;
|
use GraphQL\Language\AST\VariableNode;
|
||||||
@ -393,7 +394,7 @@ class Parser
|
|||||||
'operation' => $operation,
|
'operation' => $operation,
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'variableDefinitions' => $this->parseVariableDefinitions(),
|
'variableDefinitions' => $this->parseVariableDefinitions(),
|
||||||
'directives' => $this->parseDirectives(),
|
'directives' => $this->parseDirectives(false),
|
||||||
'selectionSet' => $this->parseSelectionSet(),
|
'selectionSet' => $this->parseSelectionSet(),
|
||||||
'loc' => $this->loc($start)
|
'loc' => $this->loc($start)
|
||||||
]);
|
]);
|
||||||
@ -494,6 +495,7 @@ class Parser
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return FieldNode
|
* @return FieldNode
|
||||||
|
* @throws SyntaxError
|
||||||
*/
|
*/
|
||||||
function parseField()
|
function parseField()
|
||||||
{
|
{
|
||||||
@ -511,20 +513,23 @@ class Parser
|
|||||||
return new FieldNode([
|
return new FieldNode([
|
||||||
'alias' => $alias,
|
'alias' => $alias,
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'arguments' => $this->parseArguments(),
|
'arguments' => $this->parseArguments(false),
|
||||||
'directives' => $this->parseDirectives(),
|
'directives' => $this->parseDirectives(false),
|
||||||
'selectionSet' => $this->peek(Token::BRACE_L) ? $this->parseSelectionSet() : null,
|
'selectionSet' => $this->peek(Token::BRACE_L) ? $this->parseSelectionSet() : null,
|
||||||
'loc' => $this->loc($start)
|
'loc' => $this->loc($start)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param bool $isConst
|
||||||
* @return ArgumentNode[]|NodeList
|
* @return ArgumentNode[]|NodeList
|
||||||
|
* @throws SyntaxError
|
||||||
*/
|
*/
|
||||||
function parseArguments()
|
function parseArguments($isConst)
|
||||||
{
|
{
|
||||||
|
$item = $isConst ? 'parseConstArgument' : 'parseArgument';
|
||||||
return $this->peek(Token::PAREN_L) ?
|
return $this->peek(Token::PAREN_L) ?
|
||||||
$this->many(Token::PAREN_L, [$this, 'parseArgument'], Token::PAREN_R) :
|
$this->many(Token::PAREN_L, [$this, $item], Token::PAREN_R) :
|
||||||
new NodeList([]);
|
new NodeList([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,6 +552,25 @@ class Parser
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ArgumentNode
|
||||||
|
* @throws SyntaxError
|
||||||
|
*/
|
||||||
|
function parseConstArgument()
|
||||||
|
{
|
||||||
|
$start = $this->lexer->token;
|
||||||
|
$name = $this->parseName();
|
||||||
|
|
||||||
|
$this->expect(Token::COLON);
|
||||||
|
$value = $this->parseConstValue();
|
||||||
|
|
||||||
|
return new ArgumentNode([
|
||||||
|
'name' => $name,
|
||||||
|
'value' => $value,
|
||||||
|
'loc' => $this->loc($start)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
// Implements the parsing rules in the Fragments section.
|
// Implements the parsing rules in the Fragments section.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -561,7 +585,7 @@ class Parser
|
|||||||
if ($this->peek(Token::NAME) && $this->lexer->token->value !== 'on') {
|
if ($this->peek(Token::NAME) && $this->lexer->token->value !== 'on') {
|
||||||
return new FragmentSpreadNode([
|
return new FragmentSpreadNode([
|
||||||
'name' => $this->parseFragmentName(),
|
'name' => $this->parseFragmentName(),
|
||||||
'directives' => $this->parseDirectives(),
|
'directives' => $this->parseDirectives(false),
|
||||||
'loc' => $this->loc($start)
|
'loc' => $this->loc($start)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -574,7 +598,7 @@ class Parser
|
|||||||
|
|
||||||
return new InlineFragmentNode([
|
return new InlineFragmentNode([
|
||||||
'typeCondition' => $typeCondition,
|
'typeCondition' => $typeCondition,
|
||||||
'directives' => $this->parseDirectives(),
|
'directives' => $this->parseDirectives(false),
|
||||||
'selectionSet' => $this->parseSelectionSet(),
|
'selectionSet' => $this->parseSelectionSet(),
|
||||||
'loc' => $this->loc($start)
|
'loc' => $this->loc($start)
|
||||||
]);
|
]);
|
||||||
@ -596,7 +620,7 @@ class Parser
|
|||||||
return new FragmentDefinitionNode([
|
return new FragmentDefinitionNode([
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'typeCondition' => $typeCondition,
|
'typeCondition' => $typeCondition,
|
||||||
'directives' => $this->parseDirectives(),
|
'directives' => $this->parseDirectives(false),
|
||||||
'selectionSet' => $this->parseSelectionSet(),
|
'selectionSet' => $this->parseSelectionSet(),
|
||||||
'loc' => $this->loc($start)
|
'loc' => $this->loc($start)
|
||||||
]);
|
]);
|
||||||
@ -775,28 +799,31 @@ class Parser
|
|||||||
// Implements the parsing rules in the Directives section.
|
// Implements the parsing rules in the Directives section.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param bool $isConst
|
||||||
* @return DirectiveNode[]|NodeList
|
* @return DirectiveNode[]|NodeList
|
||||||
|
* @throws SyntaxError
|
||||||
*/
|
*/
|
||||||
function parseDirectives()
|
function parseDirectives($isConst)
|
||||||
{
|
{
|
||||||
$directives = [];
|
$directives = [];
|
||||||
while ($this->peek(Token::AT)) {
|
while ($this->peek(Token::AT)) {
|
||||||
$directives[] = $this->parseDirective();
|
$directives[] = $this->parseDirective($isConst);
|
||||||
}
|
}
|
||||||
return new NodeList($directives);
|
return new NodeList($directives);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param bool $isConst
|
||||||
* @return DirectiveNode
|
* @return DirectiveNode
|
||||||
* @throws SyntaxError
|
* @throws SyntaxError
|
||||||
*/
|
*/
|
||||||
function parseDirective()
|
function parseDirective($isConst)
|
||||||
{
|
{
|
||||||
$start = $this->lexer->token;
|
$start = $this->lexer->token;
|
||||||
$this->expect(Token::AT);
|
$this->expect(Token::AT);
|
||||||
return new DirectiveNode([
|
return new DirectiveNode([
|
||||||
'name' => $this->parseName(),
|
'name' => $this->parseName(),
|
||||||
'arguments' => $this->parseArguments(),
|
'arguments' => $this->parseArguments($isConst),
|
||||||
'loc' => $this->loc($start)
|
'loc' => $this->loc($start)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -849,7 +876,7 @@ class Parser
|
|||||||
* TypeSystemDefinition :
|
* TypeSystemDefinition :
|
||||||
* - SchemaDefinition
|
* - SchemaDefinition
|
||||||
* - TypeDefinition
|
* - TypeDefinition
|
||||||
* - TypeExtensionDefinition
|
* - TypeExtension
|
||||||
* - DirectiveDefinition
|
* - DirectiveDefinition
|
||||||
*
|
*
|
||||||
* TypeDefinition :
|
* TypeDefinition :
|
||||||
@ -879,12 +906,12 @@ class Parser
|
|||||||
case 'union': return $this->parseUnionTypeDefinition();
|
case 'union': return $this->parseUnionTypeDefinition();
|
||||||
case 'enum': return $this->parseEnumTypeDefinition();
|
case 'enum': return $this->parseEnumTypeDefinition();
|
||||||
case 'input': return $this->parseInputObjectTypeDefinition();
|
case 'input': return $this->parseInputObjectTypeDefinition();
|
||||||
case 'extend': return $this->parseTypeExtensionDefinition();
|
case 'extend': return $this->parseTypeExtension();
|
||||||
case 'directive': return $this->parseDirectiveDefinition();
|
case 'directive': return $this->parseDirectiveDefinition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw $this->unexpected();
|
throw $this->unexpected($keywordToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -911,7 +938,7 @@ class Parser
|
|||||||
{
|
{
|
||||||
$start = $this->lexer->token;
|
$start = $this->lexer->token;
|
||||||
$this->expectKeyword('schema');
|
$this->expectKeyword('schema');
|
||||||
$directives = $this->parseDirectives();
|
$directives = $this->parseDirectives(true);
|
||||||
|
|
||||||
$operationTypes = $this->many(
|
$operationTypes = $this->many(
|
||||||
Token::BRACE_L,
|
Token::BRACE_L,
|
||||||
@ -953,7 +980,7 @@ class Parser
|
|||||||
$description = $this->parseDescription();
|
$description = $this->parseDescription();
|
||||||
$this->expectKeyword('scalar');
|
$this->expectKeyword('scalar');
|
||||||
$name = $this->parseName();
|
$name = $this->parseName();
|
||||||
$directives = $this->parseDirectives();
|
$directives = $this->parseDirectives(true);
|
||||||
|
|
||||||
return new ScalarTypeDefinitionNode([
|
return new ScalarTypeDefinitionNode([
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
@ -974,13 +1001,8 @@ class Parser
|
|||||||
$this->expectKeyword('type');
|
$this->expectKeyword('type');
|
||||||
$name = $this->parseName();
|
$name = $this->parseName();
|
||||||
$interfaces = $this->parseImplementsInterfaces();
|
$interfaces = $this->parseImplementsInterfaces();
|
||||||
$directives = $this->parseDirectives();
|
$directives = $this->parseDirectives(true);
|
||||||
|
$fields = $this->parseFieldDefinitions();
|
||||||
$fields = $this->any(
|
|
||||||
Token::BRACE_L,
|
|
||||||
[$this, 'parseFieldDefinition'],
|
|
||||||
Token::BRACE_R
|
|
||||||
);
|
|
||||||
|
|
||||||
return new ObjectTypeDefinitionNode([
|
return new ObjectTypeDefinitionNode([
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
@ -1007,6 +1029,19 @@ class Parser
|
|||||||
return $types;
|
return $types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return FieldDefinitionNode[]|NodeList
|
||||||
|
* @throws SyntaxError
|
||||||
|
*/
|
||||||
|
function parseFieldDefinitions()
|
||||||
|
{
|
||||||
|
return $this->many(
|
||||||
|
Token::BRACE_L,
|
||||||
|
[$this, 'parseFieldDefinition'],
|
||||||
|
Token::BRACE_R
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return FieldDefinitionNode
|
* @return FieldDefinitionNode
|
||||||
* @throws SyntaxError
|
* @throws SyntaxError
|
||||||
@ -1019,7 +1054,7 @@ class Parser
|
|||||||
$args = $this->parseArgumentDefs();
|
$args = $this->parseArgumentDefs();
|
||||||
$this->expect(Token::COLON);
|
$this->expect(Token::COLON);
|
||||||
$type = $this->parseTypeReference();
|
$type = $this->parseTypeReference();
|
||||||
$directives = $this->parseDirectives();
|
$directives = $this->parseDirectives(true);
|
||||||
|
|
||||||
return new FieldDefinitionNode([
|
return new FieldDefinitionNode([
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
@ -1057,7 +1092,7 @@ class Parser
|
|||||||
if ($this->skip(Token::EQUALS)) {
|
if ($this->skip(Token::EQUALS)) {
|
||||||
$defaultValue = $this->parseConstValue();
|
$defaultValue = $this->parseConstValue();
|
||||||
}
|
}
|
||||||
$directives = $this->parseDirectives();
|
$directives = $this->parseDirectives(true);
|
||||||
return new InputValueDefinitionNode([
|
return new InputValueDefinitionNode([
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'type' => $type,
|
'type' => $type,
|
||||||
@ -1078,12 +1113,8 @@ class Parser
|
|||||||
$description = $this->parseDescription();
|
$description = $this->parseDescription();
|
||||||
$this->expectKeyword('interface');
|
$this->expectKeyword('interface');
|
||||||
$name = $this->parseName();
|
$name = $this->parseName();
|
||||||
$directives = $this->parseDirectives();
|
$directives = $this->parseDirectives(true);
|
||||||
$fields = $this->any(
|
$fields = $this->parseFieldDefinitions();
|
||||||
Token::BRACE_L,
|
|
||||||
[$this, 'parseFieldDefinition'],
|
|
||||||
Token::BRACE_R
|
|
||||||
);
|
|
||||||
|
|
||||||
return new InterfaceTypeDefinitionNode([
|
return new InterfaceTypeDefinitionNode([
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
@ -1104,7 +1135,7 @@ class Parser
|
|||||||
$description = $this->parseDescription();
|
$description = $this->parseDescription();
|
||||||
$this->expectKeyword('union');
|
$this->expectKeyword('union');
|
||||||
$name = $this->parseName();
|
$name = $this->parseName();
|
||||||
$directives = $this->parseDirectives();
|
$directives = $this->parseDirectives(true);
|
||||||
$this->expect(Token::EQUALS);
|
$this->expect(Token::EQUALS);
|
||||||
$types = $this->parseUnionMembers();
|
$types = $this->parseUnionMembers();
|
||||||
|
|
||||||
@ -1146,7 +1177,7 @@ class Parser
|
|||||||
$description = $this->parseDescription();
|
$description = $this->parseDescription();
|
||||||
$this->expectKeyword('enum');
|
$this->expectKeyword('enum');
|
||||||
$name = $this->parseName();
|
$name = $this->parseName();
|
||||||
$directives = $this->parseDirectives();
|
$directives = $this->parseDirectives(true);
|
||||||
$values = $this->many(
|
$values = $this->many(
|
||||||
Token::BRACE_L,
|
Token::BRACE_L,
|
||||||
[$this, 'parseEnumValueDefinition'],
|
[$this, 'parseEnumValueDefinition'],
|
||||||
@ -1164,13 +1195,14 @@ class Parser
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return EnumValueDefinitionNode
|
* @return EnumValueDefinitionNode
|
||||||
|
* @throws SyntaxError
|
||||||
*/
|
*/
|
||||||
function parseEnumValueDefinition()
|
function parseEnumValueDefinition()
|
||||||
{
|
{
|
||||||
$start = $this->lexer->token;
|
$start = $this->lexer->token;
|
||||||
$description = $this->parseDescription();
|
$description = $this->parseDescription();
|
||||||
$name = $this->parseName();
|
$name = $this->parseName();
|
||||||
$directives = $this->parseDirectives();
|
$directives = $this->parseDirectives(true);
|
||||||
|
|
||||||
return new EnumValueDefinitionNode([
|
return new EnumValueDefinitionNode([
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
@ -1190,8 +1222,8 @@ class Parser
|
|||||||
$description = $this->parseDescription();
|
$description = $this->parseDescription();
|
||||||
$this->expectKeyword('input');
|
$this->expectKeyword('input');
|
||||||
$name = $this->parseName();
|
$name = $this->parseName();
|
||||||
$directives = $this->parseDirectives();
|
$directives = $this->parseDirectives(true);
|
||||||
$fields = $this->any(
|
$fields = $this->many(
|
||||||
Token::BRACE_L,
|
Token::BRACE_L,
|
||||||
[$this, 'parseInputValueDef'],
|
[$this, 'parseInputValueDef'],
|
||||||
Token::BRACE_R
|
Token::BRACE_R
|
||||||
@ -1207,17 +1239,51 @@ class Parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return TypeExtensionDefinitionNode
|
* @return TypeExtensionNode
|
||||||
* @throws SyntaxError
|
* @throws SyntaxError
|
||||||
*/
|
*/
|
||||||
function parseTypeExtensionDefinition()
|
function parseTypeExtension()
|
||||||
{
|
{
|
||||||
|
$keywordToken = $this->lexer->lookahead();
|
||||||
|
|
||||||
|
if ($keywordToken->kind === Token::NAME) {
|
||||||
|
switch ($keywordToken->value) {
|
||||||
|
case 'type':
|
||||||
|
return $this->parseObjectTypeExtension();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $this->unexpected($keywordToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ObjectTypeExtensionNode
|
||||||
|
* @throws SyntaxError
|
||||||
|
*/
|
||||||
|
function parseObjectTypeExtension() {
|
||||||
$start = $this->lexer->token;
|
$start = $this->lexer->token;
|
||||||
$this->expectKeyword('extend');
|
$this->expectKeyword('extend');
|
||||||
$definition = $this->parseObjectTypeDefinition();
|
$this->expectKeyword('type');
|
||||||
|
$name = $this->parseName();
|
||||||
|
$interfaces = $this->parseImplementsInterfaces();
|
||||||
|
$directives = $this->parseDirectives(true);
|
||||||
|
$fields = $this->peek(Token::BRACE_L)
|
||||||
|
? $this->parseFieldDefinitions()
|
||||||
|
: [];
|
||||||
|
|
||||||
return new TypeExtensionDefinitionNode([
|
if (
|
||||||
'definition' => $definition,
|
count($interfaces) === 0 &&
|
||||||
|
count($directives) === 0 &&
|
||||||
|
count($fields) === 0
|
||||||
|
) {
|
||||||
|
throw $this->unexpected();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ObjectTypeExtensionNode([
|
||||||
|
'name' => $name,
|
||||||
|
'interfaces' => $interfaces,
|
||||||
|
'directives' => $directives,
|
||||||
|
'fields' => $fields,
|
||||||
'loc' => $this->loc($start)
|
'loc' => $this->loc($start)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -1251,6 +1317,7 @@ class Parser
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return NameNode[]
|
* @return NameNode[]
|
||||||
|
* @throws SyntaxError
|
||||||
*/
|
*/
|
||||||
function parseDirectiveLocations()
|
function parseDirectiveLocations()
|
||||||
{
|
{
|
||||||
@ -1258,8 +1325,23 @@ class Parser
|
|||||||
$this->skip(Token::PIPE);
|
$this->skip(Token::PIPE);
|
||||||
$locations = [];
|
$locations = [];
|
||||||
do {
|
do {
|
||||||
$locations[] = $this->parseName();
|
$locations[] = $this->parseDirectiveLocation();
|
||||||
} while ($this->skip(Token::PIPE));
|
} while ($this->skip(Token::PIPE));
|
||||||
return $locations;
|
return $locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return NameNode
|
||||||
|
* @throws SyntaxError
|
||||||
|
*/
|
||||||
|
function parseDirectiveLocation()
|
||||||
|
{
|
||||||
|
$start = $this->lexer->token;
|
||||||
|
$name = $this->parseName();
|
||||||
|
if (DirectiveLocation::has($name->value)) {
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $this->unexpected($start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ use GraphQL\Language\AST\ScalarTypeDefinitionNode;
|
|||||||
use GraphQL\Language\AST\SchemaDefinitionNode;
|
use GraphQL\Language\AST\SchemaDefinitionNode;
|
||||||
use GraphQL\Language\AST\SelectionSetNode;
|
use GraphQL\Language\AST\SelectionSetNode;
|
||||||
use GraphQL\Language\AST\StringValueNode;
|
use GraphQL\Language\AST\StringValueNode;
|
||||||
use GraphQL\Language\AST\TypeExtensionDefinitionNode;
|
use GraphQL\Language\AST\ObjectTypeExtensionNode;
|
||||||
use GraphQL\Language\AST\UnionTypeDefinitionNode;
|
use GraphQL\Language\AST\UnionTypeDefinitionNode;
|
||||||
use GraphQL\Language\AST\VariableDefinitionNode;
|
use GraphQL\Language\AST\VariableDefinitionNode;
|
||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
@ -278,8 +278,14 @@ class Printer
|
|||||||
], ' ')
|
], ' ')
|
||||||
], "\n");
|
], "\n");
|
||||||
},
|
},
|
||||||
NodeKind::TYPE_EXTENSION_DEFINITION => function(TypeExtensionDefinitionNode $def) {
|
NodeKind::OBJECT_TYPE_EXTENSION => function(ObjectTypeExtensionNode $def) {
|
||||||
return "extend {$def->definition}";
|
return $this->join([
|
||||||
|
'extend type',
|
||||||
|
$def->name,
|
||||||
|
$this->wrap('implements ', $this->join($def->interfaces, ', ')),
|
||||||
|
$this->join($def->directives, ' '),
|
||||||
|
$this->block($def->fields),
|
||||||
|
], ' ');
|
||||||
},
|
},
|
||||||
NodeKind::DIRECTIVE_DEFINITION => function(DirectiveDefinitionNode $def) {
|
NodeKind::DIRECTIVE_DEFINITION => function(DirectiveDefinitionNode $def) {
|
||||||
return $this->join([
|
return $this->join([
|
||||||
@ -309,7 +315,7 @@ class Printer
|
|||||||
{
|
{
|
||||||
return ($array && $this->length($array))
|
return ($array && $this->length($array))
|
||||||
? "{\n" . $this->indent($this->join($array, "\n")) . "\n}"
|
? "{\n" . $this->indent($this->join($array, "\n")) . "\n}"
|
||||||
: '{}';
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function indent($maybeString)
|
public function indent($maybeString)
|
||||||
|
@ -142,7 +142,7 @@ class Visitor
|
|||||||
NodeKind::ENUM_TYPE_DEFINITION => ['description', 'name', 'directives', 'values'],
|
NodeKind::ENUM_TYPE_DEFINITION => ['description', 'name', 'directives', 'values'],
|
||||||
NodeKind::ENUM_VALUE_DEFINITION => ['description', 'name', 'directives'],
|
NodeKind::ENUM_VALUE_DEFINITION => ['description', 'name', 'directives'],
|
||||||
NodeKind::INPUT_OBJECT_TYPE_DEFINITION => ['description', 'name', 'directives', 'fields'],
|
NodeKind::INPUT_OBJECT_TYPE_DEFINITION => ['description', 'name', 'directives', 'fields'],
|
||||||
NodeKind::TYPE_EXTENSION_DEFINITION => [ 'definition' ],
|
NodeKind::OBJECT_TYPE_EXTENSION => [ 'name', 'interfaces', 'directives', 'fields' ],
|
||||||
NodeKind::DIRECTIVE_DEFINITION => ['description', 'name', 'arguments', 'locations']
|
NodeKind::DIRECTIVE_DEFINITION => ['description', 'name', 'arguments', 'locations']
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
namespace GraphQL\Type\Definition;
|
namespace GraphQL\Type\Definition;
|
||||||
|
|
||||||
use GraphQL\Language\AST\DirectiveDefinitionNode;
|
use GraphQL\Language\AST\DirectiveDefinitionNode;
|
||||||
|
use GraphQL\Language\DirectiveLocation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Directive
|
* Class Directive
|
||||||
@ -18,35 +19,6 @@ class Directive
|
|||||||
|
|
||||||
// Schema Definitions
|
// Schema Definitions
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
* @deprecated as of 8.0 (use DirectiveLocation constants directly)
|
|
||||||
*/
|
|
||||||
public static $directiveLocations = [
|
|
||||||
// Operations:
|
|
||||||
DirectiveLocation::QUERY => DirectiveLocation::QUERY,
|
|
||||||
DirectiveLocation::MUTATION => DirectiveLocation::MUTATION,
|
|
||||||
DirectiveLocation::SUBSCRIPTION => DirectiveLocation::SUBSCRIPTION,
|
|
||||||
DirectiveLocation::FIELD => DirectiveLocation::FIELD,
|
|
||||||
DirectiveLocation::FRAGMENT_DEFINITION => DirectiveLocation::FRAGMENT_DEFINITION,
|
|
||||||
DirectiveLocation::FRAGMENT_SPREAD => DirectiveLocation::FRAGMENT_SPREAD,
|
|
||||||
DirectiveLocation::INLINE_FRAGMENT => DirectiveLocation::INLINE_FRAGMENT,
|
|
||||||
|
|
||||||
// Schema Definitions
|
|
||||||
DirectiveLocation::SCHEMA => DirectiveLocation::SCHEMA,
|
|
||||||
DirectiveLocation::SCALAR => DirectiveLocation::SCALAR,
|
|
||||||
DirectiveLocation::OBJECT => DirectiveLocation::OBJECT,
|
|
||||||
DirectiveLocation::FIELD_DEFINITION => DirectiveLocation::FIELD_DEFINITION,
|
|
||||||
DirectiveLocation::ARGUMENT_DEFINITION => DirectiveLocation::ARGUMENT_DEFINITION,
|
|
||||||
DirectiveLocation::IFACE => DirectiveLocation::IFACE,
|
|
||||||
DirectiveLocation::UNION => DirectiveLocation::UNION,
|
|
||||||
DirectiveLocation::ENUM => DirectiveLocation::ENUM,
|
|
||||||
DirectiveLocation::ENUM_VALUE => DirectiveLocation::ENUM_VALUE,
|
|
||||||
DirectiveLocation::INPUT_OBJECT => DirectiveLocation::INPUT_OBJECT,
|
|
||||||
DirectiveLocation::INPUT_FIELD_DEFINITION => DirectiveLocation::INPUT_FIELD_DEFINITION
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Directive
|
* @return Directive
|
||||||
*/
|
*/
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GraphQL\Type\Definition;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of available directive locations
|
|
||||||
*/
|
|
||||||
class DirectiveLocation
|
|
||||||
{
|
|
||||||
const IFACE = 'INTERFACE';
|
|
||||||
const SUBSCRIPTION = 'SUBSCRIPTION';
|
|
||||||
const FRAGMENT_SPREAD = 'FRAGMENT_SPREAD';
|
|
||||||
const QUERY = 'QUERY';
|
|
||||||
const MUTATION = 'MUTATION';
|
|
||||||
const FRAGMENT_DEFINITION = 'FRAGMENT_DEFINITION';
|
|
||||||
const INPUT_OBJECT = 'INPUT_OBJECT';
|
|
||||||
const INLINE_FRAGMENT = 'INLINE_FRAGMENT';
|
|
||||||
const UNION = 'UNION';
|
|
||||||
const SCALAR = 'SCALAR';
|
|
||||||
const FIELD_DEFINITION = 'FIELD_DEFINITION';
|
|
||||||
const ARGUMENT_DEFINITION = 'ARGUMENT_DEFINITION';
|
|
||||||
const ENUM = 'ENUM';
|
|
||||||
const OBJECT = 'OBJECT';
|
|
||||||
const ENUM_VALUE = 'ENUM_VALUE';
|
|
||||||
const FIELD = 'FIELD';
|
|
||||||
const SCHEMA = 'SCHEMA';
|
|
||||||
const INPUT_FIELD_DEFINITION = 'INPUT_FIELD_DEFINITION';
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ namespace GraphQL\Type\Definition;
|
|||||||
|
|
||||||
use GraphQL\Error\InvariantViolation;
|
use GraphQL\Error\InvariantViolation;
|
||||||
use GraphQL\Language\AST\ObjectTypeDefinitionNode;
|
use GraphQL\Language\AST\ObjectTypeDefinitionNode;
|
||||||
use GraphQL\Language\AST\TypeExtensionDefinitionNode;
|
use GraphQL\Language\AST\ObjectTypeExtensionNode;
|
||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
|
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ class ObjectType extends Type implements OutputType, CompositeType
|
|||||||
public $astNode;
|
public $astNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var TypeExtensionDefinitionNode[]
|
* @var ObjectTypeExtensionNode[]
|
||||||
*/
|
*/
|
||||||
public $extensionASTNodes;
|
public $extensionASTNodes;
|
||||||
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace GraphQL\Type;
|
namespace GraphQL\Type;
|
||||||
|
|
||||||
|
|
||||||
use GraphQL\Language\Printer;
|
use GraphQL\Language\Printer;
|
||||||
use GraphQL\Type\Definition\Directive;
|
use GraphQL\Type\Definition\Directive;
|
||||||
use GraphQL\Type\Definition\DirectiveLocation;
|
use GraphQL\Language\DirectiveLocation;
|
||||||
use GraphQL\Type\Definition\EnumType;
|
use GraphQL\Type\Definition\EnumType;
|
||||||
use GraphQL\Type\Definition\FieldArgument;
|
use GraphQL\Type\Definition\FieldArgument;
|
||||||
use GraphQL\Type\Definition\FieldDefinition;
|
use GraphQL\Type\Definition\FieldDefinition;
|
||||||
@ -602,7 +601,7 @@ EOD;
|
|||||||
],
|
],
|
||||||
'type' => [
|
'type' => [
|
||||||
'type' => Type::nonNull(self::_type()),
|
'type' => Type::nonNull(self::_type()),
|
||||||
'resolve' => function ($field) {
|
'resolve' => function (FieldDefinition $field) {
|
||||||
return $field->getType();
|
return $field->getType();
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -30,7 +30,6 @@ use GraphQL\Type\Definition\NonNull;
|
|||||||
use GraphQL\Type\Definition\ObjectType;
|
use GraphQL\Type\Definition\ObjectType;
|
||||||
use GraphQL\Type\Definition\Type;
|
use GraphQL\Type\Definition\Type;
|
||||||
use GraphQL\Type\Definition\UnionType;
|
use GraphQL\Type\Definition\UnionType;
|
||||||
use GraphQL\Type\Introspection;
|
|
||||||
|
|
||||||
class ASTDefinitionBuilder
|
class ASTDefinitionBuilder
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,7 @@ use GraphQL\Validator\Rules\AbstractValidationRule;
|
|||||||
use GraphQL\Validator\Rules\ArgumentsOfCorrectType;
|
use GraphQL\Validator\Rules\ArgumentsOfCorrectType;
|
||||||
use GraphQL\Validator\Rules\DefaultValuesOfCorrectType;
|
use GraphQL\Validator\Rules\DefaultValuesOfCorrectType;
|
||||||
use GraphQL\Validator\Rules\DisableIntrospection;
|
use GraphQL\Validator\Rules\DisableIntrospection;
|
||||||
|
use GraphQL\Validator\Rules\ExecutableDefinitions;
|
||||||
use GraphQL\Validator\Rules\FieldsOnCorrectType;
|
use GraphQL\Validator\Rules\FieldsOnCorrectType;
|
||||||
use GraphQL\Validator\Rules\FragmentsOnCompositeTypes;
|
use GraphQL\Validator\Rules\FragmentsOnCompositeTypes;
|
||||||
use GraphQL\Validator\Rules\KnownArgumentNames;
|
use GraphQL\Validator\Rules\KnownArgumentNames;
|
||||||
@ -122,6 +123,7 @@ class DocumentValidator
|
|||||||
{
|
{
|
||||||
if (null === self::$defaultRules) {
|
if (null === self::$defaultRules) {
|
||||||
self::$defaultRules = [
|
self::$defaultRules = [
|
||||||
|
ExecutableDefinitions::class => new ExecutableDefinitions(),
|
||||||
UniqueOperationNames::class => new UniqueOperationNames(),
|
UniqueOperationNames::class => new UniqueOperationNames(),
|
||||||
LoneAnonymousOperation::class => new LoneAnonymousOperation(),
|
LoneAnonymousOperation::class => new LoneAnonymousOperation(),
|
||||||
KnownTypeNames::class => new KnownTypeNames(),
|
KnownTypeNames::class => new KnownTypeNames(),
|
||||||
|
47
src/Validator/Rules/ExecutableDefinitions.php
Normal file
47
src/Validator/Rules/ExecutableDefinitions.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
namespace GraphQL\Validator\Rules;
|
||||||
|
|
||||||
|
use GraphQL\Error\Error;
|
||||||
|
use GraphQL\Language\AST\DocumentNode;
|
||||||
|
use GraphQL\Language\AST\FragmentDefinitionNode;
|
||||||
|
use GraphQL\Language\AST\Node;
|
||||||
|
use GraphQL\Language\AST\NodeKind;
|
||||||
|
use GraphQL\Language\AST\OperationDefinitionNode;
|
||||||
|
use GraphQL\Language\Visitor;
|
||||||
|
use GraphQL\Validator\ValidationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executable definitions
|
||||||
|
*
|
||||||
|
* A GraphQL document is only valid for execution if all definitions are either
|
||||||
|
* operation or fragment definitions.
|
||||||
|
*/
|
||||||
|
class ExecutableDefinitions extends AbstractValidationRule
|
||||||
|
{
|
||||||
|
static function nonExecutableDefinitionMessage($defName)
|
||||||
|
{
|
||||||
|
return "The \"$defName\" definition is not executable.";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVisitor(ValidationContext $context)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
NodeKind::DOCUMENT => function (DocumentNode $node) use ($context) {
|
||||||
|
/** @var Node $definition */
|
||||||
|
foreach ($node->definitions as $definition) {
|
||||||
|
if (
|
||||||
|
!$definition instanceof OperationDefinitionNode &&
|
||||||
|
!$definition instanceof FragmentDefinitionNode
|
||||||
|
) {
|
||||||
|
$context->reportError(new Error(
|
||||||
|
self::nonExecutableDefinitionMessage($definition->name->value),
|
||||||
|
[$definition->name]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Visitor::skipNode();
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -5,8 +5,8 @@ use GraphQL\Error\Error;
|
|||||||
use GraphQL\Language\AST\DirectiveNode;
|
use GraphQL\Language\AST\DirectiveNode;
|
||||||
use GraphQL\Language\AST\InputObjectTypeDefinitionNode;
|
use GraphQL\Language\AST\InputObjectTypeDefinitionNode;
|
||||||
use GraphQL\Language\AST\NodeKind;
|
use GraphQL\Language\AST\NodeKind;
|
||||||
|
use GraphQL\Language\DirectiveLocation;
|
||||||
use GraphQL\Validator\ValidationContext;
|
use GraphQL\Validator\ValidationContext;
|
||||||
use GraphQL\Type\Definition\DirectiveLocation;
|
|
||||||
|
|
||||||
class KnownDirectives extends AbstractValidationRule
|
class KnownDirectives extends AbstractValidationRule
|
||||||
{
|
{
|
||||||
@ -37,7 +37,7 @@ class KnownDirectives extends AbstractValidationRule
|
|||||||
self::unknownDirectiveMessage($node->name->value),
|
self::unknownDirectiveMessage($node->name->value),
|
||||||
[$node]
|
[$node]
|
||||||
));
|
));
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
$candidateLocation = $this->getDirectiveLocationForASTPath($ancestors);
|
$candidateLocation = $this->getDirectiveLocationForASTPath($ancestors);
|
||||||
|
|
||||||
@ -73,7 +73,8 @@ class KnownDirectives extends AbstractValidationRule
|
|||||||
case NodeKind::FRAGMENT_DEFINITION: return DirectiveLocation::FRAGMENT_DEFINITION;
|
case NodeKind::FRAGMENT_DEFINITION: return DirectiveLocation::FRAGMENT_DEFINITION;
|
||||||
case NodeKind::SCHEMA_DEFINITION: return DirectiveLocation::SCHEMA;
|
case NodeKind::SCHEMA_DEFINITION: return DirectiveLocation::SCHEMA;
|
||||||
case NodeKind::SCALAR_TYPE_DEFINITION: return DirectiveLocation::SCALAR;
|
case NodeKind::SCALAR_TYPE_DEFINITION: return DirectiveLocation::SCALAR;
|
||||||
case NodeKind::OBJECT_TYPE_DEFINITION: return DirectiveLocation::OBJECT;
|
case NodeKind::OBJECT_TYPE_DEFINITION:
|
||||||
|
case NodeKind::OBJECT_TYPE_EXTENSION: return DirectiveLocation::OBJECT;
|
||||||
case NodeKind::FIELD_DEFINITION: return DirectiveLocation::FIELD_DEFINITION;
|
case NodeKind::FIELD_DEFINITION: return DirectiveLocation::FIELD_DEFINITION;
|
||||||
case NodeKind::INTERFACE_TYPE_DEFINITION: return DirectiveLocation::IFACE;
|
case NodeKind::INTERFACE_TYPE_DEFINITION: return DirectiveLocation::IFACE;
|
||||||
case NodeKind::UNION_TYPE_DEFINITION: return DirectiveLocation::UNION;
|
case NodeKind::UNION_TYPE_DEFINITION: return DirectiveLocation::UNION;
|
||||||
|
@ -965,14 +965,14 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @it fails to execute a query containing a type definition
|
* @it executes ignoring invalid non-executable definitions
|
||||||
*/
|
*/
|
||||||
public function testFailsToExecuteQueryContainingTypeDefinition()
|
public function testExecutesIgnoringInvalidNonExecutableDefinitions()
|
||||||
{
|
{
|
||||||
$query = Parser::parse('
|
$query = Parser::parse('
|
||||||
{ foo }
|
{ foo }
|
||||||
|
|
||||||
type Query { foo: String }
|
type Query { bar: String }
|
||||||
');
|
');
|
||||||
|
|
||||||
$schema = new Schema([
|
$schema = new Schema([
|
||||||
@ -988,12 +988,9 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
|
|||||||
$result = Executor::execute($schema, $query);
|
$result = Executor::execute($schema, $query);
|
||||||
|
|
||||||
$expected = [
|
$expected = [
|
||||||
'errors' => [
|
'data' => [
|
||||||
[
|
'foo' => null,
|
||||||
'message' => 'GraphQL cannot execute a request containing a ObjectTypeDefinition.',
|
],
|
||||||
'locations' => [['line' => 4, 'column' => 7]],
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->assertArraySubset($expected, $result->toArray());
|
$this->assertArraySubset($expected, $result->toArray());
|
||||||
|
@ -150,21 +150,16 @@ extend type Hello {
|
|||||||
'kind' => NodeKind::DOCUMENT,
|
'kind' => NodeKind::DOCUMENT,
|
||||||
'definitions' => [
|
'definitions' => [
|
||||||
[
|
[
|
||||||
'kind' => NodeKind::TYPE_EXTENSION_DEFINITION,
|
'kind' => NodeKind::OBJECT_TYPE_EXTENSION,
|
||||||
'definition' => [
|
'name' => $this->nameNode('Hello', $loc(13, 18)),
|
||||||
'kind' => NodeKind::OBJECT_TYPE_DEFINITION,
|
'interfaces' => [],
|
||||||
'name' => $this->nameNode('Hello', $loc(13, 18)),
|
'directives' => [],
|
||||||
'interfaces' => [],
|
'fields' => [
|
||||||
'directives' => [],
|
$this->fieldNode(
|
||||||
'fields' => [
|
$this->nameNode('world', $loc(23, 28)),
|
||||||
$this->fieldNode(
|
$this->typeNode('String', $loc(30, 36)),
|
||||||
$this->nameNode('world', $loc(23, 28)),
|
$loc(23, 36)
|
||||||
$this->typeNode('String', $loc(30, 36)),
|
)
|
||||||
$loc(23, 36)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
'loc' => $loc(8, 38),
|
|
||||||
'description' => null
|
|
||||||
],
|
],
|
||||||
'loc' => $loc(1, 38)
|
'loc' => $loc(1, 38)
|
||||||
]
|
]
|
||||||
@ -174,16 +169,59 @@ extend type Hello {
|
|||||||
$this->assertEquals($expected, TestUtils::nodeToArray($doc));
|
$this->assertEquals($expected, TestUtils::nodeToArray($doc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it Extension without fields
|
||||||
|
*/
|
||||||
|
public function testExtensionWithoutFields()
|
||||||
|
{
|
||||||
|
$body = 'extend type Hello implements Greeting';
|
||||||
|
$doc = Parser::parse($body);
|
||||||
|
$loc = function($start, $end) {
|
||||||
|
return TestUtils::locArray($start, $end);
|
||||||
|
};
|
||||||
|
$expected = [
|
||||||
|
'kind' => NodeKind::DOCUMENT,
|
||||||
|
'definitions' => [
|
||||||
|
[
|
||||||
|
'kind' => NodeKind::OBJECT_TYPE_EXTENSION,
|
||||||
|
'name' => $this->nameNode('Hello', $loc(12, 17)),
|
||||||
|
'interfaces' => [
|
||||||
|
$this->typeNode('Greeting', $loc(29, 37)),
|
||||||
|
],
|
||||||
|
'directives' => [],
|
||||||
|
'fields' => [],
|
||||||
|
'loc' => $loc(0, 37)
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'loc' => $loc(0, 37)
|
||||||
|
];
|
||||||
|
$this->assertEquals($expected, TestUtils::nodeToArray($doc));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @it Extension do not include descriptions
|
* @it Extension do not include descriptions
|
||||||
* @expectedException \GraphQL\Error\SyntaxError
|
* @expectedException \GraphQL\Error\SyntaxError
|
||||||
* @expectedExceptionMessage Syntax Error GraphQL (2:1)
|
* @expectedExceptionMessage Syntax Error GraphQL (3:7)
|
||||||
*/
|
*/
|
||||||
public function testExtensionDoNotIncludeDescriptions() {
|
public function testExtensionDoNotIncludeDescriptions() {
|
||||||
$body = '
|
$body = '
|
||||||
"Description"
|
"Description"
|
||||||
extend type Hello {
|
extend type Hello {
|
||||||
world: String
|
world: String
|
||||||
|
}';
|
||||||
|
Parser::parse($body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it Extension do not include descriptions
|
||||||
|
* @expectedException \GraphQL\Error\SyntaxError
|
||||||
|
* @expectedExceptionMessage Syntax Error GraphQL (2:14)
|
||||||
|
*/
|
||||||
|
public function testExtensionDoNotIncludeDescriptions2() {
|
||||||
|
$body = '
|
||||||
|
extend "Description" type Hello {
|
||||||
|
world: String
|
||||||
|
}
|
||||||
}';
|
}';
|
||||||
Parser::parse($body);
|
Parser::parse($body);
|
||||||
}
|
}
|
||||||
@ -236,7 +274,7 @@ type Hello {
|
|||||||
*/
|
*/
|
||||||
public function testSimpleTypeInheritingInterface()
|
public function testSimpleTypeInheritingInterface()
|
||||||
{
|
{
|
||||||
$body = 'type Hello implements World { }';
|
$body = 'type Hello implements World { field: String }';
|
||||||
$loc = function($start, $end) { return TestUtils::locArray($start, $end); };
|
$loc = function($start, $end) { return TestUtils::locArray($start, $end); };
|
||||||
$doc = Parser::parse($body);
|
$doc = Parser::parse($body);
|
||||||
|
|
||||||
@ -250,12 +288,18 @@ type Hello {
|
|||||||
$this->typeNode('World', $loc(22, 27))
|
$this->typeNode('World', $loc(22, 27))
|
||||||
],
|
],
|
||||||
'directives' => [],
|
'directives' => [],
|
||||||
'fields' => [],
|
'fields' => [
|
||||||
'loc' => $loc(0,31),
|
$this->fieldNode(
|
||||||
|
$this->nameNode('field', $loc(30, 35)),
|
||||||
|
$this->typeNode('String', $loc(37, 43)),
|
||||||
|
$loc(30, 43)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
'loc' => $loc(0, 45),
|
||||||
'description' => null
|
'description' => null
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'loc' => $loc(0,31)
|
'loc' => $loc(0, 45)
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->assertEquals($expected, TestUtils::nodeToArray($doc));
|
$this->assertEquals($expected, TestUtils::nodeToArray($doc));
|
||||||
@ -266,7 +310,7 @@ type Hello {
|
|||||||
*/
|
*/
|
||||||
public function testSimpleTypeInheritingMultipleInterfaces()
|
public function testSimpleTypeInheritingMultipleInterfaces()
|
||||||
{
|
{
|
||||||
$body = 'type Hello implements Wo, rld { }';
|
$body = 'type Hello implements Wo, rld { field: String }';
|
||||||
$loc = function($start, $end) {return TestUtils::locArray($start, $end);};
|
$loc = function($start, $end) {return TestUtils::locArray($start, $end);};
|
||||||
$doc = Parser::parse($body);
|
$doc = Parser::parse($body);
|
||||||
|
|
||||||
@ -281,12 +325,18 @@ type Hello {
|
|||||||
$this->typeNode('rld', $loc(26,29))
|
$this->typeNode('rld', $loc(26,29))
|
||||||
],
|
],
|
||||||
'directives' => [],
|
'directives' => [],
|
||||||
'fields' => [],
|
'fields' => [
|
||||||
'loc' => $loc(0, 33),
|
$this->fieldNode(
|
||||||
|
$this->nameNode('field', $loc(32, 37)),
|
||||||
|
$this->typeNode('String', $loc(39, 45)),
|
||||||
|
$loc(32, 45)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
'loc' => $loc(0, 47),
|
||||||
'description' => null
|
'description' => null
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'loc' => $loc(0, 33)
|
'loc' => $loc(0, 47)
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->assertEquals($expected, TestUtils::nodeToArray($doc));
|
$this->assertEquals($expected, TestUtils::nodeToArray($doc));
|
||||||
@ -754,6 +804,7 @@ input Hello {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @it Simple input object with args should fail
|
* @it Simple input object with args should fail
|
||||||
|
* @expectedException \GraphQL\Error\SyntaxError
|
||||||
*/
|
*/
|
||||||
public function testSimpleInputObjectWithArgsShouldFail()
|
public function testSimpleInputObjectWithArgsShouldFail()
|
||||||
{
|
{
|
||||||
@ -761,7 +812,19 @@ input Hello {
|
|||||||
input Hello {
|
input Hello {
|
||||||
world(foo: Int): String
|
world(foo: Int): String
|
||||||
}';
|
}';
|
||||||
$this->setExpectedException('GraphQL\Error\SyntaxError');
|
Parser::parse($body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it Directive with incorrect locations
|
||||||
|
* @expectedException \GraphQL\Error\SyntaxError
|
||||||
|
* @expectedExceptionMessage Syntax Error GraphQL (2:33) Unexpected Name "INCORRECT_LOCATION"
|
||||||
|
*/
|
||||||
|
public function testDirectiveWithIncorrectLocationShouldFail()
|
||||||
|
{
|
||||||
|
$body = '
|
||||||
|
directive @foo on FIELD | INCORRECT_LOCATION
|
||||||
|
';
|
||||||
Parser::parse($body);
|
Parser::parse($body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,9 +116,7 @@ extend type Foo {
|
|||||||
seven(argument: [String]): Type
|
seven(argument: [String]): Type
|
||||||
}
|
}
|
||||||
|
|
||||||
extend type Foo @onType {}
|
extend type Foo @onType
|
||||||
|
|
||||||
type NoFields {}
|
|
||||||
|
|
||||||
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
|
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
|
||||||
|
|
||||||
|
@ -68,9 +68,7 @@ extend type Foo {
|
|||||||
seven(argument: [String]): Type
|
seven(argument: [String]): Type
|
||||||
}
|
}
|
||||||
|
|
||||||
extend type Foo @onType {}
|
extend type Foo @onType
|
||||||
|
|
||||||
type NoFields {}
|
|
||||||
|
|
||||||
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
|
directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
|
||||||
|
|
||||||
|
@ -1025,7 +1025,9 @@ schema {
|
|||||||
query: Hello
|
query: Hello
|
||||||
}
|
}
|
||||||
|
|
||||||
type Hello implements Bar { }
|
type Hello implements Bar {
|
||||||
|
field: String
|
||||||
|
}
|
||||||
';
|
';
|
||||||
$doc = Parser::parse($body);
|
$doc = Parser::parse($body);
|
||||||
$schema = BuildSchema::buildAST($doc);
|
$schema = BuildSchema::buildAST($doc);
|
||||||
|
79
tests/Validator/ExecutableDefinitionsTest.php
Normal file
79
tests/Validator/ExecutableDefinitionsTest.php
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
namespace GraphQL\Tests\Validator;
|
||||||
|
|
||||||
|
use GraphQL\Error\FormattedError;
|
||||||
|
use GraphQL\Language\SourceLocation;
|
||||||
|
use GraphQL\Validator\Rules\ExecutableDefinitions;
|
||||||
|
use GraphQL\Validator\Rules\KnownDirectives;
|
||||||
|
|
||||||
|
class ExecutableDefinitionsTest extends TestCase
|
||||||
|
{
|
||||||
|
// Validate: Executable definitions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it with only operation
|
||||||
|
*/
|
||||||
|
public function testWithOnlyOperation()
|
||||||
|
{
|
||||||
|
$this->expectPassesRule(new ExecutableDefinitions, '
|
||||||
|
query Foo {
|
||||||
|
dog {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it with operation and fragment
|
||||||
|
*/
|
||||||
|
public function testWithOperationAndFragment()
|
||||||
|
{
|
||||||
|
$this->expectPassesRule(new ExecutableDefinitions, '
|
||||||
|
query Foo {
|
||||||
|
dog {
|
||||||
|
name
|
||||||
|
...Frag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment Frag on Dog {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it with typeDefinition
|
||||||
|
*/
|
||||||
|
public function testWithTypeDefinition()
|
||||||
|
{
|
||||||
|
$this->expectFailsRule(new ExecutableDefinitions, '
|
||||||
|
query Foo {
|
||||||
|
dog {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Cow {
|
||||||
|
name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
extend type Dog {
|
||||||
|
color: String
|
||||||
|
}
|
||||||
|
',
|
||||||
|
[
|
||||||
|
$this->nonExecutableDefinition('Cow', 8, 12),
|
||||||
|
$this->nonExecutableDefinition('Dog', 12, 19),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function nonExecutableDefinition($defName, $line, $column)
|
||||||
|
{
|
||||||
|
return FormattedError::create(
|
||||||
|
ExecutableDefinitions::nonExecutableDefinitionMessage($defName),
|
||||||
|
[ new SourceLocation($line, $column) ]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -136,6 +136,8 @@ class KnownDirectivesTest extends TestCase
|
|||||||
myField(myArg: Int @onArgumentDefinition): String @onFieldDefinition
|
myField(myArg: Int @onArgumentDefinition): String @onFieldDefinition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extend type MyObj @onObject
|
||||||
|
|
||||||
scalar MyScalar @onScalar
|
scalar MyScalar @onScalar
|
||||||
|
|
||||||
interface MyInterface @onInterface {
|
interface MyInterface @onInterface {
|
||||||
|
@ -3,6 +3,7 @@ namespace GraphQL\Tests\Validator;
|
|||||||
|
|
||||||
use GraphQL\Language\Parser;
|
use GraphQL\Language\Parser;
|
||||||
use GraphQL\Type\Schema;
|
use GraphQL\Type\Schema;
|
||||||
|
use GraphQL\Type\Definition\CustomScalarType;
|
||||||
use GraphQL\Type\Definition\Directive;
|
use GraphQL\Type\Definition\Directive;
|
||||||
use GraphQL\Type\Definition\EnumType;
|
use GraphQL\Type\Definition\EnumType;
|
||||||
use GraphQL\Type\Definition\InputObjectType;
|
use GraphQL\Type\Definition\InputObjectType;
|
||||||
@ -259,6 +260,24 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$invalidScalar = new CustomScalarType([
|
||||||
|
'name' => 'Invalid',
|
||||||
|
'serialize' => function ($value) { return $value; },
|
||||||
|
'parseLiteral' => function ($node) {
|
||||||
|
throw new \Exception('Invalid scalar is always invalid: ' . $node->value);
|
||||||
|
},
|
||||||
|
'parseValue' => function ($value) {
|
||||||
|
throw new \Exception('Invalid scalar is always invalid: ' . $value);
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
$anyScalar = new CustomScalarType([
|
||||||
|
'name' => 'Any',
|
||||||
|
'serialize' => function ($value) { return $value; },
|
||||||
|
'parseLiteral' => function ($node) { return $node; }, // Allows any value
|
||||||
|
'parseValue' => function ($value) { return $value; }, // Allows any value
|
||||||
|
]);
|
||||||
|
|
||||||
$queryRoot = new ObjectType([
|
$queryRoot = new ObjectType([
|
||||||
'name' => 'QueryRoot',
|
'name' => 'QueryRoot',
|
||||||
'fields' => [
|
'fields' => [
|
||||||
@ -274,6 +293,14 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
'dogOrHuman' => ['type' => $DogOrHuman],
|
'dogOrHuman' => ['type' => $DogOrHuman],
|
||||||
'humanOrAlien' => ['type' => $HumanOrAlien],
|
'humanOrAlien' => ['type' => $HumanOrAlien],
|
||||||
'complicatedArgs' => ['type' => $ComplicatedArgs],
|
'complicatedArgs' => ['type' => $ComplicatedArgs],
|
||||||
|
'invalidArg' => [
|
||||||
|
'args' => ['arg' => ['type' => $invalidScalar]],
|
||||||
|
'type' => Type::string(),
|
||||||
|
],
|
||||||
|
'anyArg' => [
|
||||||
|
'args' => ['arg' => ['type' => $anyScalar]],
|
||||||
|
'type' => Type::string(),
|
||||||
|
],
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ $entries = [
|
|||||||
\GraphQL\GraphQL::class,
|
\GraphQL\GraphQL::class,
|
||||||
\GraphQL\Type\Definition\Type::class,
|
\GraphQL\Type\Definition\Type::class,
|
||||||
\GraphQL\Type\Definition\ResolveInfo::class,
|
\GraphQL\Type\Definition\ResolveInfo::class,
|
||||||
\GraphQL\Type\Definition\DirectiveLocation::class => ['constants' => true],
|
\GraphQL\Language\DirectiveLocation::class => ['constants' => true],
|
||||||
\GraphQL\Type\SchemaConfig::class,
|
\GraphQL\Type\SchemaConfig::class,
|
||||||
\GraphQL\Type\Schema::class,
|
\GraphQL\Type\Schema::class,
|
||||||
\GraphQL\Language\Parser::class,
|
\GraphQL\Language\Parser::class,
|
||||||
|
Loading…
Reference in New Issue
Block a user