Moved Schema to GraphQL\Type namespace (but preserved BC)

This commit is contained in:
Vladimir Razuvaev 2017-08-12 21:32:07 +07:00
parent 2c8c7baa87
commit d3580e959e
20 changed files with 424 additions and 390 deletions

View File

@ -12,7 +12,7 @@ but make sure to restrict it to debug/development mode only.
**graphql-php** expects that each type in Schema is presented by single instance. Therefore **graphql-php** expects that each type in Schema is presented by single instance. Therefore
if you define your types as separate PHP classes you need to ensure that each type is referenced only once. if you define your types as separate PHP classes you need to ensure that each type is referenced only once.
Technically you can create several instances of your type (for example for tests), but `GraphQL\Schema` Technically you can create several instances of your type (for example for tests), but `GraphQL\Type\Schema`
will throw on attempt to add different instances with the same name. will throw on attempt to add different instances with the same name.
There are several ways to achieve this depending on your preferences. We provide reference There are several ways to achieve this depending on your preferences. We provide reference

View File

@ -27,7 +27,7 @@ Description of method arguments:
Argument | Type | Notes Argument | Type | Notes
------------ | -------- | ----- ------------ | -------- | -----
schema | `GraphQL\Schema` | **Required.** Instance of your application [Schema](type-system/schema/) schema | `GraphQL\Type\Schema` | **Required.** Instance of your application [Schema](type-system/schema/)
queryString | `string` or `GraphQL\Language\AST\DocumentNode` | **Required.** Actual GraphQL query string to be parsed, validated and executed. If you parse query elsewhere before executing - pass corresponding ast document here to avoid new parsing. queryString | `string` or `GraphQL\Language\AST\DocumentNode` | **Required.** Actual GraphQL query string to be parsed, validated and executed. If you parse query elsewhere before executing - pass corresponding ast document here to avoid new parsing.
rootValue | `mixed` | Any value that represents a root of your data graph. It is passed as 1st argument to field resolvers of [Query type](type-system/schema/#query-and-mutation-types). Can be omitted or set to null if actual root values are fetched by Query type itself. rootValue | `mixed` | Any value that represents a root of your data graph. It is passed as 1st argument to field resolvers of [Query type](type-system/schema/#query-and-mutation-types). Can be omitted or set to null if actual root values are fetched by Query type itself.
contextValue | `mixed` | Any value that holds information shared between all field resolvers. Most often they use it to pass currently logged in user, locale details, etc.<br><br>It will be available as 3rd argument in all field resolvers. (see section on [Field Definitions](type-system/object-types/#field-configuration-options) for reference) **graphql-php** never modifies this value and passes it *as is* to all underlying resolvers. contextValue | `mixed` | Any value that holds information shared between all field resolvers. Most often they use it to pass currently logged in user, locale details, etc.<br><br>It will be available as 3rd argument in all field resolvers. (see section on [Field Definitions](type-system/object-types/#field-configuration-options) for reference) **graphql-php** never modifies this value and passes it *as is* to all underlying resolvers.

View File

@ -75,7 +75,7 @@ Now when our type is ready, let's create GraphQL endpoint for it `graphql.php`:
```php ```php
<?php <?php
use GraphQL\GraphQL; use GraphQL\GraphQL;
use GraphQL\Schema; use GraphQL\Type\Schema;
$schema = new Schema([ $schema = new Schema([
'query' => $queryType 'query' => $queryType

View File

@ -2,7 +2,7 @@
Schema is a container of your type hierarchy, which accepts root types in constructor and provides Schema is a container of your type hierarchy, which accepts root types in constructor and provides
methods for receiving information about your types to internal GrahpQL tools. methods for receiving information about your types to internal GrahpQL tools.
In **graphql-php** schema is an instance of `GraphQL\Schema` which accepts configuration array In **graphql-php** schema is an instance of `GraphQL\Type\Schema` which accepts configuration array
in constructor: in constructor:
```php ```php
@ -25,7 +25,7 @@ of your API:
```php ```php
use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\Type;
use GraphQL\Schema; use GraphQL\Type\Schema;
$queryType = new ObjectType([ $queryType = new ObjectType([
'name' => 'Query', 'name' => 'Query',

View File

@ -4,7 +4,7 @@ namespace GraphQL\Executor;
use GraphQL\Error\Error; use GraphQL\Error\Error;
use GraphQL\Language\AST\FragmentDefinitionNode; use GraphQL\Language\AST\FragmentDefinitionNode;
use GraphQL\Language\AST\OperationDefinitionNode; use GraphQL\Language\AST\OperationDefinitionNode;
use GraphQL\Schema; use GraphQL\Type\Schema;
/** /**
* Data that must be available at all points during query execution. * Data that must be available at all points during query execution.

View File

@ -15,7 +15,7 @@ use GraphQL\Language\AST\NodeKind;
use GraphQL\Language\AST\OperationDefinitionNode; use GraphQL\Language\AST\OperationDefinitionNode;
use GraphQL\Language\AST\SelectionSetNode; use GraphQL\Language\AST\SelectionSetNode;
use GraphQL\Executor\Promise\PromiseAdapter; use GraphQL\Executor\Promise\PromiseAdapter;
use GraphQL\Schema; use GraphQL\Type\Schema;
use GraphQL\Type\Definition\AbstractType; use GraphQL\Type\Definition\AbstractType;
use GraphQL\Type\Definition\Directive; use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\FieldDefinition; use GraphQL\Type\Definition\FieldDefinition;

View File

@ -15,7 +15,7 @@ use GraphQL\Language\AST\NodeList;
use GraphQL\Language\AST\VariableNode; use GraphQL\Language\AST\VariableNode;
use GraphQL\Language\AST\VariableDefinitionNode; use GraphQL\Language\AST\VariableDefinitionNode;
use GraphQL\Language\Printer; use GraphQL\Language\Printer;
use GraphQL\Schema; use GraphQL\Type\Schema;
use GraphQL\Type\Definition\Directive; use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\FieldDefinition; use GraphQL\Type\Definition\FieldDefinition;
use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InputObjectType;

View File

@ -48,7 +48,7 @@ class GraphQL
* Empty array would allow to skip query validation (may be convenient for persisted * Empty array would allow to skip query validation (may be convenient for persisted
* queries which are validated before persisting and assumed valid during execution) * queries which are validated before persisting and assumed valid during execution)
* *
* @param Schema $schema * @param \GraphQL\Type\Schema $schema
* @param string|DocumentNode $source * @param string|DocumentNode $source
* @param mixed $rootValue * @param mixed $rootValue
* @param array $contextValue * @param array $contextValue
@ -61,7 +61,7 @@ class GraphQL
* @return Promise|array * @return Promise|array
*/ */
public static function execute( public static function execute(
Schema $schema, \GraphQL\Type\Schema $schema,
$source, $source,
$rootValue = null, $rootValue = null,
$contextValue = null, $contextValue = null,
@ -99,7 +99,7 @@ class GraphQL
* Same as `execute`, but returns instance of ExecutionResult instead of array, * Same as `execute`, but returns instance of ExecutionResult instead of array,
* which can be used for custom error formatting or adding extensions to response * which can be used for custom error formatting or adding extensions to response
* *
* @param Schema $schema * @param \GraphQL\Type\Schema $schema
* @param string|DocumentNode $source * @param string|DocumentNode $source
* @param mixed $rootValue * @param mixed $rootValue
* @param mixed $contextValue * @param mixed $contextValue
@ -112,7 +112,7 @@ class GraphQL
* @return ExecutionResult|Promise * @return ExecutionResult|Promise
*/ */
public static function executeAndReturnResult( public static function executeAndReturnResult(
Schema $schema, \GraphQL\Type\Schema $schema,
$source, $source,
$rootValue = null, $rootValue = null,
$contextValue = null, $contextValue = null,

View File

@ -1,16 +1,6 @@
<?php <?php
namespace GraphQL; namespace GraphQL;
use GraphQL\Type\Descriptor;
use GraphQL\Type\Definition\AbstractType;
use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType;
use GraphQL\Type\Introspection;
use GraphQL\Utils\TypeInfo;
use GraphQL\Utils\Utils;
/** /**
* Schema Definition * Schema Definition
@ -38,353 +28,8 @@ use GraphQL\Utils\Utils;
* ]) * ])
* *
* @package GraphQL * @package GraphQL
* @deprecated moved to GraphQL\Type\Schema
*/ */
class Schema class Schema extends \GraphQL\Type\Schema
{ {
/**
* @var Config
*/
private $config;
/**
* Contains actual descriptor for this schema
*
* @var Descriptor
*/
private $descriptor;
/**
* Contains currently resolved schema types
*
* @var Type[]
*/
private $resolvedTypes = [];
/**
* True when $resolvedTypes contain all possible schema types
*
* @var bool
*/
private $fullyLoaded = false;
/**
* Schema constructor.
*
* @param array|Config $config
*/
public function __construct($config = null)
{
if (func_num_args() > 1 || $config instanceof Type) {
trigger_error(
'GraphQL\Schema constructor expects config object now instead of types passed as arguments. '.
'See https://github.com/webonyx/graphql-php/issues/36',
E_USER_DEPRECATED
);
list($queryType, $mutationType, $subscriptionType) = func_get_args() + [null, null, null];
$config = [
'query' => $queryType,
'mutation' => $mutationType,
'subscription' => $subscriptionType
];
}
if (is_array($config)) {
$config = Config::create($config);
}
Utils::invariant(
$config instanceof Config,
'Schema constructor expects instance of GraphQL\Schema\Config or an array with keys: %s; but got: %s',
implode(', ', [
'query',
'mutation',
'subscription',
'types',
'directives',
'typeLoader',
'descriptor'
]),
Utils::getVariableType($config)
);
Utils::invariant(
$config->query instanceof ObjectType,
"Schema query must be Object Type but got: " . Utils::getVariableType($config->query)
);
$this->config = $config;
}
/**
* Returns schema query type
*
* @return ObjectType
*/
public function getQueryType()
{
return $this->config->query;
}
/**
* Returns schema mutation type
*
* @return ObjectType|null
*/
public function getMutationType()
{
return $this->config->mutation;
}
/**
* Returns schema subscription
*
* @return ObjectType|null
*/
public function getSubscriptionType()
{
return $this->config->subscription;
}
/**
* @return Config
*/
public function getConfig()
{
return $this->config;
}
/**
* Returns array of all types in this schema. Keys of this array represent type names, values are instances
* of corresponding type definitions
*
* @return Type[]
*/
public function getTypeMap()
{
if (!$this->fullyLoaded) {
if ($this->config->descriptor && $this->config->typeLoader) {
// Following is still faster than $this->collectAllTypes() because it won't init fields
$typesToResolve = array_diff_key($this->config->descriptor->typeMap, $this->resolvedTypes);
foreach ($typesToResolve as $typeName => $_) {
$this->resolvedTypes[$typeName] = $this->loadType($typeName);
}
} else {
$this->resolvedTypes = $this->collectAllTypes();
}
$this->fullyLoaded = true;
}
return $this->resolvedTypes;
}
/**
* Returns type by it's name
*
* @param string $name
* @return Type
*/
public function getType($name)
{
return $this->resolveType($name);
}
/**
* Returns serializable schema descriptor which can be passed later
* to Schema config to enable a set of performance optimizations
*
* @return Descriptor
*/
public function describe()
{
if ($this->descriptor) {
return $this->descriptor;
}
$this->resolvedTypes = $this->collectAllTypes();
$this->fullyLoaded = true;
$descriptor = new Descriptor();
$descriptor->version = '1.0';
$descriptor->created = time();
foreach ($this->resolvedTypes as $type) {
if ($type instanceof ObjectType) {
foreach ($type->getInterfaces() as $interface) {
$descriptor->possibleTypeMap[$interface->name][$type->name] = 1;
}
} else if ($type instanceof UnionType) {
foreach ($type->getTypes() as $innerType) {
$descriptor->possibleTypeMap[$type->name][$innerType->name] = 1;
}
}
$descriptor->typeMap[$type->name] = 1;
}
return $this->descriptor = $descriptor;
}
private function collectAllTypes()
{
$initialTypes = array_merge(
[
$this->config->query,
$this->config->mutation,
$this->config->subscription,
Introspection::_schema()
],
array_values($this->resolvedTypes)
);
$typeMap = [];
foreach ($initialTypes as $type) {
$typeMap = TypeInfo::extractTypes($type, $typeMap);
}
$types = $this->config->types;
if (is_callable($types)) {
$types = $types();
Utils::invariant(
is_array($types) || $types instanceof \Traversable,
'Schema types callable must return array or instance of Traversable but got: %s',
Utils::getVariableType($types)
);
}
if (!empty($types)) {
foreach ($types as $type) {
Utils::invariant(
$type instanceof Type,
'Each entry of schema types must be instance of GraphQL\Type\Definition\Type but got: %s',
Utils::getVariableType($types)
);
$typeMap = TypeInfo::extractTypes($type, $typeMap);
}
}
return $typeMap + Type::getInternalTypes();
}
/**
* Returns all possible concrete types for given abstract type
* (implementations for interfaces and members of union type for unions)
*
* @param AbstractType $abstractType
* @return ObjectType[]
*/
public function getPossibleTypes(AbstractType $abstractType)
{
if ($abstractType instanceof UnionType) {
return $abstractType->getTypes();
}
/** @var InterfaceType $abstractType */
$descriptor = $this->config->descriptor ?: $this->describe();
$result = [];
if (isset($descriptor->possibleTypeMap[$abstractType->name])) {
foreach ($descriptor->possibleTypeMap[$abstractType->name] as $typeName => $_) {
$result[] = $this->resolveType($typeName);
}
}
return $result;
}
/**
* Accepts name of type or type instance and returns type instance. If type with given name is not loaded yet -
* will load it first.
*
* @param $typeOrName
* @return Type
*/
public function resolveType($typeOrName)
{
if ($typeOrName instanceof Type) {
if ($typeOrName->name && !isset($this->resolvedTypes[$typeOrName->name])) {
$this->resolvedTypes[$typeOrName->name] = $typeOrName;
}
return $typeOrName;
}
if (!isset($this->resolvedTypes[$typeOrName])) {
$this->resolvedTypes[$typeOrName] = $this->loadType($typeOrName);
}
return $this->resolvedTypes[$typeOrName];
}
private function loadType($typeName)
{
$typeLoader = $this->config->typeLoader;
if (!$typeLoader) {
return $this->defaultTypeLoader($typeName);
}
$type = $typeLoader($typeName);
// TODO: validate returned value
return $type;
}
/**
* Returns true if object type is concrete type of given abstract type
* (implementation for interfaces and members of union type for unions)
*
* @param AbstractType $abstractType
* @param ObjectType $possibleType
* @return bool
*/
public function isPossibleType(AbstractType $abstractType, ObjectType $possibleType)
{
if ($this->config->descriptor) {
return !empty($this->config->descriptor->possibleTypeMap[$abstractType->name][$possibleType->name]);
}
if ($abstractType instanceof InterfaceType) {
return $possibleType->implementsInterface($abstractType);
}
/** @var UnionType $abstractType */
return $abstractType->isPossibleType($possibleType);
}
/**
* Returns a list of directives supported by this schema
*
* @return Directive[]
*/
public function getDirectives()
{
return $this->config->directives ?: GraphQL::getInternalDirectives();
}
/**
* Returns instance of directive by name
*
* @param $name
* @return Directive
*/
public function getDirective($name)
{
foreach ($this->getDirectives() as $directive) {
if ($directive->name === $name) {
return $directive;
}
}
return null;
}
/**
* @param $typeName
* @return Type
*/
private function defaultTypeLoader($typeName)
{
// Default type loader simply fallbacks to collecting all types
if (!$this->fullyLoaded) {
$this->resolvedTypes = $this->collectAllTypes();
$this->fullyLoaded = true;
}
if (!isset($this->resolvedTypes[$typeName])) {
return null;
}
return $this->resolvedTypes[$typeName];
}
} }

View File

@ -1,10 +1,9 @@
<?php <?php
namespace GraphQL\Server; namespace GraphQL\Server;
use GraphQL\Error\FormattedError;
use GraphQL\Error\InvariantViolation; use GraphQL\Error\InvariantViolation;
use GraphQL\Executor\Promise\PromiseAdapter; use GraphQL\Executor\Promise\PromiseAdapter;
use GraphQL\Schema; use GraphQL\Type\Schema;
use GraphQL\Utils\Utils; use GraphQL\Utils\Utils;
class ServerConfig class ServerConfig

View File

@ -8,7 +8,7 @@ use GraphQL\Language\AST\FragmentSpreadNode;
use GraphQL\Language\AST\InlineFragmentNode; use GraphQL\Language\AST\InlineFragmentNode;
use GraphQL\Language\AST\OperationDefinitionNode; use GraphQL\Language\AST\OperationDefinitionNode;
use GraphQL\Language\AST\SelectionSetNode; use GraphQL\Language\AST\SelectionSetNode;
use GraphQL\Schema; use GraphQL\Type\Schema;
use GraphQL\Utils\Utils; use GraphQL\Utils\Utils;
/** /**

View File

@ -3,7 +3,6 @@ namespace GraphQL\Type;
use GraphQL\Language\Printer; use GraphQL\Language\Printer;
use GraphQL\Schema;
use GraphQL\Type\Definition\Directive; use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\DirectiveLocation; use GraphQL\Type\Definition\DirectiveLocation;
use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\EnumType;

393
src/Type/Schema.php Normal file
View File

@ -0,0 +1,393 @@
<?php
namespace GraphQL\Type;
use GraphQL\Error\InvariantViolation;
use GraphQL\GraphQL;
use GraphQL\Type\Definition\FieldArgument;
use GraphQL\Type\Definition\NonNull;
use GraphQL\Type\Definition\AbstractType;
use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType;
use GraphQL\Utils\TypeComparators;
use GraphQL\Utils\TypeInfo;
use GraphQL\Utils\Utils;
/**
* Schema Definition
*
* A Schema is created by supplying the root types of each type of operation:
* query, mutation (optional) and subscription (optional). A schema definition is
* then supplied to the validator and executor.
*
* Example:
*
* $schema = new GraphQL\Type\Schema([
* 'query' => $MyAppQueryRootType,
* 'mutation' => $MyAppMutationRootType,
* ]);
*
* Note: If an array of `directives` are provided to GraphQL\Schema, that will be
* the exact list of directives represented and allowed. If `directives` is not
* provided then a default set of the specified directives (e.g. @include and
* @skip) will be used. If you wish to provide *additional* directives to these
* specified directives, you must explicitly declare them. Example:
*
* $mySchema = new GraphQL\Schema([
* ...
* 'directives' => array_merge(GraphQL::getInternalDirectives(), [ $myCustomDirective ]),
* ])
*
* @package GraphQL
*/
class Schema
{
/**
* @var SchemaConfig
*/
private $config;
/**
* Contains actual descriptor for this schema
*
* @var Descriptor
*/
private $descriptor;
/**
* Contains currently resolved schema types
*
* @var Type[]
*/
private $resolvedTypes = [];
/**
* True when $resolvedTypes contain all possible schema types
*
* @var bool
*/
private $fullyLoaded = false;
/**
* Schema constructor.
*
* @param array|SchemaConfig $config
*/
public function __construct($config = null)
{
if (func_num_args() > 1 || $config instanceof Type) {
trigger_error(
'GraphQL\Schema constructor expects config object now instead of types passed as arguments. '.
'See https://github.com/webonyx/graphql-php/issues/36',
E_USER_DEPRECATED
);
list($queryType, $mutationType, $subscriptionType) = func_get_args() + [null, null, null];
$config = [
'query' => $queryType,
'mutation' => $mutationType,
'subscription' => $subscriptionType
];
}
if (is_array($config)) {
$config = SchemaConfig::create($config);
}
Utils::invariant(
$config instanceof SchemaConfig,
'Schema constructor expects instance of GraphQL\Type\SchemaConfig or an array with keys: %s; but got: %s',
implode(', ', [
'query',
'mutation',
'subscription',
'types',
'directives',
'typeLoader',
'descriptor'
]),
Utils::getVariableType($config)
);
Utils::invariant(
$config->query instanceof ObjectType,
"Schema query must be Object Type but got: " . Utils::getVariableType($config->query)
);
$this->config = $config;
}
/**
* Returns schema query type
*
* @return ObjectType
*/
public function getQueryType()
{
return $this->config->query;
}
/**
* Returns schema mutation type
*
* @return ObjectType|null
*/
public function getMutationType()
{
return $this->config->mutation;
}
/**
* Returns schema subscription
*
* @return ObjectType|null
*/
public function getSubscriptionType()
{
return $this->config->subscription;
}
/**
* @return SchemaConfig
*/
public function getConfig()
{
return $this->config;
}
/**
* Returns array of all types in this schema. Keys of this array represent type names, values are instances
* of corresponding type definitions
*
* @return Type[]
*/
public function getTypeMap()
{
if (!$this->fullyLoaded) {
if ($this->config->descriptor && $this->config->typeLoader) {
// Following is still faster than $this->collectAllTypes() because it won't init fields
$typesToResolve = array_diff_key($this->config->descriptor->typeMap, $this->resolvedTypes);
foreach ($typesToResolve as $typeName => $_) {
$this->resolvedTypes[$typeName] = $this->loadType($typeName);
}
} else {
$this->resolvedTypes = $this->collectAllTypes();
}
$this->fullyLoaded = true;
}
return $this->resolvedTypes;
}
/**
* Returns type by it's name
*
* @param string $name
* @return Type
*/
public function getType($name)
{
return $this->resolveType($name);
}
/**
* Returns serializable schema descriptor which can be passed later
* to Schema config to enable a set of performance optimizations
*
* @return Descriptor
*/
public function describe()
{
if ($this->descriptor) {
return $this->descriptor;
}
$this->resolvedTypes = $this->collectAllTypes();
$this->fullyLoaded = true;
$descriptor = new Descriptor();
$descriptor->version = '1.0';
$descriptor->created = time();
foreach ($this->resolvedTypes as $type) {
if ($type instanceof ObjectType) {
foreach ($type->getInterfaces() as $interface) {
$descriptor->possibleTypeMap[$interface->name][$type->name] = 1;
}
} else if ($type instanceof UnionType) {
foreach ($type->getTypes() as $innerType) {
$descriptor->possibleTypeMap[$type->name][$innerType->name] = 1;
}
}
$descriptor->typeMap[$type->name] = 1;
}
return $this->descriptor = $descriptor;
}
private function collectAllTypes()
{
$initialTypes = array_merge(
[
$this->config->query,
$this->config->mutation,
$this->config->subscription,
Introspection::_schema()
],
array_values($this->resolvedTypes)
);
$typeMap = [];
foreach ($initialTypes as $type) {
$typeMap = TypeInfo::extractTypes($type, $typeMap);
}
$types = $this->config->types;
if (is_callable($types)) {
$types = $types();
Utils::invariant(
is_array($types) || $types instanceof \Traversable,
'Schema types callable must return array or instance of Traversable but got: %s',
Utils::getVariableType($types)
);
}
if (!empty($types)) {
foreach ($types as $type) {
Utils::invariant(
$type instanceof Type,
'Each entry of schema types must be instance of GraphQL\Type\Definition\Type but got: %s',
Utils::getVariableType($types)
);
$typeMap = TypeInfo::extractTypes($type, $typeMap);
}
}
return $typeMap + Type::getInternalTypes();
}
/**
* Returns all possible concrete types for given abstract type
* (implementations for interfaces and members of union type for unions)
*
* @param AbstractType $abstractType
* @return ObjectType[]
*/
public function getPossibleTypes(AbstractType $abstractType)
{
if ($abstractType instanceof UnionType) {
return $abstractType->getTypes();
}
/** @var InterfaceType $abstractType */
$descriptor = $this->config->descriptor ?: $this->describe();
$result = [];
if (isset($descriptor->possibleTypeMap[$abstractType->name])) {
foreach ($descriptor->possibleTypeMap[$abstractType->name] as $typeName => $_) {
$result[] = $this->resolveType($typeName);
}
}
return $result;
}
/**
* Accepts name of type or type instance and returns type instance. If type with given name is not loaded yet -
* will load it first.
*
* @param $typeOrName
* @return Type
*/
public function resolveType($typeOrName)
{
if ($typeOrName instanceof Type) {
if ($typeOrName->name && !isset($this->resolvedTypes[$typeOrName->name])) {
$this->resolvedTypes[$typeOrName->name] = $typeOrName;
}
return $typeOrName;
}
if (!isset($this->resolvedTypes[$typeOrName])) {
$this->resolvedTypes[$typeOrName] = $this->loadType($typeOrName);
}
return $this->resolvedTypes[$typeOrName];
}
private function loadType($typeName)
{
$typeLoader = $this->config->typeLoader;
if (!$typeLoader) {
return $this->defaultTypeLoader($typeName);
}
$type = $typeLoader($typeName);
// TODO: validate returned value
return $type;
}
/**
* Returns true if object type is concrete type of given abstract type
* (implementation for interfaces and members of union type for unions)
*
* @param AbstractType $abstractType
* @param ObjectType $possibleType
* @return bool
*/
public function isPossibleType(AbstractType $abstractType, ObjectType $possibleType)
{
if ($this->config->descriptor) {
return !empty($this->config->descriptor->possibleTypeMap[$abstractType->name][$possibleType->name]);
}
if ($abstractType instanceof InterfaceType) {
return $possibleType->implementsInterface($abstractType);
}
/** @var UnionType $abstractType */
return $abstractType->isPossibleType($possibleType);
}
/**
* Returns a list of directives supported by this schema
*
* @return Directive[]
*/
public function getDirectives()
{
return $this->config->directives ?: GraphQL::getInternalDirectives();
}
/**
* Returns instance of directive by name
*
* @param $name
* @return Directive
*/
public function getDirective($name)
{
foreach ($this->getDirectives() as $directive) {
if ($directive->name === $name) {
return $directive;
}
}
return null;
}
/**
* @param $typeName
* @return Type
*/
private function defaultTypeLoader($typeName)
{
// Default type loader simply fallbacks to collecting all types
if (!$this->fullyLoaded) {
$this->resolvedTypes = $this->collectAllTypes();
$this->fullyLoaded = true;
}
if (!isset($this->resolvedTypes[$typeName])) {
return null;
}
return $this->resolvedTypes[$typeName];
}
}

View File

@ -1,5 +1,5 @@
<?php <?php
namespace GraphQL; namespace GraphQL\Type;
use GraphQL\Type\Descriptor; use GraphQL\Type\Descriptor;
use GraphQL\Type\Definition\Directive; use GraphQL\Type\Definition\Directive;
@ -13,7 +13,7 @@ use GraphQL\Utils\Utils;
* *
* @package GraphQL * @package GraphQL
*/ */
class Config class SchemaConfig
{ {
/** /**
* @var ObjectType * @var ObjectType
@ -52,7 +52,7 @@ class Config
/** /**
* @param array $options * @param array $options
* @return Config * @return SchemaConfig
*/ */
public static function create(array $options = []) public static function create(array $options = [])
{ {
@ -136,7 +136,7 @@ class Config
/** /**
* @param ObjectType $query * @param ObjectType $query
* @return Config * @return SchemaConfig
*/ */
public function setQuery(ObjectType $query) public function setQuery(ObjectType $query)
{ {
@ -154,7 +154,7 @@ class Config
/** /**
* @param ObjectType $mutation * @param ObjectType $mutation
* @return Config * @return SchemaConfig
*/ */
public function setMutation(ObjectType $mutation) public function setMutation(ObjectType $mutation)
{ {
@ -172,7 +172,7 @@ class Config
/** /**
* @param ObjectType $subscription * @param ObjectType $subscription
* @return Config * @return SchemaConfig
*/ */
public function setSubscription(ObjectType $subscription) public function setSubscription(ObjectType $subscription)
{ {
@ -190,7 +190,7 @@ class Config
/** /**
* @param Type[]|callable $types * @param Type[]|callable $types
* @return Config * @return SchemaConfig
*/ */
public function setTypes($types) public function setTypes($types)
{ {
@ -208,7 +208,7 @@ class Config
/** /**
* @param Directive[] $directives * @param Directive[] $directives
* @return Config * @return SchemaConfig
*/ */
public function setDirectives(array $directives) public function setDirectives(array $directives)
{ {
@ -226,7 +226,7 @@ class Config
/** /**
* @param Descriptor $descriptor * @param Descriptor $descriptor
* @return Config * @return SchemaConfig
*/ */
public function setDescriptor(Descriptor $descriptor) public function setDescriptor(Descriptor $descriptor)
{ {
@ -244,7 +244,7 @@ class Config
/** /**
* @param callable $typeLoader * @param callable $typeLoader
* @return Config * @return SchemaConfig
*/ */
public function setTypeLoader(callable $typeLoader) public function setTypeLoader(callable $typeLoader)
{ {

View File

@ -19,7 +19,7 @@ use GraphQL\Language\AST\UnionTypeDefinitionNode;
use GraphQL\Language\Parser; use GraphQL\Language\Parser;
use GraphQL\Language\Source; use GraphQL\Language\Source;
use GraphQL\Language\Token; use GraphQL\Language\Token;
use GraphQL\Schema; use GraphQL\Type\Schema;
use GraphQL\Type\Definition\Directive; use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InputObjectType;

View File

@ -2,7 +2,7 @@
namespace GraphQL\Utils; namespace GraphQL\Utils;
use GraphQL\Language\Printer; use GraphQL\Language\Printer;
use GraphQL\Schema; use GraphQL\Type\Schema;
use GraphQL\Type\Definition\CompositeType; use GraphQL\Type\Definition\CompositeType;
use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InputObjectType;

View File

@ -9,7 +9,7 @@ use GraphQL\Language\AST\NullValueNode;
use GraphQL\Language\AST\VariableNode; use GraphQL\Language\AST\VariableNode;
use GraphQL\Language\Printer; use GraphQL\Language\Printer;
use GraphQL\Language\Visitor; use GraphQL\Language\Visitor;
use GraphQL\Schema; use GraphQL\Type\Schema;
use GraphQL\Type\Definition\InputObjectType; use GraphQL\Type\Definition\InputObjectType;
use GraphQL\Type\Definition\LeafType; use GraphQL\Type\Definition\LeafType;
use GraphQL\Type\Definition\ListOfType; use GraphQL\Type\Definition\ListOfType;

View File

@ -4,8 +4,6 @@ namespace GraphQL\Validator\Rules;
use GraphQL\Error\Error; use GraphQL\Error\Error;
use GraphQL\Language\AST\FieldNode; use GraphQL\Language\AST\FieldNode;
use GraphQL\Language\AST\NodeKind; use GraphQL\Language\AST\NodeKind;
use GraphQL\Schema;
use GraphQL\Type\Definition\AbstractType;
use GraphQL\Utils\Utils; use GraphQL\Utils\Utils;
use GraphQL\Validator\ValidationContext; use GraphQL\Validator\ValidationContext;

View File

@ -7,7 +7,7 @@ use GraphQL\Language\AST\FragmentSpreadNode;
use GraphQL\Language\AST\InlineFragmentNode; use GraphQL\Language\AST\InlineFragmentNode;
use GraphQL\Language\AST\Node; use GraphQL\Language\AST\Node;
use GraphQL\Language\AST\NodeKind; use GraphQL\Language\AST\NodeKind;
use GraphQL\Schema; use GraphQL\Type\Schema;
use GraphQL\Type\Definition\AbstractType; use GraphQL\Type\Definition\AbstractType;
use GraphQL\Type\Definition\CompositeType; use GraphQL\Type\Definition\CompositeType;
use GraphQL\Type\Definition\InterfaceType; use GraphQL\Type\Definition\InterfaceType;

View File

@ -9,7 +9,7 @@ use GraphQL\Language\AST\VariableNode;
use GraphQL\Language\Visitor; use GraphQL\Language\Visitor;
use \SplObjectStorage; use \SplObjectStorage;
use GraphQL\Error\Error; use GraphQL\Error\Error;
use GraphQL\Schema; use GraphQL\Type\Schema;
use GraphQL\Language\AST\DocumentNode; use GraphQL\Language\AST\DocumentNode;
use GraphQL\Language\AST\FragmentDefinitionNode; use GraphQL\Language\AST\FragmentDefinitionNode;
use GraphQL\Language\AST\Node; use GraphQL\Language\AST\Node;