Consistent coding style + doc block comments for Types and Utils

This commit is contained in:
vladar 2016-10-17 18:33:47 +07:00
parent a2e6502b68
commit 357166791a
39 changed files with 800 additions and 349 deletions

View File

@ -1,5 +1,25 @@
# Upgrade # Upgrade
## Upgrade v0.7.x > v1.0.x
### 1. Protected property and method naming
In order to unify coding style, leading underscores were removed from all private and protected properties
and methods.
Example before the change:
```php
GraphQL\Schema::$_queryType
```
Correct usage after the change:
```php
GraphQL\Schema::$queryType
```
So if you rely on any protected properties or methods of any GraphQL class, make sure to
delete leading underscores.
## Upgrade v0.6.x > v0.7.x ## Upgrade v0.6.x > v0.7.x
There are a few new breaking changes in v0.7.0 that were added to the graphql-js reference implementation There are a few new breaking changes in v0.7.0 that were added to the graphql-js reference implementation

View File

@ -76,7 +76,7 @@ abstract class Node
const DIRECTIVE_DEFINITION = 'DirectiveDefinition'; const DIRECTIVE_DEFINITION = 'DirectiveDefinition';
/** /**
type Node = Name type Node = Name
| Document | Document
| OperationDefinition | OperationDefinition
| VariableDefinition | VariableDefinition
@ -120,20 +120,24 @@ abstract class Node
*/ */
public function cloneDeep() public function cloneDeep()
{ {
return $this->_cloneValue($this); return $this->cloneValue($this);
} }
private function _cloneValue($value) /**
* @param $value
* @return array|Node
*/
private function cloneValue($value)
{ {
if (is_array($value)) { if (is_array($value)) {
$cloned = []; $cloned = [];
foreach ($value as $key => $arrValue) { foreach ($value as $key => $arrValue) {
$cloned[$key] = $this->_cloneValue($arrValue); $cloned[$key] = $this->cloneValue($arrValue);
} }
} else if ($value instanceof Node) { } else if ($value instanceof Node) {
$cloned = clone $value; $cloned = clone $value;
foreach (get_object_vars($cloned) as $prop => $propValue) { foreach (get_object_vars($cloned) as $prop => $propValue) {
$cloned->{$prop} = $this->_cloneValue($propValue); $cloned->{$prop} = $this->cloneValue($propValue);
} }
} else { } else {
$cloned = $value; $cloned = $value;
@ -147,6 +151,11 @@ abstract class Node
*/ */
public function __toString() public function __toString()
{ {
return json_encode($this); $tmp = (array) $this;
$tmp['loc'] = [
'start' => $this->loc->start,
'end' => $this->loc->end
];
return json_encode($tmp);
} }
} }

View File

@ -117,6 +117,11 @@ class Parser
*/ */
private $lexer; private $lexer;
/**
* Parser constructor.
* @param Source $source
* @param array $options
*/
function __construct(Source $source, array $options = []) function __construct(Source $source, array $options = [])
{ {
$this->lexer = new Lexer($source, $options); $this->lexer = new Lexer($source, $options);

View File

@ -11,42 +11,46 @@ use GraphQL\Type\Definition\UnionType;
use GraphQL\Type\Definition\WrappingType; use GraphQL\Type\Definition\WrappingType;
use GraphQL\Type\Introspection; use GraphQL\Type\Introspection;
/**
* Class Schema
* @package GraphQL
*/
class Schema class Schema
{ {
/** /**
* @var ObjectType * @var ObjectType
*/ */
protected $_queryType; protected $queryType;
/** /**
* @var ObjectType * @var ObjectType
*/ */
protected $_mutationType; protected $mutationType;
/** /**
* @var ObjectType * @var ObjectType
*/ */
protected $_subscriptionType; protected $subscriptionType;
/** /**
* @var Directive[] * @var Directive[]
*/ */
protected $_directives; protected $directives;
/** /**
* @var array<string, Type> * @var array<string, Type>
*/ */
protected $_typeMap; protected $typeMap;
/** /**
* @var array<string, ObjectType[]> * @var array<string, ObjectType[]>
*/ */
protected $_implementations; protected $implementations;
/** /**
* @var array<string, array<string, boolean>> * @var array<string, array<string, boolean>>
*/ */
protected $_possibleTypeMap; protected $possibleTypeMap;
/** /**
* Schema constructor. * Schema constructor.
@ -69,10 +73,13 @@ class Schema
]; ];
} }
$this->_init($config); $this->init($config);
} }
protected function _init(array $config) /**
* @param array $config
*/
protected function init(array $config)
{ {
$config += [ $config += [
'query' => null, 'query' => null,
@ -88,19 +95,19 @@ class Schema
"Schema query must be Object Type but got: " . Utils::getVariableType($config['query']) "Schema query must be Object Type but got: " . Utils::getVariableType($config['query'])
); );
$this->_queryType = $config['query']; $this->queryType = $config['query'];
Utils::invariant( Utils::invariant(
!$config['mutation'] || $config['mutation'] instanceof ObjectType, !$config['mutation'] || $config['mutation'] instanceof ObjectType,
"Schema mutation must be Object Type if provided but got: " . Utils::getVariableType($config['mutation']) "Schema mutation must be Object Type if provided but got: " . Utils::getVariableType($config['mutation'])
); );
$this->_mutationType = $config['mutation']; $this->mutationType = $config['mutation'];
Utils::invariant( Utils::invariant(
!$config['subscription'] || $config['subscription'] instanceof ObjectType, !$config['subscription'] || $config['subscription'] instanceof ObjectType,
"Schema subscription must be Object Type if provided but got: " . Utils::getVariableType($config['subscription']) "Schema subscription must be Object Type if provided but got: " . Utils::getVariableType($config['subscription'])
); );
$this->_subscriptionType = $config['subscription']; $this->subscriptionType = $config['subscription'];
Utils::invariant( Utils::invariant(
!$config['types'] || is_array($config['types']), !$config['types'] || is_array($config['types']),
@ -112,7 +119,7 @@ class Schema
"Schema directives must be Directive[] if provided but got " . Utils::getVariableType($config['directives']) "Schema directives must be Directive[] if provided but got " . Utils::getVariableType($config['directives'])
); );
$this->_directives = array_merge($config['directives'], [ $this->directives = array_merge($config['directives'], [
Directive::includeDirective(), Directive::includeDirective(),
Directive::skipDirective() Directive::skipDirective()
]); ]);
@ -129,16 +136,16 @@ class Schema
} }
foreach ($initialTypes as $type) { foreach ($initialTypes as $type) {
$this->_extractTypes($type); $this->extractTypes($type);
} }
$this->_typeMap += Type::getInternalTypes(); $this->typeMap += Type::getInternalTypes();
// Keep track of all implementations by interface name. // Keep track of all implementations by interface name.
$this->_implementations = []; $this->implementations = [];
foreach ($this->_typeMap as $typeName => $type) { foreach ($this->typeMap as $typeName => $type) {
if ($type instanceof ObjectType) { if ($type instanceof ObjectType) {
foreach ($type->getInterfaces() as $iface) { foreach ($type->getInterfaces() as $iface) {
$this->_implementations[$iface->name][] = $type; $this->implementations[$iface->name][] = $type;
} }
} }
} }
@ -149,7 +156,7 @@ class Schema
*/ */
public function getQueryType() public function getQueryType()
{ {
return $this->_queryType; return $this->queryType;
} }
/** /**
@ -157,7 +164,7 @@ class Schema
*/ */
public function getMutationType() public function getMutationType()
{ {
return $this->_mutationType; return $this->mutationType;
} }
/** /**
@ -165,7 +172,7 @@ class Schema
*/ */
public function getSubscriptionType() public function getSubscriptionType()
{ {
return $this->_subscriptionType; return $this->subscriptionType;
} }
/** /**
@ -173,7 +180,7 @@ class Schema
*/ */
public function getTypeMap() public function getTypeMap()
{ {
return $this->_typeMap; return $this->typeMap;
} }
/** /**
@ -196,7 +203,7 @@ class Schema
return $abstractType->getTypes(); return $abstractType->getTypes();
} }
Utils::invariant($abstractType instanceof InterfaceType); Utils::invariant($abstractType instanceof InterfaceType);
return isset($this->_implementations[$abstractType->name]) ? $this->_implementations[$abstractType->name] : []; return isset($this->implementations[$abstractType->name]) ? $this->implementations[$abstractType->name] : [];
} }
/** /**
@ -206,19 +213,19 @@ class Schema
*/ */
public function isPossibleType(AbstractType $abstractType, ObjectType $possibleType) public function isPossibleType(AbstractType $abstractType, ObjectType $possibleType)
{ {
if (null === $this->_possibleTypeMap) { if (null === $this->possibleTypeMap) {
$this->_possibleTypeMap = []; $this->possibleTypeMap = [];
} }
if (!isset($this->_possibleTypeMap[$abstractType->name])) { if (!isset($this->possibleTypeMap[$abstractType->name])) {
$tmp = []; $tmp = [];
foreach ($this->getPossibleTypes($abstractType) as $type) { foreach ($this->getPossibleTypes($abstractType) as $type) {
$tmp[$type->name] = true; $tmp[$type->name] = true;
} }
$this->_possibleTypeMap[$abstractType->name] = $tmp; $this->possibleTypeMap[$abstractType->name] = $tmp;
} }
return !empty($this->_possibleTypeMap[$abstractType->name][$possibleType->name]); return !empty($this->possibleTypeMap[$abstractType->name][$possibleType->name]);
} }
/** /**
@ -226,7 +233,7 @@ class Schema
*/ */
public function getDirectives() public function getDirectives()
{ {
return $this->_directives; return $this->directives;
} }
/** /**
@ -243,24 +250,39 @@ class Schema
return null; return null;
} }
/**
* @param $type
* @deprecated since 17.10.2016 in favor of $this->extractTypes
* @return array
*/
protected function _extractTypes($type) protected function _extractTypes($type)
{
trigger_error(__METHOD__ . ' is deprecated in favor of ' . __CLASS__ . '::extractTypes', E_USER_DEPRECATED);
return $this->extractTypes($type);
}
/**
* @param $type
* @return array
*/
protected function extractTypes($type)
{ {
if (!$type) { if (!$type) {
return $this->_typeMap; return $this->typeMap;
} }
if ($type instanceof WrappingType) { if ($type instanceof WrappingType) {
return $this->_extractTypes($type->getWrappedType(true)); return $this->extractTypes($type->getWrappedType(true));
} }
if (!empty($this->_typeMap[$type->name])) { if (!empty($this->typeMap[$type->name])) {
Utils::invariant( Utils::invariant(
$this->_typeMap[$type->name] === $type, $this->typeMap[$type->name] === $type,
"Schema must contain unique named types but contains multiple types named \"$type\"." "Schema must contain unique named types but contains multiple types named \"$type\"."
); );
return $this->_typeMap; return $this->typeMap;
} }
$this->_typeMap[$type->name] = $type; $this->typeMap[$type->name] = $type;
$nestedTypes = []; $nestedTypes = [];
@ -280,8 +302,8 @@ class Schema
} }
} }
foreach ($nestedTypes as $type) { foreach ($nestedTypes as $type) {
$this->_extractTypes($type); $this->extractTypes($type);
} }
return $this->_typeMap; return $this->typeMap;
} }
} }

View File

@ -1,14 +1,13 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
interface AbstractType
{
/* /*
export type GraphQLAbstractType = export type GraphQLAbstractType =
GraphQLInterfaceType | GraphQLInterfaceType |
GraphQLUnionType; GraphQLUnionType;
*/ */
interface AbstractType
{
/** /**
* @return callable|null * @return callable|null
*/ */

View File

@ -3,22 +3,44 @@ namespace GraphQL\Type\Definition;
use GraphQL\Language\AST\BooleanValue; use GraphQL\Language\AST\BooleanValue;
/**
* Class BooleanType
* @package GraphQL\Type\Definition
*/
class BooleanType extends ScalarType class BooleanType extends ScalarType
{ {
/**
* @var string
*/
public $name = Type::BOOLEAN; public $name = Type::BOOLEAN;
/**
* @var string
*/
public $description = 'The `Boolean` scalar type represents `true` or `false`.'; public $description = 'The `Boolean` scalar type represents `true` or `false`.';
/**
* @param mixed $value
* @return bool
*/
public function serialize($value) public function serialize($value)
{ {
return !!$value; return !!$value;
} }
/**
* @param mixed $value
* @return bool
*/
public function parseValue($value) public function parseValue($value)
{ {
return !!$value; return !!$value;
} }
/**
* @param $ast
* @return bool|null
*/
public function parseLiteral($ast) public function parseLiteral($ast)
{ {
if ($ast instanceof BooleanValue) { if ($ast instanceof BooleanValue) {

View File

@ -1,13 +1,12 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
interface CompositeType
{
/* /*
export type GraphQLCompositeType = export type GraphQLCompositeType =
GraphQLObjectType | GraphQLObjectType |
GraphQLInterfaceType | GraphQLInterfaceType |
GraphQLUnionType; GraphQLUnionType;
*/ */
interface CompositeType
{
} }

View File

@ -3,6 +3,10 @@ namespace GraphQL\Type\Definition;
use GraphQL\Utils; use GraphQL\Utils;
/**
* Class Config
* @package GraphQL\Type\Definition
*/
class Config class Config
{ {
const BOOLEAN = 1; const BOOLEAN = 1;
@ -23,8 +27,14 @@ class Config
const KEY_AS_NAME = 131072; const KEY_AS_NAME = 131072;
const MAYBE_THUNK = 262144; const MAYBE_THUNK = 262144;
/**
* @var bool
*/
private static $enableValidation = false; private static $enableValidation = false;
/**
* Disables config validation
*/
public static function disableValidation() public static function disableValidation()
{ {
self::$enableValidation = false; self::$enableValidation = false;
@ -39,11 +49,15 @@ class Config
self::$enableValidation = true; self::$enableValidation = true;
} }
/**
* @param array $config
* @param array $definition
*/
public static function validate(array $config, array $definition) public static function validate(array $config, array $definition)
{ {
if (self::$enableValidation) { if (self::$enableValidation) {
$name = isset($config['name']) ? $config['name'] : 'UnnamedType'; $name = isset($config['name']) ? $config['name'] : 'UnnamedType';
self::_validateMap($name, $config, $definition); self::validateMap($name, $config, $definition);
} }
} }
@ -75,7 +89,13 @@ class Config
return $tmp; return $tmp;
} }
private static function _validateMap($typeName, array $map, array $definitions, $pathStr = null) /**
* @param $typeName
* @param array $map
* @param array $definitions
* @param null $pathStr
*/
private static function validateMap($typeName, array $map, array $definitions, $pathStr = null)
{ {
$suffix = $pathStr ? " at $pathStr" : ''; $suffix = $pathStr ? " at $pathStr" : '';
@ -87,17 +107,25 @@ class Config
} }
// Make sure that all required keys are present in map // Make sure that all required keys are present in map
$requiredKeys = array_filter($definitions, function($def) {return (self::_getFlags($def) & self::REQUIRED) > 0;}); $requiredKeys = array_filter($definitions, function($def) {return (self::getFlags($def) & self::REQUIRED) > 0;});
$missingKeys = array_keys(array_diff_key($requiredKeys, $map)); $missingKeys = array_keys(array_diff_key($requiredKeys, $map));
Utils::invariant(empty($missingKeys), 'Error in "'.$typeName.'" type definition: Required keys missing: "%s"' . $suffix, implode(', ', $missingKeys)); Utils::invariant(empty($missingKeys), 'Error in "'.$typeName.'" type definition: Required keys missing: "%s"' . $suffix, implode(', ', $missingKeys));
// Make sure that every map value is valid given the definition // Make sure that every map value is valid given the definition
foreach ($map as $key => $value) { foreach ($map as $key => $value) {
self::_validateEntry($typeName, $key, $value, $definitions[$key], $pathStr ? "$pathStr:$key" : $key); self::validateEntry($typeName, $key, $value, $definitions[$key], $pathStr ? "$pathStr:$key" : $key);
} }
} }
private static function _validateEntry($typeName, $key, $value, $def, $pathStr) /**
* @param $typeName
* @param $key
* @param $value
* @param $def
* @param $pathStr
* @throws \Exception
*/
private static function validateEntry($typeName, $key, $value, $def, $pathStr)
{ {
$type = Utils::getVariableType($value); $type = Utils::getVariableType($value);
$err = 'Error in "'.$typeName.'" type definition: expecting %s at "' . $pathStr . '", but got "' . $type . '"'; $err = 'Error in "'.$typeName.'" type definition: expecting %s at "' . $pathStr . '", but got "' . $type . '"';
@ -116,7 +144,7 @@ class Config
if ($def->flags & self::KEY_AS_NAME) { if ($def->flags & self::KEY_AS_NAME) {
$value += ['name' => $key]; $value += ['name' => $key];
} }
self::_validateMap($typeName, $value, $def->definition, $pathStr); self::validateMap($typeName, $value, $def->definition, $pathStr);
} else if (!empty($def->isArray)) { } else if (!empty($def->isArray)) {
if ($def->flags & self::REQUIRED) { if ($def->flags & self::REQUIRED) {
@ -132,9 +160,9 @@ class Config
if ($def->flags & self::KEY_AS_NAME) { if ($def->flags & self::KEY_AS_NAME) {
$arrValue += ['name' => $arrKey]; $arrValue += ['name' => $arrKey];
} }
self::_validateMap($typeName, $arrValue, $def->definition, "$pathStr:$arrKey"); self::validateMap($typeName, $arrValue, $def->definition, "$pathStr:$arrKey");
} else { } else {
self::_validateEntry($typeName, $arrKey, $arrValue, $def->definition, "$pathStr:$arrKey"); self::validateEntry($typeName, $arrKey, $arrValue, $def->definition, "$pathStr:$arrKey");
} }
} }
} else { } else {
@ -209,7 +237,11 @@ class Config
} }
} }
private static function _getFlags($def) /**
* @param $def
* @return mixed
*/
private static function getFlags($def)
{ {
return is_object($def) ? $def->flags : $def; return is_object($def) ? $def->flags : $def;
} }

View File

@ -1,11 +1,21 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
/**
* Class CustomScalarType
* @package GraphQL\Type\Definition
*/
class CustomScalarType extends ScalarType class CustomScalarType extends ScalarType
{ {
private $config; /**
* @var array
*/
public $config;
/**
* CustomScalarType constructor.
* @param array $config
*/
function __construct(array $config) function __construct(array $config)
{ {
$this->name = $config['name']; $this->name = $config['name'];
@ -13,16 +23,28 @@ class CustomScalarType extends ScalarType
parent::__construct(); parent::__construct();
} }
/**
* @param mixed $value
* @return mixed
*/
public function serialize($value) public function serialize($value)
{ {
return call_user_func($this->config['serialize'], $value); return call_user_func($this->config['serialize'], $value);
} }
/**
* @param mixed $value
* @return mixed
*/
public function parseValue($value) public function parseValue($value)
{ {
return call_user_func($this->config['parseValue'], $value); return call_user_func($this->config['parseValue'], $value);
} }
/**
* @param $valueAST
* @return mixed
*/
public function parseLiteral(/* GraphQL\Language\AST\Value */ $valueAST) public function parseLiteral(/* GraphQL\Language\AST\Value */ $valueAST)
{ {
return call_user_func($this->config['parseLiteral'], $valueAST); return call_user_func($this->config['parseLiteral'], $valueAST);

View File

@ -1,10 +1,20 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
/**
* Class Directive
* @package GraphQL\Type\Definition
*/
class Directive class Directive
{ {
/**
* @var array
*/
public static $internalDirectives; public static $internalDirectives;
/**
* @var array
*/
public static $directiveLocations = [ public static $directiveLocations = [
'QUERY' => 'QUERY', 'QUERY' => 'QUERY',
'MUTATION' => 'MUTATION', 'MUTATION' => 'MUTATION',
@ -33,6 +43,9 @@ class Directive
return $internal['skip']; return $internal['skip'];
} }
/**
* @return array
*/
public static function getInternalDirectives() public static function getInternalDirectives()
{ {
if (!self::$internalDirectives) { if (!self::$internalDirectives) {
@ -96,6 +109,10 @@ class Directive
*/ */
public $args; public $args;
/**
* Directive constructor.
* @param array $config
*/
public function __construct(array $config) public function __construct(array $config)
{ {
foreach ($config as $key => $value) { foreach ($config as $key => $value) {

View File

@ -4,22 +4,26 @@ namespace GraphQL\Type\Definition;
use GraphQL\Language\AST\EnumValue; use GraphQL\Language\AST\EnumValue;
use GraphQL\Utils; use GraphQL\Utils;
class EnumType extends Type implements InputType, OutputType /**
* Class EnumType
* @package GraphQL\Type\Definition
*/
class EnumType extends Type implements InputType, OutputType, LeafType
{ {
/** /**
* @var array<EnumValueDefinition> * @var array<EnumValueDefinition>
*/ */
private $_values; private $values;
/** /**
* @var \ArrayObject<mixed, EnumValueDefinition> * @var \ArrayObject<mixed, EnumValueDefinition>
*/ */
private $_valueLookup; private $valueLookup;
/** /**
* @var \ArrayObject<string, EnumValueDefinition> * @var \ArrayObject<string, EnumValueDefinition>
*/ */
private $_nameLookup; private $nameLookup;
public function __construct($config) public function __construct($config)
{ {
@ -36,11 +40,11 @@ class EnumType extends Type implements InputType, OutputType
$this->name = $config['name']; $this->name = $config['name'];
$this->description = isset($config['description']) ? $config['description'] : null; $this->description = isset($config['description']) ? $config['description'] : null;
$this->_values = []; $this->values = [];
if (!empty($config['values'])) { if (!empty($config['values'])) {
foreach ($config['values'] as $name => $value) { foreach ($config['values'] as $name => $value) {
$this->_values[] = Utils::assign(new EnumValueDefinition(), $value + ['name' => $name, 'value' => $name]); // value will be equal to name only if 'value' is not set in definition $this->values[] = Utils::assign(new EnumValueDefinition(), $value + ['name' => $name, 'value' => $name]); // value will be equal to name only if 'value' is not set in definition
} }
} }
} }
@ -50,7 +54,7 @@ class EnumType extends Type implements InputType, OutputType
*/ */
public function getValues() public function getValues()
{ {
return $this->_values; return $this->values;
} }
/** /**
@ -59,7 +63,7 @@ class EnumType extends Type implements InputType, OutputType
*/ */
public function serialize($value) public function serialize($value)
{ {
$lookup = $this->_getValueLookup(); $lookup = $this->getValueLookup();
return isset($lookup[$value]) ? $lookup[$value]->name : null; return isset($lookup[$value]) ? $lookup[$value]->name : null;
} }
@ -69,7 +73,7 @@ class EnumType extends Type implements InputType, OutputType
*/ */
public function parseValue($value) public function parseValue($value)
{ {
$lookup = $this->_getNameLookup(); $lookup = $this->getNameLookup();
return isset($lookup[$value]) ? $lookup[$value]->value : null; return isset($lookup[$value]) ? $lookup[$value]->value : null;
} }
@ -80,7 +84,7 @@ class EnumType extends Type implements InputType, OutputType
public function parseLiteral($value) public function parseLiteral($value)
{ {
if ($value instanceof EnumValue) { if ($value instanceof EnumValue) {
$lookup = $this->_getNameLookup(); $lookup = $this->getNameLookup();
if (isset($lookup[$value->value])) { if (isset($lookup[$value->value])) {
$enumValue = $lookup[$value->value]; $enumValue = $lookup[$value->value];
if ($enumValue) { if ($enumValue) {
@ -95,31 +99,31 @@ class EnumType extends Type implements InputType, OutputType
* @todo Value lookup for any type, not just scalars * @todo Value lookup for any type, not just scalars
* @return \ArrayObject<mixed, EnumValueDefinition> * @return \ArrayObject<mixed, EnumValueDefinition>
*/ */
protected function _getValueLookup() private function getValueLookup()
{ {
if (null === $this->_valueLookup) { if (null === $this->valueLookup) {
$this->_valueLookup = new \ArrayObject(); $this->valueLookup = new \ArrayObject();
foreach ($this->getValues() as $valueName => $value) { foreach ($this->getValues() as $valueName => $value) {
$this->_valueLookup[$value->value] = $value; $this->valueLookup[$value->value] = $value;
} }
} }
return $this->_valueLookup; return $this->valueLookup;
} }
/** /**
* @return \ArrayObject<string, GraphQLEnumValueDefinition> * @return \ArrayObject<string, GraphQLEnumValueDefinition>
*/ */
protected function _getNameLookup() private function getNameLookup()
{ {
if (!$this->_nameLookup) { if (!$this->nameLookup) {
$lookup = new \ArrayObject(); $lookup = new \ArrayObject();
foreach ($this->getValues() as $value) { foreach ($this->getValues() as $value) {
$lookup[$value->name] = $value; $lookup[$value->name] = $value;
} }
$this->_nameLookup = $lookup; $this->nameLookup = $lookup;
} }
return $this->_nameLookup; return $this->nameLookup;
} }
} }

View File

@ -1,6 +1,10 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
/**
* Class EnumValueDefinition
* @package GraphQL\Type\Definition
*/
class EnumValueDefinition class EnumValueDefinition
{ {
/** /**

View File

@ -2,8 +2,6 @@
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
use GraphQL\Utils;
/** /**
* Class FieldArgument * Class FieldArgument
* *
@ -17,13 +15,6 @@ class FieldArgument
*/ */
public $name; public $name;
/**
* @var InputType
*/
private $type;
private $resolvedType;
/** /**
* @var mixed * @var mixed
*/ */
@ -34,6 +25,25 @@ class FieldArgument
*/ */
public $description; public $description;
/**
* @var array
*/
public $config;
/**
* @var InputType|callable
*/
private $type;
/**
* @var InputType
*/
private $resolvedType;
/**
* @param array $config
* @return array
*/
public static function createMap(array $config) public static function createMap(array $config)
{ {
$map = []; $map = [];
@ -43,13 +53,30 @@ class FieldArgument
return $map; return $map;
} }
/**
* FieldArgument constructor.
* @param array $def
*/
public function __construct(array $def) public function __construct(array $def)
{ {
foreach ($def as $key => $value) { $def += [
$this->{$key} = $value; 'type' => null,
} 'name' => null,
'defaultValue' => null,
'description' => null
];
$this->type = $def['type'];
$this->name = $def['name'];
$this->description = $def['description'];
$this->defaultValue = $def['defaultValue'];
$this->config = $def;
} }
/**
* @return InputType
* @deprecated in favor of setting 'fields' as closure per objectType vs on individual field/argument level
*/
public function getType() public function getType()
{ {
if (null === $this->resolvedType) { if (null === $this->resolvedType) {

View File

@ -1,8 +1,11 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
use GraphQL\Utils; /**
* Class FieldDefinition
* @package GraphQL\Type\Definition
* @todo Move complexity-related code to it's own place
*/
class FieldDefinition class FieldDefinition
{ {
const DEFAULT_COMPLEXITY_FN = 'GraphQL\Type\Definition\FieldDefinition::defaultComplexity'; const DEFAULT_COMPLEXITY_FN = 'GraphQL\Type\Definition\FieldDefinition::defaultComplexity';
@ -12,16 +15,6 @@ class FieldDefinition
*/ */
public $name; public $name;
/**
* @var OutputType
*/
private $type;
/**
* @var OutputType
*/
private $resolvedType;
/** /**
* @var array<GraphQLFieldArgument> * @var array<GraphQLFieldArgument>
*/ */
@ -60,8 +53,21 @@ class FieldDefinition
*/ */
public $config; public $config;
/**
* @var OutputType|callable
*/
private $type;
/**
* @var OutputType
*/
private $resolvedType;
private static $def; private static $def;
/**
* @return array
*/
public static function getDefinition() public static function getDefinition()
{ {
return self::$def ?: (self::$def = [ return self::$def ?: (self::$def = [
@ -107,6 +113,10 @@ class FieldDefinition
return new self($field); return new self($field);
} }
/**
* FieldDefinition constructor.
* @param array $config
*/
protected function __construct(array $config) protected function __construct(array $config)
{ {
$this->name = $config['name']; $this->name = $config['name'];
@ -139,6 +149,7 @@ class FieldDefinition
} }
/** /**
* @deprecated as of 17.10.2016 in favor of setting 'fields' as closure per ObjectType vs setting on field level
* @return Type * @return Type
*/ */
public function getType() public function getType()
@ -150,6 +161,14 @@ class FieldDefinition
return $this->resolvedType; return $this->resolvedType;
} }
/**
* @return bool
*/
public function isDeprecated()
{
return !!$this->deprecationReason;
}
/** /**
* @return callable|\Closure * @return callable|\Closure
*/ */
@ -158,6 +177,10 @@ class FieldDefinition
return $this->complexityFn; return $this->complexityFn;
} }
/**
* @param $childrenComplexity
* @return mixed
*/
public static function defaultComplexity($childrenComplexity) public static function defaultComplexity($childrenComplexity)
{ {
return $childrenComplexity + 1; return $childrenComplexity + 1;

View File

@ -4,30 +4,56 @@ namespace GraphQL\Type\Definition;
use GraphQL\Language\AST\FloatValue; use GraphQL\Language\AST\FloatValue;
use GraphQL\Language\AST\IntValue; use GraphQL\Language\AST\IntValue;
/**
* Class FloatType
* @package GraphQL\Type\Definition
*/
class FloatType extends ScalarType class FloatType extends ScalarType
{ {
/**
* @var string
*/
public $name = Type::FLOAT; public $name = Type::FLOAT;
/**
* @var string
*/
public $description = public $description =
'The `Float` scalar type represents signed double-precision fractional 'The `Float` scalar type represents signed double-precision fractional
values as specified by values as specified by
[IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). '; [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ';
/**
* @param mixed $value
* @return float|null
*/
public function serialize($value) public function serialize($value)
{ {
return $this->coerceFloat($value); return $this->coerceFloat($value);
} }
/**
* @param mixed $value
* @return float|null
*/
public function parseValue($value) public function parseValue($value)
{ {
return $this->coerceFloat($value); return $this->coerceFloat($value);
} }
/**
* @param $value
* @return float|null
*/
private function coerceFloat($value) private function coerceFloat($value)
{ {
return is_numeric($value) || $value === true || $value === false ? (float) $value : null; return is_numeric($value) || $value === true || $value === false ? (float) $value : null;
} }
/**
* @param $ast
* @return float|null
*/
public function parseLiteral($ast) public function parseLiteral($ast)
{ {
if ($ast instanceof FloatValue || $ast instanceof IntValue) { if ($ast instanceof FloatValue || $ast instanceof IntValue) {

View File

@ -4,10 +4,20 @@ namespace GraphQL\Type\Definition;
use GraphQL\Language\AST\IntValue; use GraphQL\Language\AST\IntValue;
use GraphQL\Language\AST\StringValue; use GraphQL\Language\AST\StringValue;
/**
* Class IDType
* @package GraphQL\Type\Definition
*/
class IDType extends ScalarType class IDType extends ScalarType
{ {
/**
* @var string
*/
public $name = 'ID'; public $name = 'ID';
/**
* @var string
*/
public $description = public $description =
'The `ID` scalar type represents a unique identifier, often used to 'The `ID` scalar type represents a unique identifier, often used to
refetch an object or as key for a cache. The ID type appears in a JSON refetch an object or as key for a cache. The ID type appears in a JSON
@ -15,16 +25,28 @@ response as a String; however, it is not intended to be human-readable.
When expected as an input type, any string (such as `"4"`) or integer When expected as an input type, any string (such as `"4"`) or integer
(such as `4`) input value will be accepted as an ID.'; (such as `4`) input value will be accepted as an ID.';
/**
* @param mixed $value
* @return string
*/
public function serialize($value) public function serialize($value)
{ {
return (string) $value; return (string) $value;
} }
/**
* @param mixed $value
* @return string
*/
public function parseValue($value) public function parseValue($value)
{ {
return (string) $value; return (string) $value;
} }
/**
* @param $ast
* @return null|string
*/
public function parseLiteral($ast) public function parseLiteral($ast)
{ {
if ($ast instanceof StringValue || $ast instanceof IntValue) { if ($ast instanceof StringValue || $ast instanceof IntValue) {

View File

@ -1,8 +1,10 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
use GraphQL\Utils; /**
* Class InputObjectField
* @package GraphQL\Type\Definition
*/
class InputObjectField class InputObjectField
{ {
/** /**
@ -10,11 +12,6 @@ class InputObjectField
*/ */
public $name; public $name;
/**
* @var callback|InputType
*/
private $type;
/** /**
* @var mixed|null * @var mixed|null
*/ */
@ -25,6 +22,15 @@ class InputObjectField
*/ */
public $description; public $description;
/**
* @var callback|InputType
*/
public $type;
/**
* InputObjectField constructor.
* @param array $opts
*/
public function __construct(array $opts) public function __construct(array $opts)
{ {
foreach ($opts as $k => $v) { foreach ($opts as $k => $v) {
@ -32,6 +38,10 @@ class InputObjectField
} }
} }
/**
* @deprecated in favor of defining all object 'fields' as closure vs defining closure per field
* @return mixed
*/
public function getType() public function getType()
{ {
return Type::resolve($this->type); return Type::resolve($this->type);

View File

@ -3,15 +3,26 @@ namespace GraphQL\Type\Definition;
use GraphQL\Utils; use GraphQL\Utils;
/**
* Class InputObjectType
* @package GraphQL\Type\Definition
*/
class InputObjectType extends Type implements InputType class InputObjectType extends Type implements InputType
{ {
/** /**
* @var array<InputObjectField> * @var InputObjectField[]
*/ */
private $_fields; private $fields;
/**
* @var array
*/
public $config; public $config;
/**
* InputObjectType constructor.
* @param array $config
*/
public function __construct(array $config) public function __construct(array $config)
{ {
Config::validate($config, [ Config::validate($config, [
@ -35,16 +46,16 @@ class InputObjectType extends Type implements InputType
*/ */
public function getFields() public function getFields()
{ {
if (null === $this->_fields) { if (null === $this->fields) {
$this->_fields = []; $this->fields = [];
$fields = isset($this->config['fields']) ? $this->config['fields'] : []; $fields = isset($this->config['fields']) ? $this->config['fields'] : [];
$fields = is_callable($fields) ? call_user_func($fields) : $fields; $fields = is_callable($fields) ? call_user_func($fields) : $fields;
foreach ($fields as $name => $field) { foreach ($fields as $name => $field) {
$this->_fields[$name] = new InputObjectField($field + ['name' => $name]); $this->fields[$name] = new InputObjectField($field + ['name' => $name]);
} }
} }
return $this->_fields; return $this->fields;
} }
/** /**
@ -54,10 +65,10 @@ class InputObjectType extends Type implements InputType
*/ */
public function getField($name) public function getField($name)
{ {
if (null === $this->_fields) { if (null === $this->fields) {
$this->getFields(); $this->getFields();
} }
Utils::invariant(isset($this->_fields[$name]), "Field '%s' is not defined for type '%s'", $name, $this->name); Utils::invariant(isset($this->fields[$name]), "Field '%s' is not defined for type '%s'", $name, $this->name);
return $this->_fields[$name]; return $this->fields[$name];
} }
} }

View File

@ -1,8 +1,6 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
interface InputType
{
/* /*
export type GraphQLInputType = export type GraphQLInputType =
GraphQLScalarType | GraphQLScalarType |
@ -11,4 +9,6 @@ export type GraphQLInputType =
GraphQLList | GraphQLList |
GraphQLNonNull; GraphQLNonNull;
*/ */
interface InputType
{
} }

View File

@ -4,6 +4,10 @@ namespace GraphQL\Type\Definition;
use GraphQL\Language\AST\IntValue; use GraphQL\Language\AST\IntValue;
use GraphQL\Language\AST\Value; use GraphQL\Language\AST\Value;
/**
* Class IntType
* @package GraphQL\Type\Definition
*/
class IntType extends ScalarType class IntType extends ScalarType
{ {
// As per the GraphQL Spec, Integers are only treated as valid when a valid // As per the GraphQL Spec, Integers are only treated as valid when a valid
@ -14,22 +18,40 @@ class IntType extends ScalarType
const MAX_INT = 2147483647; const MAX_INT = 2147483647;
const MIN_INT = -2147483648; const MIN_INT = -2147483648;
/**
* @var string
*/
public $name = Type::INT; public $name = Type::INT;
/**
* @var string
*/
public $description = public $description =
'The `Int` scalar type represents non-fractional signed whole numeric 'The `Int` scalar type represents non-fractional signed whole numeric
values. Int can represent values between -(2^31) and 2^31 - 1. '; values. Int can represent values between -(2^31) and 2^31 - 1. ';
/**
* @param mixed $value
* @return int|null
*/
public function serialize($value) public function serialize($value)
{ {
return $this->coerceInt($value); return $this->coerceInt($value);
} }
/**
* @param mixed $value
* @return int|null
*/
public function parseValue($value) public function parseValue($value)
{ {
return $this->coerceInt($value); return $this->coerceInt($value);
} }
/**
* @param $value
* @return int|null
*/
private function coerceInt($value) private function coerceInt($value)
{ {
if (false === $value || true === $value) { if (false === $value || true === $value) {
@ -41,6 +63,10 @@ values. Int can represent values between -(2^31) and 2^31 - 1. ';
return null; return null;
} }
/**
* @param $ast
* @return int|null
*/
public function parseLiteral($ast) public function parseLiteral($ast)
{ {
if ($ast instanceof IntValue) { if ($ast instanceof IntValue) {

View File

@ -1,22 +1,28 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
use GraphQL\Utils; use GraphQL\Utils;
/**
* Class InterfaceType
* @package GraphQL\Type\Definition
*/
class InterfaceType extends Type implements AbstractType, OutputType, CompositeType class InterfaceType extends Type implements AbstractType, OutputType, CompositeType
{ {
/** /**
* @var array<string,FieldDefinition> * @var array<string,FieldDefinition>
*/ */
private $_fields; private $fields;
/**
* @var mixed|null
*/
public $description; public $description;
/** /**
* @var callback * @var callback
*/ */
private $_resolveTypeFn; private $resolveTypeFn;
/** /**
* @var array * @var array
@ -41,7 +47,7 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
$this->name = $config['name']; $this->name = $config['name'];
$this->description = isset($config['description']) ? $config['description'] : null; $this->description = isset($config['description']) ? $config['description'] : null;
$this->_resolveTypeFn = isset($config['resolveType']) ? $config['resolveType'] : null; $this->resolveTypeFn = isset($config['resolveType']) ? $config['resolveType'] : null;
$this->config = $config; $this->config = $config;
} }
@ -50,13 +56,13 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
*/ */
public function getFields() public function getFields()
{ {
if (null === $this->_fields) { if (null === $this->fields) {
$this->_fields = []; $this->fields = [];
$fields = isset($this->config['fields']) ? $this->config['fields'] : []; $fields = isset($this->config['fields']) ? $this->config['fields'] : [];
$fields = is_callable($fields) ? call_user_func($fields) : $fields; $fields = is_callable($fields) ? call_user_func($fields) : $fields;
$this->_fields = FieldDefinition::createMap($fields); $this->fields = FieldDefinition::createMap($fields);
} }
return $this->_fields; return $this->fields;
} }
/** /**
@ -66,11 +72,11 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
*/ */
public function getField($name) public function getField($name)
{ {
if (null === $this->_fields) { if (null === $this->fields) {
$this->getFields(); $this->getFields();
} }
Utils::invariant(isset($this->_fields[$name]), 'Field "%s" is not defined for type "%s"', $name, $this->name); Utils::invariant(isset($this->fields[$name]), 'Field "%s" is not defined for type "%s"', $name, $this->name);
return $this->_fields[$name]; return $this->fields[$name];
} }
/** /**
@ -78,6 +84,6 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
*/ */
public function getResolveTypeFn() public function getResolveTypeFn()
{ {
return $this->_resolveTypeFn; return $this->resolveTypeFn;
} }
} }

View File

@ -1,12 +1,11 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
interface LeafType
{
/* /*
export type GraphQLLeafType = export type GraphQLLeafType =
GraphQLScalarType | GraphQLScalarType |
GraphQLEnumType; GraphQLEnumType;
*/ */
interface LeafType
{
} }

View File

@ -1,15 +1,18 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
use GraphQL\Utils; use GraphQL\Utils;
/**
* Class ListOfType
* @package GraphQL\Type\Definition
*/
class ListOfType extends Type implements WrappingType, OutputType, InputType class ListOfType extends Type implements WrappingType, OutputType, InputType
{ {
/** /**
* @var callable|Type * @var callable|Type
*/ */
private $ofType; public $ofType;
/** /**
* @param callable|Type $type * @param callable|Type $type

View File

@ -4,6 +4,10 @@ namespace GraphQL\Type\Definition;
use GraphQL\Type\TypeKind; use GraphQL\Type\TypeKind;
use GraphQL\Utils; use GraphQL\Utils;
/**
* Class NonNull
* @package GraphQL\Type\Definition
*/
class NonNull extends Type implements WrappingType, OutputType, InputType class NonNull extends Type implements WrappingType, OutputType, InputType
{ {
/** /**

View File

@ -11,19 +11,19 @@ use GraphQL\Utils;
* *
* Example: * Example:
* *
* var AddressType = new GraphQLObjectType({ * $AddressType = new ObjectType([
* name: 'Address', * 'name' => 'Address',
* fields: { * 'fields' => [
* street: { type: GraphQLString }, * 'street' => [ 'type' => GraphQL\Type\Definition\Type::string() ],
* number: { type: GraphQLInt }, * 'number' => [ 'type' => GraphQL\Type\Definition\Type::int() ],
* formatted: { * 'formatted' => [
* type: GraphQLString, * 'type' => GraphQL\Type\Definition\Type::string(),
* resolve(obj) { * 'resolve' => function($obj) {
* return obj.number + ' ' + obj.street * return $obj->number . ' ' . $obj->street;
* } * }
* } * ]
* } * ]
* }); * ]);
* *
* When two types need to refer to each other, or a type needs to refer to * When two types need to refer to each other, or a type needs to refer to
* itself in a field, you can use a function expression (aka a closure or a * itself in a field, you can use a function expression (aka a closure or a
@ -31,31 +31,34 @@ use GraphQL\Utils;
* *
* Example: * Example:
* *
* var PersonType = new GraphQLObjectType({ * $PersonType = null;
* name: 'Person', * $PersonType = new ObjectType([
* fields: () => ({ * 'name' => 'Person',
* name: { type: GraphQLString }, * 'fields' => function() use (&$PersonType) {
* bestFriend: { type: PersonType }, * return [
* }) * 'name' => ['type' => GraphQL\Type\Definition\Type::string() ],
* }); * 'bestFriend' => [ 'type' => $PersonType ],
* ];
* }
* ]);
* *
*/ */
class ObjectType extends Type implements OutputType, CompositeType class ObjectType extends Type implements OutputType, CompositeType
{ {
/** /**
* @var array<Field> * @var FieldDefinition[]
*/ */
private $_fields; private $fields;
/** /**
* @var array<InterfaceType> * @var InterfaceType[]
*/ */
private $_interfaces; private $interfaces;
/** /**
* @var callable * @var callable
*/ */
private $_isTypeOf; private $isTypeOf;
/** /**
* Keeping reference of config for late bindings and custom app-level metadata * Keeping reference of config for late bindings and custom app-level metadata
@ -69,6 +72,10 @@ class ObjectType extends Type implements OutputType, CompositeType
*/ */
public $resolveFieldFn; public $resolveFieldFn;
/**
* ObjectType constructor.
* @param array $config
*/
public function __construct(array $config) public function __construct(array $config)
{ {
Utils::invariant(!empty($config['name']), 'Every type is expected to have name'); Utils::invariant(!empty($config['name']), 'Every type is expected to have name');
@ -93,7 +100,7 @@ class ObjectType extends Type implements OutputType, CompositeType
$this->name = $config['name']; $this->name = $config['name'];
$this->description = isset($config['description']) ? $config['description'] : null; $this->description = isset($config['description']) ? $config['description'] : null;
$this->resolveFieldFn = isset($config['resolveField']) ? $config['resolveField'] : null; $this->resolveFieldFn = isset($config['resolveField']) ? $config['resolveField'] : null;
$this->_isTypeOf = isset($config['isTypeOf']) ? $config['isTypeOf'] : null; $this->isTypeOf = isset($config['isTypeOf']) ? $config['isTypeOf'] : null;
$this->config = $config; $this->config = $config;
} }
@ -102,12 +109,12 @@ class ObjectType extends Type implements OutputType, CompositeType
*/ */
public function getFields() public function getFields()
{ {
if (null === $this->_fields) { if (null === $this->fields) {
$fields = isset($this->config['fields']) ? $this->config['fields'] : []; $fields = isset($this->config['fields']) ? $this->config['fields'] : [];
$fields = is_callable($fields) ? call_user_func($fields) : $fields; $fields = is_callable($fields) ? call_user_func($fields) : $fields;
$this->_fields = FieldDefinition::createMap($fields); $this->fields = FieldDefinition::createMap($fields);
} }
return $this->_fields; return $this->fields;
} }
/** /**
@ -117,24 +124,24 @@ class ObjectType extends Type implements OutputType, CompositeType
*/ */
public function getField($name) public function getField($name)
{ {
if (null === $this->_fields) { if (null === $this->fields) {
$this->getFields(); $this->getFields();
} }
Utils::invariant(isset($this->_fields[$name]), "Field '%s' is not defined for type '%s'", $name, $this->name); Utils::invariant(isset($this->fields[$name]), "Field '%s' is not defined for type '%s'", $name, $this->name);
return $this->_fields[$name]; return $this->fields[$name];
} }
/** /**
* @return array<InterfaceType> * @return InterfaceType[]
*/ */
public function getInterfaces() public function getInterfaces()
{ {
if (null === $this->_interfaces) { if (null === $this->interfaces) {
$interfaces = isset($this->config['interfaces']) ? $this->config['interfaces'] : []; $interfaces = isset($this->config['interfaces']) ? $this->config['interfaces'] : [];
$interfaces = is_callable($interfaces) ? call_user_func($interfaces) : $interfaces; $interfaces = is_callable($interfaces) ? call_user_func($interfaces) : $interfaces;
$this->_interfaces = $interfaces; $this->interfaces = $interfaces;
} }
return $this->_interfaces; return $this->interfaces;
} }
/** /**
@ -153,6 +160,6 @@ class ObjectType extends Type implements OutputType, CompositeType
*/ */
public function isTypeOf($value, $context, ResolveInfo $info) public function isTypeOf($value, $context, ResolveInfo $info)
{ {
return isset($this->_isTypeOf) ? call_user_func($this->_isTypeOf, $value, $context, $info) : null; return isset($this->isTypeOf) ? call_user_func($this->isTypeOf, $value, $context, $info) : null;
} }
} }

View File

@ -2,8 +2,6 @@
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
interface OutputType
{
/* /*
GraphQLScalarType | GraphQLScalarType |
GraphQLObjectType | GraphQLObjectType |
@ -13,4 +11,6 @@ GraphQLEnumType |
GraphQLList | GraphQLList |
GraphQLNonNull; GraphQLNonNull;
*/ */
interface OutputType
{
} }

View File

@ -10,6 +10,10 @@ use GraphQL\Language\AST\SelectionSet;
use GraphQL\Schema; use GraphQL\Schema;
use GraphQL\Utils; use GraphQL\Utils;
/**
* Class ResolveInfo
* @package GraphQL\Type\Definition
*/
class ResolveInfo class ResolveInfo
{ {
/** /**

View File

@ -12,24 +12,46 @@ use GraphQL\Utils;
* *
* Example: * Example:
* *
* var OddType = new GraphQLScalarType({ * class OddType extends ScalarType
* name: 'Odd', * {
* serialize(value) { * public $name = 'Odd',
* return value % 2 === 1 ? value : null; * public function serialize($value)
* } * {
* }); * return $value % 2 === 1 ? $value : null;
* * }
* }
*/ */
abstract class ScalarType extends Type implements OutputType, InputType abstract class ScalarType extends Type implements OutputType, InputType, LeafType
{ {
/**
* ScalarType constructor.
*/
protected function __construct() protected function __construct()
{ {
Utils::invariant($this->name, 'Type must be named.'); Utils::invariant($this->name, 'Type must be named.');
} }
/**
* Serializes an internal value to include in a response.
*
* @param mixed $value
* @return mixed
*/
abstract public function serialize($value); abstract public function serialize($value);
/**
* Parses an externally provided value to use as an input
*
* @param mixed $value
* @return mixed
*/
abstract public function parseValue($value); abstract public function parseValue($value);
/**
* Parses an externally provided literal value to use as an input
*
* @param $valueAST
* @return mixed
*/
abstract public function parseLiteral(/* GraphQL\Language\AST\Value */$valueAST); abstract public function parseLiteral(/* GraphQL\Language\AST\Value */$valueAST);
} }

View File

@ -3,20 +3,38 @@ namespace GraphQL\Type\Definition;
use GraphQL\Language\AST\StringValue; use GraphQL\Language\AST\StringValue;
/**
* Class StringType
* @package GraphQL\Type\Definition
*/
class StringType extends ScalarType class StringType extends ScalarType
{ {
/**
* @var string
*/
public $name = Type::STRING; public $name = Type::STRING;
/**
* @var string
*/
public $description = public $description =
'The `String` scalar type represents textual data, represented as UTF-8 'The `String` scalar type represents textual data, represented as UTF-8
character sequences. The String type is most often used by GraphQL to character sequences. The String type is most often used by GraphQL to
represent free-form human-readable text.'; represent free-form human-readable text.';
/**
* @param mixed $value
* @return mixed|string
*/
public function serialize($value) public function serialize($value)
{ {
return $this->parseValue($value); return $this->parseValue($value);
} }
/**
* @param mixed $value
* @return string
*/
public function parseValue($value) public function parseValue($value)
{ {
if ($value === true) { if ($value === true) {
@ -28,6 +46,10 @@ represent free-form human-readable text.';
return (string) $value; return (string) $value;
} }
/**
* @param $ast
* @return null|string
*/
public function parseLiteral($ast) public function parseLiteral($ast)
{ {
if ($ast instanceof StringValue) { if ($ast instanceof StringValue) {

View File

@ -3,8 +3,6 @@ namespace GraphQL\Type\Definition;
use GraphQL\Utils; use GraphQL\Utils;
abstract class Type
{
/* /*
export type GraphQLType = export type GraphQLType =
GraphQLScalarType | GraphQLScalarType |
@ -16,14 +14,22 @@ GraphQLInputObjectType |
GraphQLList | GraphQLList |
GraphQLNonNull; GraphQLNonNull;
*/ */
abstract class Type
{
const STRING = 'String'; const STRING = 'String';
const INT = 'Int'; const INT = 'Int';
const BOOLEAN = 'Boolean'; const BOOLEAN = 'Boolean';
const FLOAT = 'Float'; const FLOAT = 'Float';
const ID = 'ID'; const ID = 'ID';
/**
* @var array
*/
private static $internalTypes; private static $internalTypes;
/**
* @return IDType
*/
public static function id() public static function id()
{ {
return self::getInternalType(self::ID); return self::getInternalType(self::ID);
@ -81,7 +87,7 @@ GraphQLNonNull;
/** /**
* @param $name * @param $name
* @return Type * @return Type|array
*/ */
private static function getInternalType($name = null) private static function getInternalType($name = null)
{ {
@ -125,21 +131,29 @@ GraphQLNonNull;
return $nakedType instanceof OutputType; return $nakedType instanceof OutputType;
} }
/**
* @param $type
* @return bool
*/
public static function isLeafType($type) public static function isLeafType($type)
{ {
// TODO: add LeafType interface
$nakedType = self::getNamedType($type); $nakedType = self::getNamedType($type);
return ( return $nakedType instanceof LeafType;
$nakedType instanceof ScalarType ||
$nakedType instanceof EnumType
);
} }
/**
* @param $type
* @return bool
*/
public static function isCompositeType($type) public static function isCompositeType($type)
{ {
return $type instanceof CompositeType; return $type instanceof CompositeType;
} }
/**
* @param $type
* @return bool
*/
public static function isAbstractType($type) public static function isAbstractType($type)
{ {
return $type instanceof AbstractType; return $type instanceof AbstractType;
@ -169,6 +183,11 @@ GraphQLNonNull;
return self::resolve($type); return self::resolve($type);
} }
/**
* @param $type
* @deprecated in favor of defining ObjectType 'fields' as closure (vs defining closure per field type)
* @return mixed
*/
public static function resolve($type) public static function resolve($type)
{ {
if (is_callable($type)) { if (is_callable($type)) {
@ -213,11 +232,17 @@ GraphQLNonNull;
*/ */
public $description; public $description;
/**
* @return string
*/
public function toString() public function toString()
{ {
return $this->name; return $this->name;
} }
/**
* @return string
*/
public function __toString() public function __toString()
{ {
try { try {

View File

@ -3,28 +3,36 @@ namespace GraphQL\Type\Definition;
use GraphQL\Utils; use GraphQL\Utils;
/**
* Class UnionType
* @package GraphQL\Type\Definition
*/
class UnionType extends Type implements AbstractType, OutputType, CompositeType class UnionType extends Type implements AbstractType, OutputType, CompositeType
{ {
/** /**
* @var ObjectType[] * @var ObjectType[]
*/ */
private $_types; private $types;
/** /**
* @var array<string, ObjectType> * @var array<string, ObjectType>
*/ */
private $_possibleTypeNames; private $possibleTypeNames;
/** /**
* @var callback * @var callback
*/ */
private $_resolveTypeFn; private $resolveTypeFn;
/** /**
* @var array * @var array
*/ */
private $_config; public $config;
/**
* UnionType constructor.
* @param $config
*/
public function __construct($config) public function __construct($config)
{ {
Config::validate($config, [ Config::validate($config, [
@ -43,11 +51,14 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType
*/ */
$this->name = $config['name']; $this->name = $config['name'];
$this->description = isset($config['description']) ? $config['description'] : null; $this->description = isset($config['description']) ? $config['description'] : null;
$this->_types = $config['types']; $this->types = $config['types'];
$this->_resolveTypeFn = isset($config['resolveType']) ? $config['resolveType'] : null; $this->resolveTypeFn = isset($config['resolveType']) ? $config['resolveType'] : null;
$this->_config = $config; $this->config = $config;
} }
/**
* @return ObjectType[]
*/
public function getPossibleTypes() public function getPossibleTypes()
{ {
trigger_error(__METHOD__ . ' is deprecated in favor of ' . __CLASS__ . '::getTypes()', E_USER_DEPRECATED); trigger_error(__METHOD__ . ' is deprecated in favor of ' . __CLASS__ . '::getTypes()', E_USER_DEPRECATED);
@ -59,10 +70,10 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType
*/ */
public function getTypes() public function getTypes()
{ {
if ($this->_types instanceof \Closure) { if ($this->types instanceof \Closure) {
$this->_types = call_user_func($this->_types); $this->types = call_user_func($this->types);
} }
return $this->_types; return $this->types;
} }
/** /**
@ -75,13 +86,13 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType
return false; return false;
} }
if (null === $this->_possibleTypeNames) { if (null === $this->possibleTypeNames) {
$this->_possibleTypeNames = []; $this->possibleTypeNames = [];
foreach ($this->getTypes() as $possibleType) { foreach ($this->getTypes() as $possibleType) {
$this->_possibleTypeNames[$possibleType->name] = true; $this->possibleTypeNames[$possibleType->name] = true;
} }
} }
return isset($this->_possibleTypeNames[$type->name]); return isset($this->possibleTypeNames[$type->name]);
} }
/** /**
@ -89,6 +100,6 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType
*/ */
public function getResolveTypeFn() public function getResolveTypeFn()
{ {
return $this->_resolveTypeFn; return $this->resolveTypeFn;
} }
} }

View File

@ -1,9 +1,6 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
interface UnmodifiedType
{
/* /*
export type GraphQLUnmodifiedType = export type GraphQLUnmodifiedType =
GraphQLScalarType | GraphQLScalarType |
@ -13,4 +10,6 @@ GraphQLUnionType |
GraphQLEnumType | GraphQLEnumType |
GraphQLInputObjectType; GraphQLInputObjectType;
*/ */
interface UnmodifiedType
{
} }

View File

@ -1,12 +1,15 @@
<?php <?php
namespace GraphQL\Type\Definition; namespace GraphQL\Type\Definition;
interface WrappingType
{
/* /*
NonNullType NonNullType
ListOfType ListOfType
*/ */
interface WrappingType
{
/**
* @param bool $recurse
* @return Type
*/
public function getWrappedType($recurse = false); public function getWrappedType($recurse = false);
} }

View File

@ -32,7 +32,7 @@ class TypeKind {
class Introspection class Introspection
{ {
private static $_map = []; private static $map = [];
/** /**
* @return string * @return string
@ -198,8 +198,8 @@ EOD;
public static function _schema() public static function _schema()
{ {
if (!isset(self::$_map['__Schema'])) { if (!isset(self::$map['__Schema'])) {
self::$_map['__Schema'] = new ObjectType([ self::$map['__Schema'] = new ObjectType([
'name' => '__Schema', 'name' => '__Schema',
'description' => 'description' =>
'A GraphQL Schema defines the capabilities of a GraphQL ' . 'A GraphQL Schema defines the capabilities of a GraphQL ' .
@ -247,13 +247,13 @@ EOD;
] ]
]); ]);
} }
return self::$_map['__Schema']; return self::$map['__Schema'];
} }
public static function _directive() public static function _directive()
{ {
if (!isset(self::$_map['__Directive'])) { if (!isset(self::$map['__Directive'])) {
self::$_map['__Directive'] = new ObjectType([ self::$map['__Directive'] = new ObjectType([
'name' => '__Directive', 'name' => '__Directive',
'description' => 'A Directive provides a way to describe alternate runtime execution and ' . 'description' => 'A Directive provides a way to describe alternate runtime execution and ' .
'type validation behavior in a GraphQL document.' . 'type validation behavior in a GraphQL document.' .
@ -306,13 +306,13 @@ EOD;
] ]
]); ]);
} }
return self::$_map['__Directive']; return self::$map['__Directive'];
} }
public static function _directiveLocation() public static function _directiveLocation()
{ {
if (!isset(self::$_map['__DirectiveLocation'])) { if (!isset(self::$map['__DirectiveLocation'])) {
self::$_map['__DirectiveLocation'] = new EnumType([ self::$map['__DirectiveLocation'] = new EnumType([
'name' => '__DirectiveLocation', 'name' => '__DirectiveLocation',
'description' => 'description' =>
'A Directive can be adjacent to many parts of the GraphQL language, a ' . 'A Directive can be adjacent to many parts of the GraphQL language, a ' .
@ -349,13 +349,13 @@ EOD;
] ]
]); ]);
} }
return self::$_map['__DirectiveLocation']; return self::$map['__DirectiveLocation'];
} }
public static function _type() public static function _type()
{ {
if (!isset(self::$_map['__Type'])) { if (!isset(self::$map['__Type'])) {
self::$_map['__Type'] = new ObjectType([ self::$map['__Type'] = new ObjectType([
'name' => '__Type', 'name' => '__Type',
'description' => 'description' =>
'The fundamental unit of any GraphQL Schema is the type. There are ' . 'The fundamental unit of any GraphQL Schema is the type. There are ' .
@ -474,14 +474,14 @@ EOD;
} }
]); ]);
} }
return self::$_map['__Type']; return self::$map['__Type'];
} }
public static function _field() public static function _field()
{ {
if (!isset(self::$_map['__Field'])) { if (!isset(self::$map['__Field'])) {
self::$_map['__Field'] = new ObjectType([ self::$map['__Field'] = new ObjectType([
'name' => '__Field', 'name' => '__Field',
'description' => 'description' =>
'Object and Interface types are described by a list of Fields, each of ' . 'Object and Interface types are described by a list of Fields, each of ' .
@ -515,13 +515,13 @@ EOD;
} }
]); ]);
} }
return self::$_map['__Field']; return self::$map['__Field'];
} }
public static function _inputValue() public static function _inputValue()
{ {
if (!isset(self::$_map['__InputValue'])) { if (!isset(self::$map['__InputValue'])) {
self::$_map['__InputValue'] = new ObjectType([ self::$map['__InputValue'] = new ObjectType([
'name' => '__InputValue', 'name' => '__InputValue',
'description' => 'description' =>
'Arguments provided to Fields or Directives and the input fields of an ' . 'Arguments provided to Fields or Directives and the input fields of an ' .
@ -549,13 +549,13 @@ EOD;
} }
]); ]);
} }
return self::$_map['__InputValue']; return self::$map['__InputValue'];
} }
public static function _enumValue() public static function _enumValue()
{ {
if (!isset(self::$_map['__EnumValue'])) { if (!isset(self::$map['__EnumValue'])) {
self::$_map['__EnumValue'] = new ObjectType([ self::$map['__EnumValue'] = new ObjectType([
'name' => '__EnumValue', 'name' => '__EnumValue',
'description' => 'description' =>
'One possible value for a given Enum. Enum values are unique values, not ' . 'One possible value for a given Enum. Enum values are unique values, not ' .
@ -576,13 +576,13 @@ EOD;
] ]
]); ]);
} }
return self::$_map['__EnumValue']; return self::$map['__EnumValue'];
} }
public static function _typeKind() public static function _typeKind()
{ {
if (!isset(self::$_map['__TypeKind'])) { if (!isset(self::$map['__TypeKind'])) {
self::$_map['__TypeKind'] = new EnumType([ self::$map['__TypeKind'] = new EnumType([
'name' => '__TypeKind', 'name' => '__TypeKind',
'description' => 'An enum describing what kind of type a given __Type is.', 'description' => 'An enum describing what kind of type a given __Type is.',
'values' => [ 'values' => [
@ -621,13 +621,13 @@ EOD;
] ]
]); ]);
} }
return self::$_map['__TypeKind']; return self::$map['__TypeKind'];
} }
public static function schemaMetaFieldDef() public static function schemaMetaFieldDef()
{ {
if (!isset(self::$_map['__schema'])) { if (!isset(self::$map['__schema'])) {
self::$_map['__schema'] = FieldDefinition::create([ self::$map['__schema'] = FieldDefinition::create([
'name' => '__schema', 'name' => '__schema',
'type' => Type::nonNull(self::_schema()), 'type' => Type::nonNull(self::_schema()),
'description' => 'Access the current type schema of this server.', 'description' => 'Access the current type schema of this server.',
@ -642,13 +642,13 @@ EOD;
} }
]); ]);
} }
return self::$_map['__schema']; return self::$map['__schema'];
} }
public static function typeMetaFieldDef() public static function typeMetaFieldDef()
{ {
if (!isset(self::$_map['__type'])) { if (!isset(self::$map['__type'])) {
self::$_map['__type'] = FieldDefinition::create([ self::$map['__type'] = FieldDefinition::create([
'name' => '__type', 'name' => '__type',
'type' => self::_type(), 'type' => self::_type(),
'description' => 'Request the type information of a single type.', 'description' => 'Request the type information of a single type.',
@ -660,13 +660,13 @@ EOD;
} }
]); ]);
} }
return self::$_map['__type']; return self::$map['__type'];
} }
public static function typeNameMetaFieldDef() public static function typeNameMetaFieldDef()
{ {
if (!isset(self::$_map['__typename'])) { if (!isset(self::$map['__typename'])) {
self::$_map['__typename'] = FieldDefinition::create([ self::$map['__typename'] = FieldDefinition::create([
'name' => '__typename', 'name' => '__typename',
'type' => Type::nonNull(Type::string()), 'type' => Type::nonNull(Type::string()),
'description' => 'The name of the current Object type at runtime.', 'description' => 'The name of the current Object type at runtime.',
@ -681,6 +681,6 @@ EOD;
} }
]); ]);
} }
return self::$_map['__typename']; return self::$map['__typename'];
} }
} }

View File

@ -22,6 +22,10 @@ use GraphQL\Type\Definition\ScalarType;
use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\Type;
use GraphQL\Utils; use GraphQL\Utils;
/**
* Class AST
* @package GraphQL\Utils
*/
class AST class AST
{ {
/** /**

View File

@ -1,60 +1,86 @@
<?php <?php
namespace GraphQL\Utils; namespace GraphQL\Utils;
/**
* Class PairSet
* @package GraphQL\Utils
*/
class PairSet class PairSet
{ {
/** /**
* @var \SplObjectStorage<any, Set<any>> * @var \SplObjectStorage<any, Set<any>>
*/ */
private $_data; private $data;
private $_wrappers = []; /**
* @var array
*/
private $wrappers = [];
/**
* PairSet constructor.
*/
public function __construct() public function __construct()
{ {
$this->_data = new \SplObjectStorage(); // SplObject hash instead? $this->data = new \SplObjectStorage(); // SplObject hash instead?
} }
/**
* @param $a
* @param $b
* @return null|object
*/
public function has($a, $b) public function has($a, $b)
{ {
$a = $this->_toObj($a); $a = $this->toObj($a);
$b = $this->_toObj($b); $b = $this->toObj($b);
/** @var \SplObjectStorage $first */ /** @var \SplObjectStorage $first */
$first = isset($this->_data[$a]) ? $this->_data[$a] : null; $first = isset($this->data[$a]) ? $this->data[$a] : null;
return isset($first, $first[$b]) ? $first[$b] : null; return isset($first, $first[$b]) ? $first[$b] : null;
} }
/**
* @param $a
* @param $b
*/
public function add($a, $b) public function add($a, $b)
{ {
$this->_pairSetAdd($a, $b); $this->pairSetAdd($a, $b);
$this->_pairSetAdd($b, $a); $this->pairSetAdd($b, $a);
} }
private function _toObj($var) /**
* @param $var
* @return mixed
*/
private function toObj($var)
{ {
// SplObjectStorage expects objects, so wrapping non-objects to objects // SplObjectStorage expects objects, so wrapping non-objects to objects
if (is_object($var)) { if (is_object($var)) {
return $var; return $var;
} }
if (!isset($this->_wrappers[$var])) { if (!isset($this->wrappers[$var])) {
$tmp = new \stdClass(); $tmp = new \stdClass();
$tmp->_internal = $var; $tmp->_internal = $var;
$this->_wrappers[$var] = $tmp; $this->wrappers[$var] = $tmp;
} }
return $this->_wrappers[$var]; return $this->wrappers[$var];
} }
private function _pairSetAdd($a, $b) /**
* @param $a
* @param $b
*/
private function pairSetAdd($a, $b)
{ {
$a = $this->_toObj($a); $a = $this->toObj($a);
$b = $this->_toObj($b); $b = $this->toObj($b);
$set = isset($this->_data[$a]) ? $this->_data[$a] : null; $set = isset($this->data[$a]) ? $this->data[$a] : null;
if (!isset($set)) { if (!isset($set)) {
$set = new \SplObjectStorage(); $set = new \SplObjectStorage();
$this->_data[$a] = $set; $this->data[$a] = $set;
} }
$set[$b] = true; $set[$b] = true;
} }

View File

@ -23,6 +23,10 @@ use GraphQL\Type\Definition\UnionType;
use GraphQL\Type\Introspection; use GraphQL\Type\Introspection;
use GraphQL\Utils; use GraphQL\Utils;
/**
* Class TypeInfo
* @package GraphQL\Utils
*/
class TypeInfo class TypeInfo
{ {
/** /**
@ -163,7 +167,7 @@ class TypeInfo
* *
* @return FieldDefinition * @return FieldDefinition
*/ */
static private function _getFieldDef(Schema $schema, Type $parentType, Field $fieldAST) static private function getFieldDefinition(Schema $schema, Type $parentType, Field $fieldAST)
{ {
$name = $fieldAST->name->value; $name = $fieldAST->name->value;
$schemaMeta = Introspection::schemaMetaFieldDef(); $schemaMeta = Introspection::schemaMetaFieldDef();
@ -195,45 +199,49 @@ class TypeInfo
/** /**
* @var Schema * @var Schema
*/ */
private $_schema; private $schema;
/** /**
* @var \SplStack<OutputType> * @var \SplStack<OutputType>
*/ */
private $_typeStack; private $typeStack;
/** /**
* @var \SplStack<CompositeType> * @var \SplStack<CompositeType>
*/ */
private $_parentTypeStack; private $parentTypeStack;
/** /**
* @var \SplStack<InputType> * @var \SplStack<InputType>
*/ */
private $_inputTypeStack; private $inputTypeStack;
/** /**
* @var \SplStack<FieldDefinition> * @var \SplStack<FieldDefinition>
*/ */
private $_fieldDefStack; private $fieldDefStack;
/** /**
* @var Directive * @var Directive
*/ */
private $_directive; private $directive;
/** /**
* @var FieldArgument * @var FieldArgument
*/ */
private $_argument; private $argument;
/**
* TypeInfo constructor.
* @param Schema $schema
*/
public function __construct(Schema $schema) public function __construct(Schema $schema)
{ {
$this->_schema = $schema; $this->schema = $schema;
$this->_typeStack = []; $this->typeStack = [];
$this->_parentTypeStack = []; $this->parentTypeStack = [];
$this->_inputTypeStack = []; $this->inputTypeStack = [];
$this->_fieldDefStack = []; $this->fieldDefStack = [];
} }
/** /**
@ -241,8 +249,8 @@ class TypeInfo
*/ */
function getType() function getType()
{ {
if (!empty($this->_typeStack)) { if (!empty($this->typeStack)) {
return $this->_typeStack[count($this->_typeStack) - 1]; return $this->typeStack[count($this->typeStack) - 1];
} }
return null; return null;
} }
@ -252,8 +260,8 @@ class TypeInfo
*/ */
function getParentType() function getParentType()
{ {
if (!empty($this->_parentTypeStack)) { if (!empty($this->parentTypeStack)) {
return $this->_parentTypeStack[count($this->_parentTypeStack) - 1]; return $this->parentTypeStack[count($this->parentTypeStack) - 1];
} }
return null; return null;
} }
@ -263,8 +271,8 @@ class TypeInfo
*/ */
function getInputType() function getInputType()
{ {
if (!empty($this->_inputTypeStack)) { if (!empty($this->inputTypeStack)) {
return $this->_inputTypeStack[count($this->_inputTypeStack) - 1]; return $this->inputTypeStack[count($this->inputTypeStack) - 1];
} }
return null; return null;
} }
@ -274,8 +282,8 @@ class TypeInfo
*/ */
function getFieldDef() function getFieldDef()
{ {
if (!empty($this->_fieldDefStack)) { if (!empty($this->fieldDefStack)) {
return $this->_fieldDefStack[count($this->_fieldDefStack) - 1]; return $this->fieldDefStack[count($this->fieldDefStack) - 1];
} }
return null; return null;
} }
@ -285,7 +293,7 @@ class TypeInfo
*/ */
function getDirective() function getDirective()
{ {
return $this->_directive; return $this->directive;
} }
/** /**
@ -293,12 +301,15 @@ class TypeInfo
*/ */
function getArgument() function getArgument()
{ {
return $this->_argument; return $this->argument;
} }
/**
* @param Node $node
*/
function enter(Node $node) function enter(Node $node)
{ {
$schema = $this->_schema; $schema = $this->schema;
switch ($node->kind) { switch ($node->kind) {
case Node::SELECTION_SET: case Node::SELECTION_SET:
@ -308,21 +319,21 @@ class TypeInfo
// isCompositeType is a type refining predicate, so this is safe. // isCompositeType is a type refining predicate, so this is safe.
$compositeType = $namedType; $compositeType = $namedType;
} }
$this->_parentTypeStack[] = $compositeType; // push $this->parentTypeStack[] = $compositeType; // push
break; break;
case Node::FIELD: case Node::FIELD:
$parentType = $this->getParentType(); $parentType = $this->getParentType();
$fieldDef = null; $fieldDef = null;
if ($parentType) { if ($parentType) {
$fieldDef = self::_getFieldDef($schema, $parentType, $node); $fieldDef = self::getFieldDefinition($schema, $parentType, $node);
} }
$this->_fieldDefStack[] = $fieldDef; // push $this->fieldDefStack[] = $fieldDef; // push
$this->_typeStack[] = $fieldDef ? $fieldDef->getType() : null; // push $this->typeStack[] = $fieldDef ? $fieldDef->getType() : null; // push
break; break;
case Node::DIRECTIVE: case Node::DIRECTIVE:
$this->_directive = $schema->getDirective($node->name->value); $this->directive = $schema->getDirective($node->name->value);
break; break;
case Node::OPERATION_DEFINITION: case Node::OPERATION_DEFINITION:
@ -334,19 +345,19 @@ 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; // push
break; break;
case Node::INLINE_FRAGMENT: case Node::INLINE_FRAGMENT:
case Node::FRAGMENT_DEFINITION: case Node::FRAGMENT_DEFINITION:
$typeConditionAST = $node->typeCondition; $typeConditionAST = $node->typeCondition;
$outputType = $typeConditionAST ? self::typeFromAST($schema, $typeConditionAST) : $this->getType(); $outputType = $typeConditionAST ? self::typeFromAST($schema, $typeConditionAST) : $this->getType();
$this->_typeStack[] = $outputType; // push $this->typeStack[] = $outputType; // push
break; break;
case Node::VARIABLE_DEFINITION: case Node::VARIABLE_DEFINITION:
$inputType = self::typeFromAST($schema, $node->type); $inputType = self::typeFromAST($schema, $node->type);
$this->_inputTypeStack[] = $inputType; // push $this->inputTypeStack[] = $inputType; // push
break; break;
case Node::ARGUMENT: case Node::ARGUMENT:
@ -358,13 +369,13 @@ class TypeInfo
$argType = $argDef->getType(); $argType = $argDef->getType();
} }
} }
$this->_argument = $argDef; $this->argument = $argDef;
$this->_inputTypeStack[] = $argType; // push $this->inputTypeStack[] = $argType; // push
break; break;
case Node::LST: case Node::LST:
$listType = Type::getNullableType($this->getInputType()); $listType = Type::getNullableType($this->getInputType());
$this->_inputTypeStack[] = ($listType instanceof ListOfType ? $listType->getWrappedType() : null); // push $this->inputTypeStack[] = ($listType instanceof ListOfType ? $listType->getWrappedType() : null); // push
break; break;
case Node::OBJECT_FIELD: case Node::OBJECT_FIELD:
@ -375,42 +386,45 @@ class TypeInfo
$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; $fieldType = $inputField ? $inputField->getType() : null;
} }
$this->_inputTypeStack[] = $fieldType; $this->inputTypeStack[] = $fieldType;
break; break;
} }
} }
/**
* @param Node $node
*/
function leave(Node $node) function leave(Node $node)
{ {
switch ($node->kind) { switch ($node->kind) {
case Node::SELECTION_SET: case Node::SELECTION_SET:
array_pop($this->_parentTypeStack); array_pop($this->parentTypeStack);
break; break;
case Node::FIELD: case Node::FIELD:
array_pop($this->_fieldDefStack); array_pop($this->fieldDefStack);
array_pop($this->_typeStack); array_pop($this->typeStack);
break; break;
case Node::DIRECTIVE: case Node::DIRECTIVE:
$this->_directive = null; $this->directive = null;
break; break;
case Node::OPERATION_DEFINITION: case Node::OPERATION_DEFINITION:
case Node::INLINE_FRAGMENT: case Node::INLINE_FRAGMENT:
case Node::FRAGMENT_DEFINITION: case Node::FRAGMENT_DEFINITION:
array_pop($this->_typeStack); array_pop($this->typeStack);
break; break;
case Node::VARIABLE_DEFINITION: case Node::VARIABLE_DEFINITION:
array_pop($this->_inputTypeStack); array_pop($this->inputTypeStack);
break; break;
case Node::ARGUMENT: case Node::ARGUMENT:
$this->_argument = null; $this->argument = null;
array_pop($this->_inputTypeStack); array_pop($this->inputTypeStack);
break; break;
case Node::LST: case Node::LST:
case Node::OBJECT_FIELD: case Node::OBJECT_FIELD:
array_pop($this->_inputTypeStack); array_pop($this->inputTypeStack);
break; break;
} }
} }

View File

@ -17,7 +17,9 @@ abstract class AbstractQuerySecurity
{ {
const DISABLED = 0; const DISABLED = 0;
/** @var FragmentDefinition[] */ /**
* @var FragmentDefinition[]
*/
private $fragments = []; private $fragments = [];
/** /**

View File

@ -29,47 +29,47 @@ class ValidationContext
/** /**
* @var Schema * @var Schema
*/ */
private $_schema; private $schema;
/** /**
* @var Document * @var Document
*/ */
private $_ast; private $ast;
/** /**
* @var TypeInfo * @var TypeInfo
*/ */
private $_typeInfo; private $typeInfo;
/** /**
* @var Error[] * @var Error[]
*/ */
private $_errors; private $errors;
/** /**
* @var array<string, FragmentDefinition> * @var array<string, FragmentDefinition>
*/ */
private $_fragments; private $fragments;
/** /**
* @var SplObjectStorage * @var SplObjectStorage
*/ */
private $_fragmentSpreads; private $fragmentSpreads;
/** /**
* @var SplObjectStorage * @var SplObjectStorage
*/ */
private $_recursivelyReferencedFragments; private $recursivelyReferencedFragments;
/** /**
* @var SplObjectStorage * @var SplObjectStorage
*/ */
private $_variableUsages; private $variableUsages;
/** /**
* @var SplObjectStorage * @var SplObjectStorage
*/ */
private $_recursiveVariableUsages; private $recursiveVariableUsages;
/** /**
* ValidationContext constructor. * ValidationContext constructor.
@ -80,14 +80,14 @@ class ValidationContext
*/ */
function __construct(Schema $schema, Document $ast, TypeInfo $typeInfo) function __construct(Schema $schema, Document $ast, TypeInfo $typeInfo)
{ {
$this->_schema = $schema; $this->schema = $schema;
$this->_ast = $ast; $this->ast = $ast;
$this->_typeInfo = $typeInfo; $this->typeInfo = $typeInfo;
$this->_errors = []; $this->errors = [];
$this->_fragmentSpreads = new SplObjectStorage(); $this->fragmentSpreads = new SplObjectStorage();
$this->_recursivelyReferencedFragments = new SplObjectStorage(); $this->recursivelyReferencedFragments = new SplObjectStorage();
$this->_variableUsages = new SplObjectStorage(); $this->variableUsages = new SplObjectStorage();
$this->_recursiveVariableUsages = new SplObjectStorage(); $this->recursiveVariableUsages = new SplObjectStorage();
} }
/** /**
@ -95,7 +95,7 @@ class ValidationContext
*/ */
function reportError(Error $error) function reportError(Error $error)
{ {
$this->_errors[] = $error; $this->errors[] = $error;
} }
/** /**
@ -103,7 +103,7 @@ class ValidationContext
*/ */
function getErrors() function getErrors()
{ {
return $this->_errors; return $this->errors;
} }
/** /**
@ -111,7 +111,7 @@ class ValidationContext
*/ */
function getSchema() function getSchema()
{ {
return $this->_schema; return $this->schema;
} }
/** /**
@ -119,7 +119,7 @@ class ValidationContext
*/ */
function getDocument() function getDocument()
{ {
return $this->_ast; return $this->ast;
} }
/** /**
@ -128,9 +128,9 @@ class ValidationContext
*/ */
function getFragment($name) function getFragment($name)
{ {
$fragments = $this->_fragments; $fragments = $this->fragments;
if (!$fragments) { if (!$fragments) {
$this->_fragments = $fragments = $this->fragments = $fragments =
array_reduce($this->getDocument()->definitions, function($frags, $statement) { array_reduce($this->getDocument()->definitions, function($frags, $statement) {
if ($statement->kind === Node::FRAGMENT_DEFINITION) { if ($statement->kind === Node::FRAGMENT_DEFINITION) {
$frags[$statement->name->value] = $statement; $frags[$statement->name->value] = $statement;
@ -147,7 +147,7 @@ class ValidationContext
*/ */
function getFragmentSpreads(HasSelectionSet $node) function getFragmentSpreads(HasSelectionSet $node)
{ {
$spreads = isset($this->_fragmentSpreads[$node]) ? $this->_fragmentSpreads[$node] : null; $spreads = isset($this->fragmentSpreads[$node]) ? $this->fragmentSpreads[$node] : null;
if (!$spreads) { if (!$spreads) {
$spreads = []; $spreads = [];
$setsToVisit = [$node->selectionSet]; $setsToVisit = [$node->selectionSet];
@ -163,7 +163,7 @@ class ValidationContext
} }
} }
} }
$this->_fragmentSpreads[$node] = $spreads; $this->fragmentSpreads[$node] = $spreads;
} }
return $spreads; return $spreads;
} }
@ -174,7 +174,7 @@ class ValidationContext
*/ */
function getRecursivelyReferencedFragments(OperationDefinition $operation) function getRecursivelyReferencedFragments(OperationDefinition $operation)
{ {
$fragments = isset($this->_recursivelyReferencedFragments[$operation]) ? $this->_recursivelyReferencedFragments[$operation] : null; $fragments = isset($this->recursivelyReferencedFragments[$operation]) ? $this->recursivelyReferencedFragments[$operation] : null;
if (!$fragments) { if (!$fragments) {
$fragments = []; $fragments = [];
@ -196,7 +196,7 @@ class ValidationContext
} }
} }
} }
$this->_recursivelyReferencedFragments[$operation] = $fragments; $this->recursivelyReferencedFragments[$operation] = $fragments;
} }
return $fragments; return $fragments;
} }
@ -207,11 +207,11 @@ class ValidationContext
*/ */
function getVariableUsages(HasSelectionSet $node) function getVariableUsages(HasSelectionSet $node)
{ {
$usages = isset($this->_variableUsages[$node]) ? $this->_variableUsages[$node] : null; $usages = isset($this->variableUsages[$node]) ? $this->variableUsages[$node] : null;
if (!$usages) { if (!$usages) {
$newUsages = []; $newUsages = [];
$typeInfo = new TypeInfo($this->_schema); $typeInfo = new TypeInfo($this->schema);
Visitor::visit($node, Visitor::visitWithTypeInfo($typeInfo, [ Visitor::visit($node, Visitor::visitWithTypeInfo($typeInfo, [
Node::VARIABLE_DEFINITION => function () { Node::VARIABLE_DEFINITION => function () {
return false; return false;
@ -221,7 +221,7 @@ class ValidationContext
} }
])); ]));
$usages = $newUsages; $usages = $newUsages;
$this->_variableUsages[$node] = $usages; $this->variableUsages[$node] = $usages;
} }
return $usages; return $usages;
} }
@ -232,7 +232,7 @@ class ValidationContext
*/ */
function getRecursiveVariableUsages(OperationDefinition $operation) function getRecursiveVariableUsages(OperationDefinition $operation)
{ {
$usages = isset($this->_recursiveVariableUsages[$operation]) ? $this->_recursiveVariableUsages[$operation] : null; $usages = isset($this->recursiveVariableUsages[$operation]) ? $this->recursiveVariableUsages[$operation] : null;
if (!$usages) { if (!$usages) {
$usages = $this->getVariableUsages($operation); $usages = $this->getVariableUsages($operation);
@ -243,7 +243,7 @@ class ValidationContext
$tmp[] = $this->getVariableUsages($fragments[$i]); $tmp[] = $this->getVariableUsages($fragments[$i]);
} }
$usages = call_user_func_array('array_merge', $tmp); $usages = call_user_func_array('array_merge', $tmp);
$this->_recursiveVariableUsages[$operation] = $usages; $this->recursiveVariableUsages[$operation] = $usages;
} }
return $usages; return $usages;
} }
@ -255,7 +255,7 @@ class ValidationContext
*/ */
function getType() function getType()
{ {
return $this->_typeInfo->getType(); return $this->typeInfo->getType();
} }
/** /**
@ -263,7 +263,7 @@ class ValidationContext
*/ */
function getParentType() function getParentType()
{ {
return $this->_typeInfo->getParentType(); return $this->typeInfo->getParentType();
} }
/** /**
@ -271,7 +271,7 @@ class ValidationContext
*/ */
function getInputType() function getInputType()
{ {
return $this->_typeInfo->getInputType(); return $this->typeInfo->getInputType();
} }
/** /**
@ -279,16 +279,16 @@ class ValidationContext
*/ */
function getFieldDef() function getFieldDef()
{ {
return $this->_typeInfo->getFieldDef(); return $this->typeInfo->getFieldDef();
} }
function getDirective() function getDirective()
{ {
return $this->_typeInfo->getDirective(); return $this->typeInfo->getDirective();
} }
function getArgument() function getArgument()
{ {
return $this->_typeInfo->getArgument(); return $this->typeInfo->getArgument();
} }
} }