Global config; descriptor moved to appropriate namespace; minor cleanup

This commit is contained in:
Vladimir Razuvaev 2017-07-10 20:17:55 +07:00
parent 296544089c
commit aaa5b7af41
10 changed files with 105 additions and 64 deletions

View File

@ -22,7 +22,7 @@ class HugeSchemaBench
private $schemaBuilder; private $schemaBuilder;
/** /**
* @var Schema\Descriptor * @var \GraphQL\Type\Descriptor
*/ */
private $descriptor; private $descriptor;
@ -47,7 +47,7 @@ class HugeSchemaBench
$this->schema = $this->schemaBuilder->buildSchema(); $this->schema = $this->schemaBuilder->buildSchema();
$queryBuilder = new QueryGenerator($this->schema, 0.05); $queryBuilder = new QueryGenerator($this->schema, 0.05);
$this->descriptor = $this->schema->getDescriptor(); $this->descriptor = $this->schema->describe();
$this->smallQuery = $queryBuilder->buildQuery(); $this->smallQuery = $queryBuilder->buildQuery();
} }
@ -78,7 +78,7 @@ class HugeSchemaBench
private function createLazySchema() private function createLazySchema()
{ {
return new Schema( return new Schema(
Schema\Config::create() \GraphQL\Config::create()
->setQuery($this->schemaBuilder->buildQueryType()) ->setQuery($this->schemaBuilder->buildQueryType())
// ->setDescriptor($this->descriptor) // ->setDescriptor($this->descriptor)
->setTypeLoader(function($name) { ->setTypeLoader(function($name) {

View File

@ -1,6 +1,8 @@
<?php <?php
namespace GraphQL\Schema; namespace GraphQL;
use GraphQL\Executor\Promise\PromiseAdapter;
use GraphQL\Type\Descriptor;
use GraphQL\Type\Definition\Directive; use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\Type;
@ -10,9 +12,9 @@ use GraphQL\Utils\Utils;
* Class Config * Class Config
* Note: properties are marked as public for performance reasons. They should be considered read-only. * Note: properties are marked as public for performance reasons. They should be considered read-only.
* *
* @package GraphQL\Schema * @package GraphQL
*/ */
final class Config class Config
{ {
/** /**
* @var ObjectType * @var ObjectType
@ -49,6 +51,11 @@ final class Config
*/ */
public $typeLoader; public $typeLoader;
/**
* @var PromiseAdapter
*/
public $promiseAdapter;
/** /**
* @param array $options * @param array $options
* @return Config * @return Config
@ -61,7 +68,8 @@ final class Config
if (isset($options['query'])) { if (isset($options['query'])) {
Utils::invariant( Utils::invariant(
$options['query'] instanceof ObjectType, $options['query'] instanceof ObjectType,
"Schema query must be Object Type if provided but got: " . Utils::getVariableType($options['query']) 'Schema query must be Object Type if provided but got: %s',
Utils::getVariableType($options['query'])
); );
$config->setQuery($options['query']); $config->setQuery($options['query']);
} }
@ -69,7 +77,8 @@ final class Config
if (isset($options['mutation'])) { if (isset($options['mutation'])) {
Utils::invariant( Utils::invariant(
$options['mutation'] instanceof ObjectType, $options['mutation'] instanceof ObjectType,
"Schema mutation must be Object Type if provided but got: " . Utils::getVariableType($options['mutation']) 'Schema mutation must be Object Type if provided but got: %s',
Utils::getVariableType($options['mutation'])
); );
$config->setMutation($options['mutation']); $config->setMutation($options['mutation']);
} }
@ -77,7 +86,8 @@ final class Config
if (isset($options['subscription'])) { if (isset($options['subscription'])) {
Utils::invariant( Utils::invariant(
$options['subscription'] instanceof ObjectType, $options['subscription'] instanceof ObjectType,
"Schema subscription must be Object Type if provided but got: " . Utils::getVariableType($options['subscription']) 'Schema subscription must be Object Type if provided but got: %s',
Utils::getVariableType($options['subscription'])
); );
$config->setSubscription($options['subscription']); $config->setSubscription($options['subscription']);
} }
@ -85,7 +95,8 @@ final class Config
if (isset($options['types'])) { if (isset($options['types'])) {
Utils::invariant( Utils::invariant(
is_array($options['types']), is_array($options['types']),
"Schema types must be array if provided but got: " . Utils::getVariableType($options['types']) 'Schema types must be array if provided but got: %s',
Utils::getVariableType($options['types'])
); );
$config->setTypes($options['types']); $config->setTypes($options['types']);
} }
@ -93,7 +104,8 @@ final class Config
if (isset($options['directives'])) { if (isset($options['directives'])) {
Utils::invariant( Utils::invariant(
is_array($options['directives']), is_array($options['directives']),
"Schema directives must be array if provided but got: " . Utils::getVariableType($options['directives']) 'Schema directives must be array if provided but got: %s',
Utils::getVariableType($options['directives'])
); );
$config->setDirectives($options['directives']); $config->setDirectives($options['directives']);
} }
@ -101,15 +113,27 @@ final class Config
if (isset($options['typeLoader'])) { if (isset($options['typeLoader'])) {
Utils::invariant( Utils::invariant(
is_callable($options['typeLoader']), is_callable($options['typeLoader']),
"Schema type loader must be callable if provided but got: " . Utils::getVariableType($options['typeLoader']) 'Schema type loader must be callable if provided but got: %s',
Utils::getVariableType($options['typeLoader'])
); );
} }
if (isset($options['descriptor'])) { if (isset($options['descriptor'])) {
Utils::invariant( Utils::invariant(
$options['descriptor'] instanceof Descriptor, $options['descriptor'] instanceof Descriptor,
"Schema descriptor must be instance of GraphQL\\Schema\\Descriptor but got: " . Utils::getVariableType($options['descriptor']) 'Schema descriptor must be instance of GraphQL\Type\Descriptor but got: %s',
Utils::getVariableType($options['descriptor'])
); );
$config->setDescriptor($options['descriptor']);
}
if (isset($options['promiseAdapter'])) {
Utils::invariant(
$options['promiseAdapter'] instanceof PromiseAdapter,
'Promise adapter must be an instance of GraphQL\Executor\Promise\PromiseAdapter but got: %s',
Utils::getVariableType($options['promiseAdapter'])
);
$config->setPromiseAdapter($options['promiseAdapter']);
} }
} }
@ -259,4 +283,22 @@ final class Config
$this->typeLoader = $typeLoader; $this->typeLoader = $typeLoader;
return $this; return $this;
} }
/**
* @return PromiseAdapter
*/
public function getPromiseAdapter()
{
return $this->promiseAdapter;
}
/**
* @param PromiseAdapter $promiseAdapter
* @return Config
*/
public function setPromiseAdapter($promiseAdapter)
{
$this->promiseAdapter = $promiseAdapter;
return $this;
}
} }

View File

@ -4,8 +4,7 @@ namespace GraphQL\Error;
/** /**
* Class UserError * Class UserError
* *
* Note: * Error that can be safely displayed to client...
* Error that can be display safely to client...
* *
* @package GraphQL\Error * @package GraphQL\Error
*/ */

View File

@ -16,20 +16,6 @@ use GraphQL\Validator\Rules\QueryComplexity;
class GraphQL class GraphQL
{ {
const WARNING_ON_IMPLEMENTATION_RESOLUTION = 1;
private static $ignoredErrors = [];
public static function setIgnoreError($errorCode, $set = true)
{
self::$ignoredErrors[$errorCode] = $set ? true : null;
}
public static function isIgnoredError($errorCode)
{
return isset(self::$ignoredErrors[$errorCode]);
}
/** /**
* This is the primary entry point function for fulfilling GraphQL operations * This is the primary entry point function for fulfilling GraphQL operations
* by parsing, validating, and executing a GraphQL document along side a * by parsing, validating, and executing a GraphQL document along side a
@ -73,7 +59,7 @@ class GraphQL
$contextValue = null, $contextValue = null,
$variableValues = null, $variableValues = null,
$operationName = null, $operationName = null,
$fieldResolver = null callable $fieldResolver = null
) )
{ {
$result = self::executeAndReturnResult( $result = self::executeAndReturnResult(
@ -104,6 +90,7 @@ class GraphQL
* @param Schema $schema * @param Schema $schema
* @param string|DocumentNode $source * @param string|DocumentNode $source
* @param mixed $rootValue * @param mixed $rootValue
* @param mixed $contextValue
* @param array|null $variableValues * @param array|null $variableValues
* @param string|null $operationName * @param string|null $operationName
* @param callable $fieldResolver * @param callable $fieldResolver
@ -116,7 +103,7 @@ class GraphQL
$contextValue = null, $contextValue = null,
$variableValues = null, $variableValues = null,
$operationName = null, $operationName = null,
$fieldResolver = null callable $fieldResolver = null
) )
{ {
try { try {

View File

@ -1,8 +1,7 @@
<?php <?php
namespace GraphQL; namespace GraphQL;
use GraphQL\Schema\Config; use GraphQL\Type\Descriptor;
use GraphQL\Schema\Descriptor;
use GraphQL\Type\Definition\AbstractType; use GraphQL\Type\Definition\AbstractType;
use GraphQL\Type\Definition\Directive; use GraphQL\Type\Definition\Directive;
use GraphQL\Type\Definition\InterfaceType; use GraphQL\Type\Definition\InterfaceType;
@ -83,12 +82,13 @@ class Schema
); );
list($queryType, $mutationType, $subscriptionType) = func_get_args() + [null, null, null]; list($queryType, $mutationType, $subscriptionType) = func_get_args() + [null, null, null];
$config = Config::create() $config = [
->setQuery($queryType) 'query' => $queryType,
->setMutation($mutationType) 'mutation' => $mutationType,
->setSubscription($subscriptionType) 'subscription' => $subscriptionType
; ];
} else if (is_array($config)) { }
if (is_array($config)) {
$config = Config::create($config); $config = Config::create($config);
} }
@ -101,8 +101,8 @@ class Schema
'subscription', 'subscription',
'types', 'types',
'directives', 'directives',
'descriptor', 'typeLoader',
'typeLoader' 'descriptor'
]), ]),
Utils::getVariableType($config) Utils::getVariableType($config)
); );
@ -116,6 +116,8 @@ class Schema
} }
/** /**
* Returns schema query type
*
* @return ObjectType * @return ObjectType
*/ */
public function getQueryType() public function getQueryType()
@ -124,6 +126,8 @@ class Schema
} }
/** /**
* Returns schema mutation type
*
* @return ObjectType|null * @return ObjectType|null
*/ */
public function getMutationType() public function getMutationType()
@ -132,6 +136,8 @@ class Schema
} }
/** /**
* Returns schema subscription
*
* @return ObjectType|null * @return ObjectType|null
*/ */
public function getSubscriptionType() public function getSubscriptionType()
@ -148,7 +154,8 @@ class Schema
} }
/** /**
* Returns full map of types in this schema. * Returns array of all types in this schema. Keys of this array represent type names, values are instances
* of corresponding type definitions
* *
* @return Type[] * @return Type[]
*/ */
@ -156,6 +163,7 @@ class Schema
{ {
if (!$this->fullyLoaded) { if (!$this->fullyLoaded) {
if ($this->config->descriptor && $this->config->typeLoader) { 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); $typesToResolve = array_diff_key($this->config->descriptor->typeMap, $this->resolvedTypes);
foreach ($typesToResolve as $typeName => $_) { foreach ($typesToResolve as $typeName => $_) {
$this->resolvedTypes[$typeName] = $this->loadType($typeName); $this->resolvedTypes[$typeName] = $this->loadType($typeName);
@ -185,22 +193,12 @@ class Schema
* *
* @return Descriptor * @return Descriptor
*/ */
public function getDescriptor() public function describe()
{ {
if ($this->descriptor) { if ($this->descriptor) {
return $this->descriptor; return $this->descriptor;
} }
if ($this->config->descriptor) {
return $this->config->descriptor;
}
return $this->descriptor = $this->buildDescriptor();
}
/**
* @return Descriptor
*/
public function buildDescriptor()
{
$this->resolvedTypes = $this->collectAllTypes(); $this->resolvedTypes = $this->collectAllTypes();
$this->fullyLoaded = true; $this->fullyLoaded = true;
@ -243,6 +241,9 @@ class Schema
} }
/** /**
* Returns all possible concrete types for given abstract type
* (implementations for interfaces and members of union type for unions)
*
* @param AbstractType $abstractType * @param AbstractType $abstractType
* @return ObjectType[] * @return ObjectType[]
*/ */
@ -253,7 +254,7 @@ class Schema
} }
/** @var InterfaceType $abstractType */ /** @var InterfaceType $abstractType */
$descriptor = $this->getDescriptor(); $descriptor = $this->config->descriptor ?: $this->describe();
$result = []; $result = [];
if (isset($descriptor->possibleTypeMap[$abstractType->name])) { if (isset($descriptor->possibleTypeMap[$abstractType->name])) {
@ -264,6 +265,13 @@ class Schema
return $result; 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) public function resolveType($typeOrName)
{ {
if ($typeOrName instanceof Type) { if ($typeOrName instanceof Type) {
@ -292,6 +300,9 @@ class Schema
} }
/** /**
* 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 AbstractType $abstractType
* @param ObjectType $possibleType * @param ObjectType $possibleType
* @return bool * @return bool
@ -311,6 +322,8 @@ class Schema
} }
/** /**
* Returns a list of directives supported by this schema
*
* @return Directive[] * @return Directive[]
*/ */
public function getDirectives() public function getDirectives()
@ -319,6 +332,8 @@ class Schema
} }
/** /**
* Returns instance of directive by name
*
* @param $name * @param $name
* @return Directive * @return Directive
*/ */

View File

@ -1,5 +1,5 @@
<?php <?php
namespace GraphQL\Schema; namespace GraphQL\Type;
use GraphQL\Utils\Utils; use GraphQL\Utils\Utils;

View File

@ -1,6 +1,5 @@
<?php <?php
namespace GraphQL\Utils; namespace GraphQL\Utils;
use GraphQL\Utils\Utils;
/** /**
* Similar to PHP array, but allows any type of data to act as key (including arrays, objects, scalars) * Similar to PHP array, but allows any type of data to act as key (including arrays, objects, scalars)

View File

@ -12,7 +12,6 @@ use GraphQL\Type\Definition\ScalarType;
use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType; use GraphQL\Type\Definition\UnionType;
use GraphQL\Type\Definition\Directive; use GraphQL\Type\Definition\Directive;
use GraphQL\Utils\Utils;
/** /**
* Class SchemaPrinter * Class SchemaPrinter

View File

@ -24,7 +24,6 @@ use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType; use GraphQL\Type\Definition\UnionType;
use GraphQL\Type\Definition\WrappingType; use GraphQL\Type\Definition\WrappingType;
use GraphQL\Type\Introspection; use GraphQL\Type\Introspection;
use GraphQL\Utils\Utils;
/** /**
* Class TypeInfo * Class TypeInfo

View File

@ -3,6 +3,7 @@ namespace GraphQL\Tests\Executor;
require_once __DIR__ . '/TestClasses.php'; require_once __DIR__ . '/TestClasses.php';
use GraphQL\Error\Warning;
use GraphQL\Executor\Executor; use GraphQL\Executor\Executor;
use GraphQL\GraphQL; use GraphQL\GraphQL;
use GraphQL\Language\Parser; use GraphQL\Language\Parser;
@ -256,9 +257,9 @@ class UnionInterfaceTest extends \PHPUnit_Framework_TestCase
] ]
]; ];
GraphQL::setIgnoreError(GraphQL::WARNING_ON_IMPLEMENTATION_RESOLUTION); Warning::suppress(Warning::RESOLVE_TYPE_WARNING);
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray()); $this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
GraphQL::setIgnoreError(GraphQL::WARNING_ON_IMPLEMENTATION_RESOLUTION, false); Warning::enable(Warning::RESOLVE_TYPE_WARNING);
} }
/** /**
@ -294,9 +295,9 @@ class UnionInterfaceTest extends \PHPUnit_Framework_TestCase
] ]
]; ];
GraphQL::setIgnoreError(GraphQL::WARNING_ON_IMPLEMENTATION_RESOLUTION); Warning::suppress(Warning::RESOLVE_TYPE_WARNING);
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray()); $this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
GraphQL::setIgnoreError(GraphQL::WARNING_ON_IMPLEMENTATION_RESOLUTION, false); Warning::enable(Warning::RESOLVE_TYPE_WARNING);
} }
/** /**
@ -351,9 +352,9 @@ class UnionInterfaceTest extends \PHPUnit_Framework_TestCase
] ]
]; ];
GraphQL::setIgnoreError(GraphQL::WARNING_ON_IMPLEMENTATION_RESOLUTION); Warning::suppress(Warning::RESOLVE_TYPE_WARNING);
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray()); $this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
GraphQL::setIgnoreError(GraphQL::WARNING_ON_IMPLEMENTATION_RESOLUTION, false); Warning::enable(Warning::RESOLVE_TYPE_WARNING);
} }
/** /**