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 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
There are a few new breaking changes in v0.7.0 that were added to the graphql-js reference implementation

View File

@ -120,20 +120,24 @@ abstract class Node
*/
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)) {
$cloned = [];
foreach ($value as $key => $arrValue) {
$cloned[$key] = $this->_cloneValue($arrValue);
$cloned[$key] = $this->cloneValue($arrValue);
}
} else if ($value instanceof Node) {
$cloned = clone $value;
foreach (get_object_vars($cloned) as $prop => $propValue) {
$cloned->{$prop} = $this->_cloneValue($propValue);
$cloned->{$prop} = $this->cloneValue($propValue);
}
} else {
$cloned = $value;
@ -147,6 +151,11 @@ abstract class Node
*/
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;
/**
* Parser constructor.
* @param Source $source
* @param array $options
*/
function __construct(Source $source, array $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\Introspection;
/**
* Class Schema
* @package GraphQL
*/
class Schema
{
/**
* @var ObjectType
*/
protected $_queryType;
protected $queryType;
/**
* @var ObjectType
*/
protected $_mutationType;
protected $mutationType;
/**
* @var ObjectType
*/
protected $_subscriptionType;
protected $subscriptionType;
/**
* @var Directive[]
*/
protected $_directives;
protected $directives;
/**
* @var array<string, Type>
*/
protected $_typeMap;
protected $typeMap;
/**
* @var array<string, ObjectType[]>
*/
protected $_implementations;
protected $implementations;
/**
* @var array<string, array<string, boolean>>
*/
protected $_possibleTypeMap;
protected $possibleTypeMap;
/**
* 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 += [
'query' => null,
@ -88,19 +95,19 @@ class Schema
"Schema query must be Object Type but got: " . Utils::getVariableType($config['query'])
);
$this->_queryType = $config['query'];
$this->queryType = $config['query'];
Utils::invariant(
!$config['mutation'] || $config['mutation'] instanceof ObjectType,
"Schema mutation must be Object Type if provided but got: " . Utils::getVariableType($config['mutation'])
);
$this->_mutationType = $config['mutation'];
$this->mutationType = $config['mutation'];
Utils::invariant(
!$config['subscription'] || $config['subscription'] instanceof ObjectType,
"Schema subscription must be Object Type if provided but got: " . Utils::getVariableType($config['subscription'])
);
$this->_subscriptionType = $config['subscription'];
$this->subscriptionType = $config['subscription'];
Utils::invariant(
!$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'])
);
$this->_directives = array_merge($config['directives'], [
$this->directives = array_merge($config['directives'], [
Directive::includeDirective(),
Directive::skipDirective()
]);
@ -129,16 +136,16 @@ class Schema
}
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.
$this->_implementations = [];
foreach ($this->_typeMap as $typeName => $type) {
$this->implementations = [];
foreach ($this->typeMap as $typeName => $type) {
if ($type instanceof ObjectType) {
foreach ($type->getInterfaces() as $iface) {
$this->_implementations[$iface->name][] = $type;
$this->implementations[$iface->name][] = $type;
}
}
}
@ -149,7 +156,7 @@ class Schema
*/
public function getQueryType()
{
return $this->_queryType;
return $this->queryType;
}
/**
@ -157,7 +164,7 @@ class Schema
*/
public function getMutationType()
{
return $this->_mutationType;
return $this->mutationType;
}
/**
@ -165,7 +172,7 @@ class Schema
*/
public function getSubscriptionType()
{
return $this->_subscriptionType;
return $this->subscriptionType;
}
/**
@ -173,7 +180,7 @@ class Schema
*/
public function getTypeMap()
{
return $this->_typeMap;
return $this->typeMap;
}
/**
@ -196,7 +203,7 @@ class Schema
return $abstractType->getTypes();
}
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)
{
if (null === $this->_possibleTypeMap) {
$this->_possibleTypeMap = [];
if (null === $this->possibleTypeMap) {
$this->possibleTypeMap = [];
}
if (!isset($this->_possibleTypeMap[$abstractType->name])) {
if (!isset($this->possibleTypeMap[$abstractType->name])) {
$tmp = [];
foreach ($this->getPossibleTypes($abstractType) as $type) {
$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()
{
return $this->_directives;
return $this->directives;
}
/**
@ -243,24 +250,39 @@ class Schema
return null;
}
/**
* @param $type
* @deprecated since 17.10.2016 in favor of $this->extractTypes
* @return array
*/
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) {
return $this->_typeMap;
return $this->typeMap;
}
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(
$this->_typeMap[$type->name] === $type,
$this->typeMap[$type->name] === $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 = [];
@ -280,8 +302,8 @@ class Schema
}
}
foreach ($nestedTypes as $type) {
$this->_extractTypes($type);
$this->extractTypes($type);
}
return $this->_typeMap;
return $this->typeMap;
}
}

View File

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

View File

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

View File

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

View File

@ -3,6 +3,10 @@ namespace GraphQL\Type\Definition;
use GraphQL\Utils;
/**
* Class Config
* @package GraphQL\Type\Definition
*/
class Config
{
const BOOLEAN = 1;
@ -23,8 +27,14 @@ class Config
const KEY_AS_NAME = 131072;
const MAYBE_THUNK = 262144;
/**
* @var bool
*/
private static $enableValidation = false;
/**
* Disables config validation
*/
public static function disableValidation()
{
self::$enableValidation = false;
@ -39,11 +49,15 @@ class Config
self::$enableValidation = true;
}
/**
* @param array $config
* @param array $definition
*/
public static function validate(array $config, array $definition)
{
if (self::$enableValidation) {
$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;
}
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" : '';
@ -87,17 +107,25 @@ class Config
}
// 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));
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
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);
$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) {
$value += ['name' => $key];
}
self::_validateMap($typeName, $value, $def->definition, $pathStr);
self::validateMap($typeName, $value, $def->definition, $pathStr);
} else if (!empty($def->isArray)) {
if ($def->flags & self::REQUIRED) {
@ -132,9 +160,9 @@ class Config
if ($def->flags & self::KEY_AS_NAME) {
$arrValue += ['name' => $arrKey];
}
self::_validateMap($typeName, $arrValue, $def->definition, "$pathStr:$arrKey");
self::validateMap($typeName, $arrValue, $def->definition, "$pathStr:$arrKey");
} else {
self::_validateEntry($typeName, $arrKey, $arrValue, $def->definition, "$pathStr:$arrKey");
self::validateEntry($typeName, $arrKey, $arrValue, $def->definition, "$pathStr:$arrKey");
}
}
} 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;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -2,8 +2,6 @@
namespace GraphQL\Type\Definition;
use GraphQL\Utils;
/**
* Class FieldArgument
*
@ -17,13 +15,6 @@ class FieldArgument
*/
public $name;
/**
* @var InputType
*/
private $type;
private $resolvedType;
/**
* @var mixed
*/
@ -34,6 +25,25 @@ class FieldArgument
*/
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)
{
$map = [];
@ -43,13 +53,30 @@ class FieldArgument
return $map;
}
/**
* FieldArgument constructor.
* @param array $def
*/
public function __construct(array $def)
{
foreach ($def as $key => $value) {
$this->{$key} = $value;
}
$def += [
'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()
{
if (null === $this->resolvedType) {

View File

@ -1,8 +1,11 @@
<?php
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
{
const DEFAULT_COMPLEXITY_FN = 'GraphQL\Type\Definition\FieldDefinition::defaultComplexity';
@ -12,16 +15,6 @@ class FieldDefinition
*/
public $name;
/**
* @var OutputType
*/
private $type;
/**
* @var OutputType
*/
private $resolvedType;
/**
* @var array<GraphQLFieldArgument>
*/
@ -60,8 +53,21 @@ class FieldDefinition
*/
public $config;
/**
* @var OutputType|callable
*/
private $type;
/**
* @var OutputType
*/
private $resolvedType;
private static $def;
/**
* @return array
*/
public static function getDefinition()
{
return self::$def ?: (self::$def = [
@ -107,6 +113,10 @@ class FieldDefinition
return new self($field);
}
/**
* FieldDefinition constructor.
* @param array $config
*/
protected function __construct(array $config)
{
$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
*/
public function getType()
@ -150,6 +161,14 @@ class FieldDefinition
return $this->resolvedType;
}
/**
* @return bool
*/
public function isDeprecated()
{
return !!$this->deprecationReason;
}
/**
* @return callable|\Closure
*/
@ -158,6 +177,10 @@ class FieldDefinition
return $this->complexityFn;
}
/**
* @param $childrenComplexity
* @return mixed
*/
public static function defaultComplexity($childrenComplexity)
{
return $childrenComplexity + 1;

View File

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

View File

@ -1,8 +1,10 @@
<?php
namespace GraphQL\Type\Definition;
use GraphQL\Utils;
/**
* Class InputObjectField
* @package GraphQL\Type\Definition
*/
class InputObjectField
{
/**
@ -10,11 +12,6 @@ class InputObjectField
*/
public $name;
/**
* @var callback|InputType
*/
private $type;
/**
* @var mixed|null
*/
@ -25,6 +22,15 @@ class InputObjectField
*/
public $description;
/**
* @var callback|InputType
*/
public $type;
/**
* InputObjectField constructor.
* @param array $opts
*/
public function __construct(array $opts)
{
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()
{
return Type::resolve($this->type);

View File

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

View File

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

View File

@ -4,6 +4,10 @@ namespace GraphQL\Type\Definition;
use GraphQL\Language\AST\IntValue;
use GraphQL\Language\AST\Value;
/**
* Class IntType
* @package GraphQL\Type\Definition
*/
class IntType extends ScalarType
{
// 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 MIN_INT = -2147483648;
/**
* @var string
*/
public $name = Type::INT;
/**
* @var string
*/
public $description =
'The `Int` scalar type represents non-fractional signed whole numeric
values. Int can represent values between -(2^31) and 2^31 - 1. ';
/**
* @param mixed $value
* @return int|null
*/
public function serialize($value)
{
return $this->coerceInt($value);
}
/**
* @param mixed $value
* @return int|null
*/
public function parseValue($value)
{
return $this->coerceInt($value);
}
/**
* @param $value
* @return int|null
*/
private function coerceInt($value)
{
if (false === $value || true === $value) {
@ -41,6 +63,10 @@ values. Int can represent values between -(2^31) and 2^31 - 1. ';
return null;
}
/**
* @param $ast
* @return int|null
*/
public function parseLiteral($ast)
{
if ($ast instanceof IntValue) {

View File

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

View File

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

View File

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

View File

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

View File

@ -11,19 +11,19 @@ use GraphQL\Utils;
*
* Example:
*
* var AddressType = new GraphQLObjectType({
* name: 'Address',
* fields: {
* street: { type: GraphQLString },
* number: { type: GraphQLInt },
* formatted: {
* type: GraphQLString,
* resolve(obj) {
* return obj.number + ' ' + obj.street
* $AddressType = new ObjectType([
* 'name' => 'Address',
* 'fields' => [
* 'street' => [ 'type' => GraphQL\Type\Definition\Type::string() ],
* 'number' => [ 'type' => GraphQL\Type\Definition\Type::int() ],
* 'formatted' => [
* 'type' => GraphQL\Type\Definition\Type::string(),
* 'resolve' => function($obj) {
* return $obj->number . ' ' . $obj->street;
* }
* }
* }
* });
* ]
* ]
* ]);
*
* 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
@ -31,31 +31,34 @@ use GraphQL\Utils;
*
* Example:
*
* var PersonType = new GraphQLObjectType({
* name: 'Person',
* fields: () => ({
* name: { type: GraphQLString },
* bestFriend: { type: PersonType },
* })
* });
* $PersonType = null;
* $PersonType = new ObjectType([
* 'name' => 'Person',
* 'fields' => function() use (&$PersonType) {
* return [
* 'name' => ['type' => GraphQL\Type\Definition\Type::string() ],
* 'bestFriend' => [ 'type' => $PersonType ],
* ];
* }
* ]);
*
*/
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
*/
private $_isTypeOf;
private $isTypeOf;
/**
* 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;
/**
* ObjectType constructor.
* @param array $config
*/
public function __construct(array $config)
{
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->description = isset($config['description']) ? $config['description'] : 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;
}
@ -102,12 +109,12 @@ class ObjectType extends Type implements OutputType, CompositeType
*/
public function getFields()
{
if (null === $this->_fields) {
if (null === $this->fields) {
$fields = isset($this->config['fields']) ? $this->config['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)
{
if (null === $this->_fields) {
if (null === $this->fields) {
$this->getFields();
}
Utils::invariant(isset($this->_fields[$name]), "Field '%s' is not defined for type '%s'", $name, $this->name);
return $this->_fields[$name];
Utils::invariant(isset($this->fields[$name]), "Field '%s' is not defined for type '%s'", $name, $this->name);
return $this->fields[$name];
}
/**
* @return array<InterfaceType>
* @return InterfaceType[]
*/
public function getInterfaces()
{
if (null === $this->_interfaces) {
if (null === $this->interfaces) {
$interfaces = isset($this->config['interfaces']) ? $this->config['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)
{
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;
interface OutputType
{
/*
GraphQLScalarType |
GraphQLObjectType |
@ -13,4 +11,6 @@ GraphQLEnumType |
GraphQLList |
GraphQLNonNull;
*/
interface OutputType
{
}

View File

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

View File

@ -12,24 +12,46 @@ use GraphQL\Utils;
*
* Example:
*
* var OddType = new GraphQLScalarType({
* name: 'Odd',
* serialize(value) {
* return value % 2 === 1 ? value : null;
* class OddType extends ScalarType
* {
* public $name = 'Odd',
* 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()
{
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);
/**
* Parses an externally provided value to use as an input
*
* @param mixed $value
* @return mixed
*/
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);
}

View File

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

View File

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

View File

@ -3,28 +3,36 @@ namespace GraphQL\Type\Definition;
use GraphQL\Utils;
/**
* Class UnionType
* @package GraphQL\Type\Definition
*/
class UnionType extends Type implements AbstractType, OutputType, CompositeType
{
/**
* @var ObjectType[]
*/
private $_types;
private $types;
/**
* @var array<string, ObjectType>
*/
private $_possibleTypeNames;
private $possibleTypeNames;
/**
* @var callback
*/
private $_resolveTypeFn;
private $resolveTypeFn;
/**
* @var array
*/
private $_config;
public $config;
/**
* UnionType constructor.
* @param $config
*/
public function __construct($config)
{
Config::validate($config, [
@ -43,11 +51,14 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType
*/
$this->name = $config['name'];
$this->description = isset($config['description']) ? $config['description'] : null;
$this->_types = $config['types'];
$this->_resolveTypeFn = isset($config['resolveType']) ? $config['resolveType'] : null;
$this->_config = $config;
$this->types = $config['types'];
$this->resolveTypeFn = isset($config['resolveType']) ? $config['resolveType'] : null;
$this->config = $config;
}
/**
* @return ObjectType[]
*/
public function getPossibleTypes()
{
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()
{
if ($this->_types instanceof \Closure) {
$this->_types = call_user_func($this->_types);
if ($this->types instanceof \Closure) {
$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;
}
if (null === $this->_possibleTypeNames) {
$this->_possibleTypeNames = [];
if (null === $this->possibleTypeNames) {
$this->possibleTypeNames = [];
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()
{
return $this->_resolveTypeFn;
return $this->resolveTypeFn;
}
}

View File

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

View File

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

View File

@ -32,7 +32,7 @@ class TypeKind {
class Introspection
{
private static $_map = [];
private static $map = [];
/**
* @return string
@ -198,8 +198,8 @@ EOD;
public static function _schema()
{
if (!isset(self::$_map['__Schema'])) {
self::$_map['__Schema'] = new ObjectType([
if (!isset(self::$map['__Schema'])) {
self::$map['__Schema'] = new ObjectType([
'name' => '__Schema',
'description' =>
'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()
{
if (!isset(self::$_map['__Directive'])) {
self::$_map['__Directive'] = new ObjectType([
if (!isset(self::$map['__Directive'])) {
self::$map['__Directive'] = new ObjectType([
'name' => '__Directive',
'description' => 'A Directive provides a way to describe alternate runtime execution and ' .
'type validation behavior in a GraphQL document.' .
@ -306,13 +306,13 @@ EOD;
]
]);
}
return self::$_map['__Directive'];
return self::$map['__Directive'];
}
public static function _directiveLocation()
{
if (!isset(self::$_map['__DirectiveLocation'])) {
self::$_map['__DirectiveLocation'] = new EnumType([
if (!isset(self::$map['__DirectiveLocation'])) {
self::$map['__DirectiveLocation'] = new EnumType([
'name' => '__DirectiveLocation',
'description' =>
'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()
{
if (!isset(self::$_map['__Type'])) {
self::$_map['__Type'] = new ObjectType([
if (!isset(self::$map['__Type'])) {
self::$map['__Type'] = new ObjectType([
'name' => '__Type',
'description' =>
'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()
{
if (!isset(self::$_map['__Field'])) {
if (!isset(self::$map['__Field'])) {
self::$_map['__Field'] = new ObjectType([
self::$map['__Field'] = new ObjectType([
'name' => '__Field',
'description' =>
'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()
{
if (!isset(self::$_map['__InputValue'])) {
self::$_map['__InputValue'] = new ObjectType([
if (!isset(self::$map['__InputValue'])) {
self::$map['__InputValue'] = new ObjectType([
'name' => '__InputValue',
'description' =>
'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()
{
if (!isset(self::$_map['__EnumValue'])) {
self::$_map['__EnumValue'] = new ObjectType([
if (!isset(self::$map['__EnumValue'])) {
self::$map['__EnumValue'] = new ObjectType([
'name' => '__EnumValue',
'description' =>
'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()
{
if (!isset(self::$_map['__TypeKind'])) {
self::$_map['__TypeKind'] = new EnumType([
if (!isset(self::$map['__TypeKind'])) {
self::$map['__TypeKind'] = new EnumType([
'name' => '__TypeKind',
'description' => 'An enum describing what kind of type a given __Type is.',
'values' => [
@ -621,13 +621,13 @@ EOD;
]
]);
}
return self::$_map['__TypeKind'];
return self::$map['__TypeKind'];
}
public static function schemaMetaFieldDef()
{
if (!isset(self::$_map['__schema'])) {
self::$_map['__schema'] = FieldDefinition::create([
if (!isset(self::$map['__schema'])) {
self::$map['__schema'] = FieldDefinition::create([
'name' => '__schema',
'type' => Type::nonNull(self::_schema()),
'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()
{
if (!isset(self::$_map['__type'])) {
self::$_map['__type'] = FieldDefinition::create([
if (!isset(self::$map['__type'])) {
self::$map['__type'] = FieldDefinition::create([
'name' => '__type',
'type' => self::_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()
{
if (!isset(self::$_map['__typename'])) {
self::$_map['__typename'] = FieldDefinition::create([
if (!isset(self::$map['__typename'])) {
self::$map['__typename'] = FieldDefinition::create([
'name' => '__typename',
'type' => Type::nonNull(Type::string()),
'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\Utils;
/**
* Class AST
* @package GraphQL\Utils
*/
class AST
{
/**

View File

@ -1,60 +1,86 @@
<?php
namespace GraphQL\Utils;
/**
* Class PairSet
* @package GraphQL\Utils
*/
class PairSet
{
/**
* @var \SplObjectStorage<any, Set<any>>
*/
private $_data;
private $data;
private $_wrappers = [];
/**
* @var array
*/
private $wrappers = [];
/**
* PairSet constructor.
*/
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)
{
$a = $this->_toObj($a);
$b = $this->_toObj($b);
$a = $this->toObj($a);
$b = $this->toObj($b);
/** @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;
}
/**
* @param $a
* @param $b
*/
public function add($a, $b)
{
$this->_pairSetAdd($a, $b);
$this->_pairSetAdd($b, $a);
$this->pairSetAdd($a, $b);
$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
if (is_object($var)) {
return $var;
}
if (!isset($this->_wrappers[$var])) {
if (!isset($this->wrappers[$var])) {
$tmp = new \stdClass();
$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);
$b = $this->_toObj($b);
$set = isset($this->_data[$a]) ? $this->_data[$a] : null;
$a = $this->toObj($a);
$b = $this->toObj($b);
$set = isset($this->data[$a]) ? $this->data[$a] : null;
if (!isset($set)) {
$set = new \SplObjectStorage();
$this->_data[$a] = $set;
$this->data[$a] = $set;
}
$set[$b] = true;
}

View File

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

View File

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

View File

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