diff --git a/benchmarks/HugeSchemaBench.php b/benchmarks/HugeSchemaBench.php index fa26228..b9830c0 100644 --- a/benchmarks/HugeSchemaBench.php +++ b/benchmarks/HugeSchemaBench.php @@ -22,7 +22,7 @@ class HugeSchemaBench private $schemaBuilder; /** - * @var Schema\Descriptor + * @var \GraphQL\Type\Descriptor */ private $descriptor; @@ -47,7 +47,7 @@ class HugeSchemaBench $this->schema = $this->schemaBuilder->buildSchema(); $queryBuilder = new QueryGenerator($this->schema, 0.05); - $this->descriptor = $this->schema->getDescriptor(); + $this->descriptor = $this->schema->describe(); $this->smallQuery = $queryBuilder->buildQuery(); } @@ -78,7 +78,7 @@ class HugeSchemaBench private function createLazySchema() { return new Schema( - Schema\Config::create() + \GraphQL\Config::create() ->setQuery($this->schemaBuilder->buildQueryType()) // ->setDescriptor($this->descriptor) ->setTypeLoader(function($name) { diff --git a/src/Schema/Config.php b/src/Config.php similarity index 71% rename from src/Schema/Config.php rename to src/Config.php index c59e0b5..f908980 100644 --- a/src/Schema/Config.php +++ b/src/Config.php @@ -1,6 +1,8 @@ setQuery($options['query']); } @@ -69,7 +77,8 @@ final class Config if (isset($options['mutation'])) { Utils::invariant( $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']); } @@ -77,7 +86,8 @@ final class Config if (isset($options['subscription'])) { Utils::invariant( $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']); } @@ -85,7 +95,8 @@ final class Config if (isset($options['types'])) { Utils::invariant( 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']); } @@ -93,7 +104,8 @@ final class Config if (isset($options['directives'])) { Utils::invariant( 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']); } @@ -101,15 +113,27 @@ final class Config if (isset($options['typeLoader'])) { Utils::invariant( 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'])) { Utils::invariant( $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; return $this; } + + /** + * @return PromiseAdapter + */ + public function getPromiseAdapter() + { + return $this->promiseAdapter; + } + + /** + * @param PromiseAdapter $promiseAdapter + * @return Config + */ + public function setPromiseAdapter($promiseAdapter) + { + $this->promiseAdapter = $promiseAdapter; + return $this; + } } diff --git a/src/Error/UserError.php b/src/Error/UserError.php index ad07ee9..8276c94 100644 --- a/src/Error/UserError.php +++ b/src/Error/UserError.php @@ -4,8 +4,7 @@ namespace GraphQL\Error; /** * Class UserError * - * Note: - * Error that can be display safely to client... + * Error that can be safely displayed to client... * * @package GraphQL\Error */ diff --git a/src/GraphQL.php b/src/GraphQL.php index 4ec1e88..3417d49 100644 --- a/src/GraphQL.php +++ b/src/GraphQL.php @@ -16,20 +16,6 @@ use GraphQL\Validator\Rules\QueryComplexity; 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 * by parsing, validating, and executing a GraphQL document along side a @@ -73,7 +59,7 @@ class GraphQL $contextValue = null, $variableValues = null, $operationName = null, - $fieldResolver = null + callable $fieldResolver = null ) { $result = self::executeAndReturnResult( @@ -104,6 +90,7 @@ class GraphQL * @param Schema $schema * @param string|DocumentNode $source * @param mixed $rootValue + * @param mixed $contextValue * @param array|null $variableValues * @param string|null $operationName * @param callable $fieldResolver @@ -116,7 +103,7 @@ class GraphQL $contextValue = null, $variableValues = null, $operationName = null, - $fieldResolver = null + callable $fieldResolver = null ) { try { diff --git a/src/Schema.php b/src/Schema.php index 01fc3b5..51c34bb 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -1,8 +1,7 @@ setQuery($queryType) - ->setMutation($mutationType) - ->setSubscription($subscriptionType) - ; - } else if (is_array($config)) { + $config = [ + 'query' => $queryType, + 'mutation' => $mutationType, + 'subscription' => $subscriptionType + ]; + } + if (is_array($config)) { $config = Config::create($config); } @@ -101,8 +101,8 @@ class Schema 'subscription', 'types', 'directives', - 'descriptor', - 'typeLoader' + 'typeLoader', + 'descriptor' ]), Utils::getVariableType($config) ); @@ -116,6 +116,8 @@ class Schema } /** + * Returns schema query type + * * @return ObjectType */ public function getQueryType() @@ -124,6 +126,8 @@ class Schema } /** + * Returns schema mutation type + * * @return ObjectType|null */ public function getMutationType() @@ -132,6 +136,8 @@ class Schema } /** + * Returns schema subscription + * * @return ObjectType|null */ 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[] */ @@ -156,6 +163,7 @@ class Schema { 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); @@ -185,22 +193,12 @@ class Schema * * @return Descriptor */ - public function getDescriptor() + public function describe() { if ($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->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 * @return ObjectType[] */ @@ -253,7 +254,7 @@ class Schema } /** @var InterfaceType $abstractType */ - $descriptor = $this->getDescriptor(); + $descriptor = $this->config->descriptor ?: $this->describe(); $result = []; if (isset($descriptor->possibleTypeMap[$abstractType->name])) { @@ -264,6 +265,13 @@ class Schema 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) { @@ -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 ObjectType $possibleType * @return bool @@ -311,6 +322,8 @@ class Schema } /** + * Returns a list of directives supported by this schema + * * @return Directive[] */ public function getDirectives() @@ -319,6 +332,8 @@ class Schema } /** + * Returns instance of directive by name + * * @param $name * @return Directive */ diff --git a/src/Schema/Descriptor.php b/src/Type/Descriptor.php similarity index 98% rename from src/Schema/Descriptor.php rename to src/Type/Descriptor.php index b41029c..39e98cf 100644 --- a/src/Schema/Descriptor.php +++ b/src/Type/Descriptor.php @@ -1,5 +1,5 @@ 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()); - 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()); - GraphQL::setIgnoreError(GraphQL::WARNING_ON_IMPLEMENTATION_RESOLUTION, false); + Warning::enable(Warning::RESOLVE_TYPE_WARNING); } /**