mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-25 14:26:08 +03:00
Removed schema descriptor (as lazy loading of types can work without it now)
This commit is contained in:
parent
f9eb14869f
commit
20f8cab943
@ -21,11 +21,6 @@ class HugeSchemaBench
|
|||||||
*/
|
*/
|
||||||
private $schemaBuilder;
|
private $schemaBuilder;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \GraphQL\Type\Descriptor
|
|
||||||
*/
|
|
||||||
private $descriptor;
|
|
||||||
|
|
||||||
private $schema;
|
private $schema;
|
||||||
|
|
||||||
private $lazySchema;
|
private $lazySchema;
|
||||||
@ -47,7 +42,6 @@ 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->describe();
|
|
||||||
$this->smallQuery = $queryBuilder->buildQuery();
|
$this->smallQuery = $queryBuilder->buildQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +74,6 @@ class HugeSchemaBench
|
|||||||
return new Schema(
|
return new Schema(
|
||||||
\GraphQL\Type\SchemaConfig::create()
|
\GraphQL\Type\SchemaConfig::create()
|
||||||
->setQuery($this->schemaBuilder->buildQueryType())
|
->setQuery($this->schemaBuilder->buildQueryType())
|
||||||
// ->setDescriptor($this->descriptor)
|
|
||||||
->setTypeLoader(function($name) {
|
->setTypeLoader(function($name) {
|
||||||
return $this->schemaBuilder->loadType($name);
|
return $this->schemaBuilder->loadType($name);
|
||||||
})
|
})
|
||||||
|
@ -1062,7 +1062,7 @@ class Executor
|
|||||||
$runtimeType = $returnType->resolveType($result, $exeContext->contextValue, $info);
|
$runtimeType = $returnType->resolveType($result, $exeContext->contextValue, $info);
|
||||||
|
|
||||||
if (null === $runtimeType) {
|
if (null === $runtimeType) {
|
||||||
if ($returnType instanceof InterfaceType && !$exeContext->schema->getConfig()->descriptor) {
|
if ($returnType instanceof InterfaceType) {
|
||||||
Warning::warnOnce(
|
Warning::warnOnce(
|
||||||
"GraphQL Interface Type `{$returnType->name}` returned `null` from it`s `resolveType` function ".
|
"GraphQL Interface Type `{$returnType->name}` returned `null` from it`s `resolveType` function ".
|
||||||
'for value: ' . Utils::printSafe($result) . '. Switching to slow resolution method using `isTypeOf` ' .
|
'for value: ' . Utils::printSafe($result) . '. Switching to slow resolution method using `isTypeOf` ' .
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace GraphQL\Type;
|
|
||||||
|
|
||||||
use GraphQL\Utils\Utils;
|
|
||||||
|
|
||||||
class Descriptor implements \JsonSerializable
|
|
||||||
{
|
|
||||||
public $version = '1.0';
|
|
||||||
|
|
||||||
public $typeMap = [];
|
|
||||||
|
|
||||||
public $possibleTypeMap = [];
|
|
||||||
|
|
||||||
public $created;
|
|
||||||
|
|
||||||
public static function fromArray(array $array)
|
|
||||||
{
|
|
||||||
Utils::invariant(
|
|
||||||
isset($array['version'], $array['typeMap'], $array['possibleTypeMap'], $array['created']),
|
|
||||||
__METHOD__ . ' expects array with keys "version", "typeMap", "possibleTypeMap", "created" but got keys: %s',
|
|
||||||
implode(', ', array_keys($array))
|
|
||||||
);
|
|
||||||
Utils::invariant(
|
|
||||||
is_string($array['version']) && '1.0' === $array['version'],
|
|
||||||
__METHOD__ . ' expects array where "version" key equals to "1.0"'
|
|
||||||
);
|
|
||||||
Utils::invariant(
|
|
||||||
is_array($array['typeMap']) && is_array($array['possibleTypeMap']),
|
|
||||||
__METHOD__ . ' expects array where "typeMap" and "possibleTypeMap" keys are arrays'
|
|
||||||
);
|
|
||||||
Utils::invariant(
|
|
||||||
is_int($array['created']),
|
|
||||||
__METHOD__ . ' expects array where "created" key is integer timestamp'
|
|
||||||
);
|
|
||||||
|
|
||||||
$descriptor = new self();
|
|
||||||
Utils::assign($descriptor, $array);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toArray()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'typeMap' => $this->typeMap,
|
|
||||||
'version' => $this->version,
|
|
||||||
'possibleTypeMap' => $this->possibleTypeMap,
|
|
||||||
'created' => $this->created
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify data which should be serialized to JSON
|
|
||||||
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
|
|
||||||
* @return mixed data which can be serialized by <b>json_encode</b>,
|
|
||||||
* which is a value of any type other than a resource.
|
|
||||||
* @since 5.4.0
|
|
||||||
*/
|
|
||||||
function jsonSerialize()
|
|
||||||
{
|
|
||||||
return $this->toArray();
|
|
||||||
}
|
|
||||||
}
|
|
@ -49,13 +49,6 @@ class Schema
|
|||||||
*/
|
*/
|
||||||
private $config;
|
private $config;
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains actual descriptor for this schema
|
|
||||||
*
|
|
||||||
* @var Descriptor
|
|
||||||
*/
|
|
||||||
private $descriptor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains currently resolved schema types
|
* Contains currently resolved schema types
|
||||||
*
|
*
|
||||||
@ -63,6 +56,11 @@ class Schema
|
|||||||
*/
|
*/
|
||||||
private $resolvedTypes = [];
|
private $resolvedTypes = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $possibleTypeMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True when $resolvedTypes contain all possible schema types
|
* True when $resolvedTypes contain all possible schema types
|
||||||
*
|
*
|
||||||
@ -104,8 +102,7 @@ class Schema
|
|||||||
'subscription',
|
'subscription',
|
||||||
'types',
|
'types',
|
||||||
'directives',
|
'directives',
|
||||||
'typeLoader',
|
'typeLoader'
|
||||||
'descriptor'
|
|
||||||
]),
|
]),
|
||||||
Utils::getVariableType($config)
|
Utils::getVariableType($config)
|
||||||
);
|
);
|
||||||
@ -116,6 +113,15 @@ class Schema
|
|||||||
);
|
);
|
||||||
|
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
|
|
||||||
|
$this->resolvedTypes[$config->query->name] = $config->query;
|
||||||
|
|
||||||
|
if ($config->mutation) {
|
||||||
|
$this->resolvedTypes[$config->mutation->name] = $config->mutation;
|
||||||
|
}
|
||||||
|
if ($config->subscription) {
|
||||||
|
$this->resolvedTypes[$config->subscription->name] = $config->subscription;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,15 +171,7 @@ class Schema
|
|||||||
public function getTypeMap()
|
public function getTypeMap()
|
||||||
{
|
{
|
||||||
if (!$this->fullyLoaded) {
|
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->resolvedTypes = $this->collectAllTypes();
|
||||||
}
|
|
||||||
$this->fullyLoaded = true;
|
$this->fullyLoaded = true;
|
||||||
}
|
}
|
||||||
return $this->resolvedTypes;
|
return $this->resolvedTypes;
|
||||||
@ -190,51 +188,11 @@ class Schema
|
|||||||
return $this->resolveType($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()
|
private function collectAllTypes()
|
||||||
{
|
{
|
||||||
$initialTypes = array_merge(
|
$initialTypes = array_merge(
|
||||||
[
|
array_values($this->resolvedTypes),
|
||||||
$this->config->query,
|
[Introspection::_schema()]
|
||||||
$this->config->mutation,
|
|
||||||
$this->config->subscription,
|
|
||||||
Introspection::_schema()
|
|
||||||
],
|
|
||||||
array_values($this->resolvedTypes)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$typeMap = [];
|
$typeMap = [];
|
||||||
@ -276,20 +234,30 @@ class Schema
|
|||||||
*/
|
*/
|
||||||
public function getPossibleTypes(AbstractType $abstractType)
|
public function getPossibleTypes(AbstractType $abstractType)
|
||||||
{
|
{
|
||||||
if ($abstractType instanceof UnionType) {
|
$possibleTypeMap = $this->getPossibleTypeMap();
|
||||||
return $abstractType->getTypes();
|
return array_values($possibleTypeMap[$abstractType->name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var InterfaceType $abstractType */
|
/**
|
||||||
$descriptor = $this->config->descriptor ?: $this->describe();
|
* @return array
|
||||||
|
*/
|
||||||
$result = [];
|
private function getPossibleTypeMap()
|
||||||
if (isset($descriptor->possibleTypeMap[$abstractType->name])) {
|
{
|
||||||
foreach ($descriptor->possibleTypeMap[$abstractType->name] as $typeName => $_) {
|
if ($this->possibleTypeMap === null) {
|
||||||
$result[] = $this->resolveType($typeName);
|
$this->possibleTypeMap = [];
|
||||||
|
foreach ($this->getTypeMap() as $type) {
|
||||||
|
if ($type instanceof ObjectType) {
|
||||||
|
foreach ($type->getInterfaces() as $interface) {
|
||||||
|
$this->possibleTypeMap[$interface->name][$type->name] = $type;
|
||||||
|
}
|
||||||
|
} else if ($type instanceof UnionType) {
|
||||||
|
foreach ($type->getTypes() as $innerType) {
|
||||||
|
$this->possibleTypeMap[$type->name][$innerType->name] = $innerType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $result;
|
}
|
||||||
|
}
|
||||||
|
return $this->possibleTypeMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,10 +304,6 @@ class Schema
|
|||||||
*/
|
*/
|
||||||
public function isPossibleType(AbstractType $abstractType, ObjectType $possibleType)
|
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) {
|
if ($abstractType instanceof InterfaceType) {
|
||||||
return $possibleType->implementsInterface($abstractType);
|
return $possibleType->implementsInterface($abstractType);
|
||||||
}
|
}
|
||||||
@ -381,14 +345,8 @@ class Schema
|
|||||||
private function defaultTypeLoader($typeName)
|
private function defaultTypeLoader($typeName)
|
||||||
{
|
{
|
||||||
// Default type loader simply fallbacks to collecting all types
|
// Default type loader simply fallbacks to collecting all types
|
||||||
if (!$this->fullyLoaded) {
|
$typeMap = $this->getTypeMap();
|
||||||
$this->resolvedTypes = $this->collectAllTypes();
|
return isset($typeMap[$typeName]) ? $typeMap[$typeName] : null;
|
||||||
$this->fullyLoaded = true;
|
|
||||||
}
|
|
||||||
if (!isset($this->resolvedTypes[$typeName])) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return $this->resolvedTypes[$typeName];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace GraphQL\Type;
|
namespace GraphQL\Type;
|
||||||
|
|
||||||
use GraphQL\Error\InvariantViolation;
|
|
||||||
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;
|
||||||
@ -41,11 +39,6 @@ class SchemaConfig
|
|||||||
*/
|
*/
|
||||||
public $directives;
|
public $directives;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Descriptor
|
|
||||||
*/
|
|
||||||
public $descriptor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var callable
|
* @var callable
|
||||||
*/
|
*/
|
||||||
@ -105,6 +98,20 @@ class SchemaConfig
|
|||||||
$config->setDirectives($options['directives']);
|
$config->setDirectives($options['directives']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($options['typeResolution'])) {
|
||||||
|
trigger_error(
|
||||||
|
'Type resolution strategies are deprecated. Just pass single option `typeLoader` '.
|
||||||
|
'to schema constructor instead.',
|
||||||
|
E_USER_DEPRECATED
|
||||||
|
);
|
||||||
|
if ($options['typeResolution'] instanceof Resolution && !isset($options['typeLoader'])) {
|
||||||
|
$strategy = $options['typeResolution'];
|
||||||
|
$options['typeLoader'] = function($name) use ($strategy) {
|
||||||
|
return $strategy->resolveType($name);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($options['typeLoader'])) {
|
if (isset($options['typeLoader'])) {
|
||||||
Utils::invariant(
|
Utils::invariant(
|
||||||
is_callable($options['typeLoader']),
|
is_callable($options['typeLoader']),
|
||||||
@ -113,15 +120,6 @@ class SchemaConfig
|
|||||||
);
|
);
|
||||||
$config->setTypeLoader($options['typeLoader']);
|
$config->setTypeLoader($options['typeLoader']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($options['descriptor'])) {
|
|
||||||
Utils::invariant(
|
|
||||||
$options['descriptor'] instanceof Descriptor,
|
|
||||||
'Schema descriptor must be instance of GraphQL\Type\Descriptor but got: %s',
|
|
||||||
Utils::getVariableType($options['descriptor'])
|
|
||||||
);
|
|
||||||
$config->setDescriptor($options['descriptor']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $config;
|
return $config;
|
||||||
@ -217,24 +215,6 @@ class SchemaConfig
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Descriptor
|
|
||||||
*/
|
|
||||||
public function getDescriptor()
|
|
||||||
{
|
|
||||||
return $this->descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Descriptor $descriptor
|
|
||||||
* @return SchemaConfig
|
|
||||||
*/
|
|
||||||
public function setDescriptor(Descriptor $descriptor)
|
|
||||||
{
|
|
||||||
$this->descriptor = $descriptor;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return callable
|
* @return callable
|
||||||
*/
|
*/
|
||||||
|
@ -106,7 +106,7 @@ class TypeInfo
|
|||||||
}
|
}
|
||||||
if (!$type instanceof Type) {
|
if (!$type instanceof Type) {
|
||||||
Warning::warnOnce(
|
Warning::warnOnce(
|
||||||
'One of schema types is not a valid type definition instance. Ignoring it. '.
|
'One of the schema types is not a valid type definition instance. '.
|
||||||
'Try running $schema->assertValid() to find out the cause of this warning.',
|
'Try running $schema->assertValid() to find out the cause of this warning.',
|
||||||
Warning::NOT_A_TYPE
|
Warning::NOT_A_TYPE
|
||||||
);
|
);
|
||||||
|
@ -577,7 +577,7 @@ class DefinitionTest extends \PHPUnit_Framework_TestCase
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertFalse($called);
|
$this->assertFalse($called);
|
||||||
$schema->getType('Query');
|
$schema->getType('Blog');
|
||||||
$this->assertTrue($called);
|
$this->assertTrue($called);
|
||||||
|
|
||||||
$this->assertEquals([$node], $blog->getInterfaces());
|
$this->assertEquals([$node], $blog->getInterfaces());
|
||||||
|
Loading…
Reference in New Issue
Block a user