mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-22 04:46:04 +03:00
Merge pull request #503 from simPod/fix-reference-executor
Fix ReferenceExecutor
This commit is contained in:
commit
974258b352
@ -134,16 +134,16 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
) {
|
) {
|
||||||
$errors = [];
|
$errors = [];
|
||||||
$fragments = [];
|
$fragments = [];
|
||||||
/** @var OperationDefinitionNode $operation */
|
/** @var OperationDefinitionNode|null $operation */
|
||||||
$operation = null;
|
$operation = null;
|
||||||
$hasMultipleAssumedOperations = false;
|
$hasMultipleAssumedOperations = false;
|
||||||
foreach ($documentNode->definitions as $definition) {
|
foreach ($documentNode->definitions as $definition) {
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case $definition instanceof OperationDefinitionNode:
|
case $definition instanceof OperationDefinitionNode:
|
||||||
if (! $operationName && $operation) {
|
if ($operationName === null && $operation !== null) {
|
||||||
$hasMultipleAssumedOperations = true;
|
$hasMultipleAssumedOperations = true;
|
||||||
}
|
}
|
||||||
if (! $operationName ||
|
if ($operationName === null ||
|
||||||
(isset($definition->name) && $definition->name->value === $operationName)) {
|
(isset($definition->name) && $definition->name->value === $operationName)) {
|
||||||
$operation = $definition;
|
$operation = $definition;
|
||||||
}
|
}
|
||||||
@ -154,10 +154,10 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($operation === null) {
|
if ($operation === null) {
|
||||||
if ($operationName) {
|
if ($operationName === null) {
|
||||||
$errors[] = new Error(sprintf('Unknown operation named "%s".', $operationName));
|
|
||||||
} else {
|
|
||||||
$errors[] = new Error('Must provide an operation.');
|
$errors[] = new Error('Must provide an operation.');
|
||||||
|
} else {
|
||||||
|
$errors[] = new Error(sprintf('Unknown operation named "%s".', $operationName));
|
||||||
}
|
}
|
||||||
} elseif ($hasMultipleAssumedOperations) {
|
} elseif ($hasMultipleAssumedOperations) {
|
||||||
$errors[] = new Error(
|
$errors[] = new Error(
|
||||||
@ -288,7 +288,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
switch ($operation->operation) {
|
switch ($operation->operation) {
|
||||||
case 'query':
|
case 'query':
|
||||||
$queryType = $schema->getQueryType();
|
$queryType = $schema->getQueryType();
|
||||||
if (! $queryType) {
|
if ($queryType === null) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Schema does not define the required query root type.',
|
'Schema does not define the required query root type.',
|
||||||
[$operation]
|
[$operation]
|
||||||
@ -298,7 +298,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
return $queryType;
|
return $queryType;
|
||||||
case 'mutation':
|
case 'mutation':
|
||||||
$mutationType = $schema->getMutationType();
|
$mutationType = $schema->getMutationType();
|
||||||
if (! $mutationType) {
|
if ($mutationType === null) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Schema is not configured for mutations.',
|
'Schema is not configured for mutations.',
|
||||||
[$operation]
|
[$operation]
|
||||||
@ -308,7 +308,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
return $mutationType;
|
return $mutationType;
|
||||||
case 'subscription':
|
case 'subscription':
|
||||||
$subscriptionType = $schema->getSubscriptionType();
|
$subscriptionType = $schema->getSubscriptionType();
|
||||||
if (! $subscriptionType) {
|
if ($subscriptionType === null) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Schema is not configured for subscriptions.',
|
'Schema is not configured for subscriptions.',
|
||||||
[$operation]
|
[$operation]
|
||||||
@ -377,7 +377,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
$visitedFragmentNames[$fragName] = true;
|
$visitedFragmentNames[$fragName] = true;
|
||||||
/** @var FragmentDefinitionNode|null $fragment */
|
/** @var FragmentDefinitionNode|null $fragment */
|
||||||
$fragment = $exeContext->fragments[$fragName] ?? null;
|
$fragment = $exeContext->fragments[$fragName] ?? null;
|
||||||
if (! $fragment || ! $this->doesFragmentConditionMatch($fragment, $runtimeType)) {
|
if ($fragment === null || ! $this->doesFragmentConditionMatch($fragment, $runtimeType)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$this->collectFields(
|
$this->collectFields(
|
||||||
@ -398,10 +398,8 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
* directives, where @skip has higher precedence than @include.
|
* directives, where @skip has higher precedence than @include.
|
||||||
*
|
*
|
||||||
* @param FragmentSpreadNode|FieldNode|InlineFragmentNode $node
|
* @param FragmentSpreadNode|FieldNode|InlineFragmentNode $node
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
private function shouldIncludeNode($node)
|
private function shouldIncludeNode($node) : bool
|
||||||
{
|
{
|
||||||
$variableValues = $this->exeContext->variableValues;
|
$variableValues = $this->exeContext->variableValues;
|
||||||
$skipDirective = Directive::skipDirective();
|
$skipDirective = Directive::skipDirective();
|
||||||
@ -425,12 +423,10 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the logic to compute the key of a given fields entry
|
* Implements the logic to compute the key of a given fields entry
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
private static function getFieldEntryKey(FieldNode $node)
|
private static function getFieldEntryKey(FieldNode $node) : string
|
||||||
{
|
{
|
||||||
return $node->alias ? $node->alias->value : $node->name->value;
|
return $node->alias === null ? $node->name->value : $node->alias->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -482,7 +478,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
$promise = $this->getPromise($result);
|
$promise = $this->getPromise($result);
|
||||||
if ($promise) {
|
if ($promise !== null) {
|
||||||
return $promise->then(static function ($resolvedResult) use ($responseName, $results) {
|
return $promise->then(static function ($resolvedResult) use ($responseName, $results) {
|
||||||
$results[$responseName] = $resolvedResult;
|
$results[$responseName] = $resolvedResult;
|
||||||
|
|
||||||
@ -523,7 +519,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
$fieldNode = $fieldNodes[0];
|
$fieldNode = $fieldNodes[0];
|
||||||
$fieldName = $fieldNode->name->value;
|
$fieldName = $fieldNode->name->value;
|
||||||
$fieldDef = $this->getFieldDef($exeContext->schema, $parentType, $fieldName);
|
$fieldDef = $this->getFieldDef($exeContext->schema, $parentType, $fieldName);
|
||||||
if (! $fieldDef) {
|
if ($fieldDef === null) {
|
||||||
return self::$UNDEFINED;
|
return self::$UNDEFINED;
|
||||||
}
|
}
|
||||||
$returnType = $fieldDef->getType();
|
$returnType = $fieldDef->getType();
|
||||||
@ -582,12 +578,8 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
* are allowed, like on a Union. __schema could get automatically
|
* are allowed, like on a Union. __schema could get automatically
|
||||||
* added to the query type, but that would require mutating type
|
* added to the query type, but that would require mutating type
|
||||||
* definitions, which would cause issues.
|
* definitions, which would cause issues.
|
||||||
*
|
|
||||||
* @param string $fieldName
|
|
||||||
*
|
|
||||||
* @return FieldDefinition
|
|
||||||
*/
|
*/
|
||||||
private function getFieldDef(Schema $schema, ObjectType $parentType, $fieldName)
|
private function getFieldDef(Schema $schema, ObjectType $parentType, string $fieldName) : ?FieldDefinition
|
||||||
{
|
{
|
||||||
static $schemaMetaFieldDef, $typeMetaFieldDef, $typeNameMetaFieldDef;
|
static $schemaMetaFieldDef, $typeMetaFieldDef, $typeNameMetaFieldDef;
|
||||||
$schemaMetaFieldDef = $schemaMetaFieldDef ?: Introspection::schemaMetaFieldDef();
|
$schemaMetaFieldDef = $schemaMetaFieldDef ?: Introspection::schemaMetaFieldDef();
|
||||||
@ -681,7 +673,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
$promise = $this->getPromise($completed);
|
$promise = $this->getPromise($completed);
|
||||||
if ($promise) {
|
if ($promise !== null) {
|
||||||
return $promise->then(
|
return $promise->then(
|
||||||
null,
|
null,
|
||||||
function ($error) use ($exeContext) {
|
function ($error) use ($exeContext) {
|
||||||
@ -730,7 +722,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
$promise = $this->getPromise($completed);
|
$promise = $this->getPromise($completed);
|
||||||
if ($promise) {
|
if ($promise !== null) {
|
||||||
return $promise->then(
|
return $promise->then(
|
||||||
null,
|
null,
|
||||||
function ($error) use ($fieldNodes, $path) {
|
function ($error) use ($fieldNodes, $path) {
|
||||||
@ -790,7 +782,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
) {
|
) {
|
||||||
$promise = $this->getPromise($result);
|
$promise = $this->getPromise($result);
|
||||||
// If result is a Promise, apply-lift over completeValue.
|
// If result is a Promise, apply-lift over completeValue.
|
||||||
if ($promise) {
|
if ($promise !== null) {
|
||||||
return $promise->then(function (&$resolved) use ($returnType, $fieldNodes, $info, $path) {
|
return $promise->then(function (&$resolved) use ($returnType, $fieldNodes, $info, $path) {
|
||||||
return $this->completeValue($returnType, $fieldNodes, $info, $path, $resolved);
|
return $this->completeValue($returnType, $fieldNodes, $info, $path, $resolved);
|
||||||
});
|
});
|
||||||
@ -828,7 +820,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
// instance than `resolveType` or $field->getType() or $arg->getType()
|
// instance than `resolveType` or $field->getType() or $arg->getType()
|
||||||
if ($returnType !== $this->exeContext->schema->getType($returnType->name)) {
|
if ($returnType !== $this->exeContext->schema->getType($returnType->name)) {
|
||||||
$hint = '';
|
$hint = '';
|
||||||
if ($this->exeContext->schema->getConfig()->typeLoader) {
|
if ($this->exeContext->schema->getConfig()->typeLoader !== null) {
|
||||||
$hint = sprintf(
|
$hint = sprintf(
|
||||||
'Make sure that type loader returns the same instance as defined in %s.%s',
|
'Make sure that type loader returns the same instance as defined in %s.%s',
|
||||||
$info->parentType,
|
$info->parentType,
|
||||||
@ -908,7 +900,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
* @param mixed[] $values
|
* @param mixed[] $values
|
||||||
* @param Promise|mixed|null $initialValue
|
* @param Promise|mixed|null $initialValue
|
||||||
*
|
*
|
||||||
* @return mixed[]
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
private function promiseReduce(array $values, callable $callback, $initialValue)
|
private function promiseReduce(array $values, callable $callback, $initialValue)
|
||||||
{
|
{
|
||||||
@ -916,7 +908,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
$values,
|
$values,
|
||||||
function ($previous, $value) use ($callback) {
|
function ($previous, $value) use ($callback) {
|
||||||
$promise = $this->getPromise($previous);
|
$promise = $this->getPromise($previous);
|
||||||
if ($promise) {
|
if ($promise !== null) {
|
||||||
return $promise->then(static function ($resolved) use ($callback, $value) {
|
return $promise->then(static function ($resolved) use ($callback, $value) {
|
||||||
return $callback($resolved, $value);
|
return $callback($resolved, $value);
|
||||||
});
|
});
|
||||||
@ -954,7 +946,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
$fieldPath[] = $i++;
|
$fieldPath[] = $i++;
|
||||||
$info->path = $fieldPath;
|
$info->path = $fieldPath;
|
||||||
$completedItem = $this->completeValueCatchingError($itemType, $fieldNodes, $info, $fieldPath, $item);
|
$completedItem = $this->completeValueCatchingError($itemType, $fieldNodes, $info, $fieldPath, $item);
|
||||||
if (! $containsPromise && $this->getPromise($completedItem)) {
|
if (! $containsPromise && $this->getPromise($completedItem) !== null) {
|
||||||
$containsPromise = true;
|
$containsPromise = true;
|
||||||
}
|
}
|
||||||
$completedItems[] = $completedItem;
|
$completedItems[] = $completedItem;
|
||||||
@ -1013,7 +1005,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
$runtimeType = self::defaultTypeResolver($result, $exeContext->contextValue, $info, $returnType);
|
$runtimeType = self::defaultTypeResolver($result, $exeContext->contextValue, $info, $returnType);
|
||||||
}
|
}
|
||||||
$promise = $this->getPromise($runtimeType);
|
$promise = $this->getPromise($runtimeType);
|
||||||
if ($promise) {
|
if ($promise !== null) {
|
||||||
return $promise->then(function ($resolvedRuntimeType) use (
|
return $promise->then(function ($resolvedRuntimeType) use (
|
||||||
$returnType,
|
$returnType,
|
||||||
$fieldNodes,
|
$fieldNodes,
|
||||||
@ -1075,7 +1067,8 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
) {
|
) {
|
||||||
return $value['__typename'];
|
return $value['__typename'];
|
||||||
}
|
}
|
||||||
if ($abstractType instanceof InterfaceType && $info->schema->getConfig()->typeLoader) {
|
|
||||||
|
if ($abstractType instanceof InterfaceType && $info->schema->getConfig()->typeLoader !== null) {
|
||||||
Warning::warnOnce(
|
Warning::warnOnce(
|
||||||
sprintf(
|
sprintf(
|
||||||
'GraphQL Interface Type `%s` returned `null` from its `resolveType` function ' .
|
'GraphQL Interface Type `%s` returned `null` from its `resolveType` function ' .
|
||||||
@ -1097,7 +1090,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$promise = $this->getPromise($isTypeOfResult);
|
$promise = $this->getPromise($isTypeOfResult);
|
||||||
if ($promise) {
|
if ($promise !== null) {
|
||||||
$promisedIsTypeOfResults[$index] = $promise;
|
$promisedIsTypeOfResults[$index] = $promise;
|
||||||
} elseif ($isTypeOfResult) {
|
} elseif ($isTypeOfResult) {
|
||||||
return $type;
|
return $type;
|
||||||
@ -1138,7 +1131,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
$isTypeOf = $returnType->isTypeOf($result, $this->exeContext->contextValue, $info);
|
$isTypeOf = $returnType->isTypeOf($result, $this->exeContext->contextValue, $info);
|
||||||
if ($isTypeOf !== null) {
|
if ($isTypeOf !== null) {
|
||||||
$promise = $this->getPromise($isTypeOf);
|
$promise = $this->getPromise($isTypeOf);
|
||||||
if ($promise) {
|
if ($promise !== null) {
|
||||||
return $promise->then(function ($isTypeOfResult) use (
|
return $promise->then(function ($isTypeOfResult) use (
|
||||||
$returnType,
|
$returnType,
|
||||||
$fieldNodes,
|
$fieldNodes,
|
||||||
@ -1254,7 +1247,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
if ($result === self::$UNDEFINED) {
|
if ($result === self::$UNDEFINED) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (! $containsPromise && $this->getPromise($result)) {
|
if (! $containsPromise && $this->getPromise($result) !== null) {
|
||||||
$containsPromise = true;
|
$containsPromise = true;
|
||||||
}
|
}
|
||||||
$finalResults[$responseName] = $result;
|
$finalResults[$responseName] = $result;
|
||||||
@ -1316,7 +1309,6 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string|ObjectType|null $runtimeTypeOrName
|
* @param string|ObjectType|null $runtimeTypeOrName
|
||||||
* @param FieldNode[] $fieldNodes
|
|
||||||
* @param mixed $result
|
* @param mixed $result
|
||||||
*
|
*
|
||||||
* @return ObjectType
|
* @return ObjectType
|
||||||
|
@ -21,7 +21,7 @@ class Directive
|
|||||||
public const REASON_ARGUMENT_NAME = 'reason';
|
public const REASON_ARGUMENT_NAME = 'reason';
|
||||||
|
|
||||||
/** @var Directive[] */
|
/** @var Directive[] */
|
||||||
public static $internalDirectives;
|
public static $internalDirectives = [];
|
||||||
|
|
||||||
// Schema Definitions
|
// Schema Definitions
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user