Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open ReferenceExecutor for extending #801

Merged
merged 2 commits into from Mar 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,9 @@
#### Unreleased
- PHP version required: 7.4+

Feat:
- Open ReferenceExecutor for extending

#### 14.5.1

Fix:
Expand Down
94 changes: 47 additions & 47 deletions src/Executor/ReferenceExecutor.php
Expand Up @@ -56,18 +56,18 @@
class ReferenceExecutor implements ExecutorImplementation
{
/** @var object */
private static $UNDEFINED;
protected static $UNDEFINED;

/** @var ExecutionContext */
private $exeContext;
protected $exeContext;

/** @var SplObjectStorage */
private $subFieldCache;
protected $subFieldCache;

private function __construct(ExecutionContext $context)
protected function __construct(ExecutionContext $context)
{
if (! self::$UNDEFINED) {
self::$UNDEFINED = Utils::undefined();
if (! static::$UNDEFINED) {
static::$UNDEFINED = Utils::undefined();
}

$this->exeContext = $context;
Expand All @@ -89,7 +89,7 @@ public static function create(
?string $operationName,
callable $fieldResolver
): ExecutorImplementation {
$exeContext = self::buildExecutionContext(
$exeContext = static::buildExecutionContext(
$schema,
$documentNode,
$rootValue,
Expand Down Expand Up @@ -118,7 +118,7 @@ public function doExecute(): Promise
};
}

return new self($exeContext);
return new static($exeContext);
}

/**
Expand All @@ -131,7 +131,7 @@ public function doExecute(): Promise
*
* @return ExecutionContext|array<Error>
*/
private static function buildExecutionContext(
protected static function buildExecutionContext(
Schema $schema,
DocumentNode $documentNode,
$rootValue,
Expand Down Expand Up @@ -237,7 +237,7 @@ public function doExecute(): Promise
*
* @return ExecutionResult|Promise
*/
private function buildResponse($data)
protected function buildResponse($data)
{
if ($this->isPromise($data)) {
return $data->then(function ($resolved) {
Expand All @@ -259,7 +259,7 @@ private function buildResponse($data)
*
* @return array<mixed>|Promise|stdClass|null
*/
private function executeOperation(OperationDefinitionNode $operation, $rootValue)
protected function executeOperation(OperationDefinitionNode $operation, $rootValue)
{
$type = $this->getOperationRootType($this->exeContext->schema, $operation);
$fields = $this->collectFields($type, $operation->selectionSet, new ArrayObject(), new ArrayObject());
Expand Down Expand Up @@ -301,7 +301,7 @@ function ($error): ?Promise {
*
* @throws Error
*/
private function getOperationRootType(Schema $schema, OperationDefinitionNode $operation): ObjectType
protected function getOperationRootType(Schema $schema, OperationDefinitionNode $operation): ObjectType
{
switch ($operation->operation) {
case 'query':
Expand Down Expand Up @@ -353,7 +353,7 @@ private function getOperationRootType(Schema $schema, OperationDefinitionNode $o
* returns an Interface or Union type, the "runtime type" will be the actual
* Object type returned by that field.
*/
private function collectFields(
protected function collectFields(
ObjectType $runtimeType,
SelectionSetNode $selectionSet,
ArrayObject $fields,
Expand All @@ -367,7 +367,7 @@ private function collectFields(
break;
}

$name = self::getFieldEntryKey($selection);
$name = static::getFieldEntryKey($selection);
if (! isset($fields[$name])) {
$fields[$name] = new ArrayObject();
}
Expand Down Expand Up @@ -422,7 +422,7 @@ private function collectFields(
*
* @param FragmentSpreadNode|FieldNode|InlineFragmentNode $node
*/
private function shouldIncludeNode(SelectionNode $node): bool
protected function shouldIncludeNode(SelectionNode $node): bool
{
$variableValues = $this->exeContext->variableValues;
$skipDirective = Directive::skipDirective();
Expand All @@ -448,7 +448,7 @@ private function shouldIncludeNode(SelectionNode $node): bool
/**
* Implements the logic to compute the key of a given fields entry
*/
private static function getFieldEntryKey(FieldNode $node): string
protected static function getFieldEntryKey(FieldNode $node): string
{
return $node->alias === null ? $node->name->value : $node->alias->value;
}
Expand All @@ -458,7 +458,7 @@ private static function getFieldEntryKey(FieldNode $node): string
*
* @param FragmentDefinitionNode|InlineFragmentNode $fragment
*/
private function doesFragmentConditionMatch(Node $fragment, ObjectType $type): bool
protected function doesFragmentConditionMatch(Node $fragment, ObjectType $type): bool
{
$typeConditionNode = $fragment->typeCondition;
if ($typeConditionNode === null) {
Expand Down Expand Up @@ -486,7 +486,7 @@ private function doesFragmentConditionMatch(Node $fragment, ObjectType $type): b
*
* @return array<mixed>|Promise|stdClass
*/
private function executeFieldsSerially(ObjectType $parentType, $rootValue, array $path, ArrayObject $fields)
protected function executeFieldsSerially(ObjectType $parentType, $rootValue, array $path, ArrayObject $fields)
{
$result = $this->promiseReduce(
array_keys($fields->getArrayCopy()),
Expand All @@ -495,7 +495,7 @@ function ($results, $responseName) use ($path, $parentType, $rootValue, $fields)
$fieldPath = $path;
$fieldPath[] = $responseName;
$result = $this->resolveField($parentType, $rootValue, $fieldNodes, $fieldPath);
if ($result === self::$UNDEFINED) {
if ($result === static::$UNDEFINED) {
return $results;
}

Expand All @@ -517,11 +517,11 @@ function ($results, $responseName) use ($path, $parentType, $rootValue, $fields)

if ($this->isPromise($result)) {
return $result->then(static function ($resolvedResults) {
return self::fixResultsIfEmptyArray($resolvedResults);
return static::fixResultsIfEmptyArray($resolvedResults);
});
}

return self::fixResultsIfEmptyArray($result);
return static::fixResultsIfEmptyArray($result);
}

/**
Expand All @@ -536,14 +536,14 @@ function ($results, $responseName) use ($path, $parentType, $rootValue, $fields)
*
* @return array<mixed>|Throwable|mixed|null
*/
private function resolveField(ObjectType $parentType, $rootValue, ArrayObject $fieldNodes, array $path)
protected function resolveField(ObjectType $parentType, $rootValue, ArrayObject $fieldNodes, array $path)
{
$exeContext = $this->exeContext;
$fieldNode = $fieldNodes[0];
$fieldName = $fieldNode->name->value;
$fieldDef = $this->getFieldDef($exeContext->schema, $parentType, $fieldName);
if ($fieldDef === null) {
return self::$UNDEFINED;
return static::$UNDEFINED;
}

$returnType = $fieldDef->getType();
Expand Down Expand Up @@ -601,7 +601,7 @@ private function resolveField(ObjectType $parentType, $rootValue, ArrayObject $f
* added to the query type, but that would require mutating type
* definitions, which would cause issues.
*/
private function getFieldDef(Schema $schema, ObjectType $parentType, string $fieldName): ?FieldDefinition
protected function getFieldDef(Schema $schema, ObjectType $parentType, string $fieldName): ?FieldDefinition
{
static $schemaMetaFieldDef, $typeMetaFieldDef, $typeNameMetaFieldDef;
$schemaMetaFieldDef ??= Introspection::schemaMetaFieldDef();
Expand Down Expand Up @@ -632,7 +632,7 @@ private function getFieldDef(Schema $schema, ObjectType $parentType, string $fie
*
* @return Throwable|Promise|mixed
*/
private function resolveFieldValueOrError(
protected function resolveFieldValueOrError(
FieldDefinition $fieldDef,
FieldNode $fieldNode,
callable $resolveFn,
Expand Down Expand Up @@ -664,7 +664,7 @@ private function resolveFieldValueOrError(
*
* @return array<mixed>|Promise|stdClass|null
*/
private function completeValueCatchingError(
protected function completeValueCatchingError(
Type $returnType,
ArrayObject $fieldNodes,
ResolveInfo $info,
Expand Down Expand Up @@ -704,7 +704,7 @@ private function completeValueCatchingError(
*
* @throws Error
*/
private function handleFieldError($rawError, ArrayObject $fieldNodes, array $path, Type $returnType): void
protected function handleFieldError($rawError, ArrayObject $fieldNodes, array $path, Type $returnType): void
{
$error = Error::createLocatedError(
$rawError,
Expand Down Expand Up @@ -752,7 +752,7 @@ private function handleFieldError($rawError, ArrayObject $fieldNodes, array $pat
* @throws Error
* @throws Throwable
*/
private function completeValue(
protected function completeValue(
Type $returnType,
ArrayObject $fieldNodes,
ResolveInfo $info,
Expand Down Expand Up @@ -836,7 +836,7 @@ private function completeValue(
/**
* @param mixed $value
*/
private function isPromise($value): bool
protected function isPromise($value): bool
{
return $value instanceof Promise || $this->exeContext->promiseAdapter->isThenable($value);
}
Expand All @@ -847,7 +847,7 @@ private function isPromise($value): bool
*
* @param mixed $value
*/
private function getPromise($value): ?Promise
protected function getPromise($value): ?Promise
{
if ($value === null || $value instanceof Promise) {
return $value;
Expand Down Expand Up @@ -881,7 +881,7 @@ private function getPromise($value): ?Promise
*
* @return Promise|mixed|null
*/
private function promiseReduce(array $values, callable $callback, $initialValue)
protected function promiseReduce(array $values, callable $callback, $initialValue)
{
return array_reduce(
$values,
Expand Down Expand Up @@ -909,7 +909,7 @@ function ($previous, $value) use ($callback) {
*
* @throws Exception
*/
private function completeListValue(ListOfType $returnType, ArrayObject $fieldNodes, ResolveInfo $info, array $path, &$results)
protected function completeListValue(ListOfType $returnType, ArrayObject $fieldNodes, ResolveInfo $info, array $path, &$results)
{
$itemType = $returnType->getWrappedType();
Utils::invariant(
Expand Down Expand Up @@ -945,7 +945,7 @@ private function completeListValue(ListOfType $returnType, ArrayObject $fieldNod
*
* @throws Exception
*/
private function completeLeafValue(LeafType $returnType, &$result)
protected function completeLeafValue(LeafType $returnType, &$result)
{
try {
return $returnType->serialize($result);
Expand All @@ -969,7 +969,7 @@ private function completeLeafValue(LeafType $returnType, &$result)
*
* @throws Error
*/
private function completeAbstractValue(
protected function completeAbstractValue(
AbstractType $returnType,
ArrayObject $fieldNodes,
ResolveInfo $info,
Expand All @@ -980,7 +980,7 @@ private function completeAbstractValue(
$typeCandidate = $returnType->resolveType($result, $exeContext->contextValue, $info);

if ($typeCandidate === null) {
$runtimeType = self::defaultTypeResolver($result, $exeContext->contextValue, $info, $returnType);
$runtimeType = static::defaultTypeResolver($result, $exeContext->contextValue, $info, $returnType);
} elseif (is_callable($typeCandidate)) {
$runtimeType = Schema::resolveType($typeCandidate);
} else {
Expand Down Expand Up @@ -1041,7 +1041,7 @@ private function completeAbstractValue(
*
* @return Promise|Type|string|null
*/
private function defaultTypeResolver($value, $contextValue, ResolveInfo $info, AbstractType $abstractType)
protected function defaultTypeResolver($value, $contextValue, ResolveInfo $info, AbstractType $abstractType)
{
// First, look for `__typename`.
if (
Expand Down Expand Up @@ -1110,7 +1110,7 @@ private function defaultTypeResolver($value, $contextValue, ResolveInfo $info, A
*
* @throws Error
*/
private function completeObjectValue(
protected function completeObjectValue(
ObjectType $returnType,
ArrayObject $fieldNodes,
ResolveInfo $info,
Expand Down Expand Up @@ -1161,7 +1161,7 @@ private function completeObjectValue(
*
* @return Error
*/
private function invalidReturnTypeError(
protected function invalidReturnTypeError(
ObjectType $returnType,
$result,
ArrayObject $fieldNodes
Expand All @@ -1180,7 +1180,7 @@ private function invalidReturnTypeError(
*
* @throws Error
*/
private function collectAndExecuteSubfields(
protected function collectAndExecuteSubfields(
ObjectType $returnType,
ArrayObject $fieldNodes,
array $path,
Expand All @@ -1196,7 +1196,7 @@ private function collectAndExecuteSubfields(
* type. Memoizing ensures the subfields are not repeatedly calculated, which
* saves overhead when resolving lists of values.
*/
private function collectSubFields(ObjectType $returnType, ArrayObject $fieldNodes): ArrayObject
protected function collectSubFields(ObjectType $returnType, ArrayObject $fieldNodes): ArrayObject
{
if (! isset($this->subFieldCache[$returnType])) {
$this->subFieldCache[$returnType] = new SplObjectStorage();
Expand Down Expand Up @@ -1234,15 +1234,15 @@ private function collectSubFields(ObjectType $returnType, ArrayObject $fieldNode
*
* @return Promise|stdClass|array<mixed>
*/
private function executeFields(ObjectType $parentType, $rootValue, array $path, ArrayObject $fields)
protected function executeFields(ObjectType $parentType, $rootValue, array $path, ArrayObject $fields)
{
$containsPromise = false;
$results = [];
foreach ($fields as $responseName => $fieldNodes) {
$fieldPath = $path;
$fieldPath[] = $responseName;
$result = $this->resolveField($parentType, $rootValue, $fieldNodes, $fieldPath);
if ($result === self::$UNDEFINED) {
if ($result === static::$UNDEFINED) {
continue;
}

Expand All @@ -1255,7 +1255,7 @@ private function executeFields(ObjectType $parentType, $rootValue, array $path,

// If there are no promises, we can just return the object
if (! $containsPromise) {
return self::fixResultsIfEmptyArray($results);
return static::fixResultsIfEmptyArray($results);
}

// Otherwise, results is a map from field name to the result of resolving that
Expand All @@ -1273,7 +1273,7 @@ private function executeFields(ObjectType $parentType, $rootValue, array $path,
*
* @return array<mixed>|stdClass|mixed
*/
private static function fixResultsIfEmptyArray($results)
protected static function fixResultsIfEmptyArray($results)
{
if ($results === []) {
return new stdClass();
Expand All @@ -1288,7 +1288,7 @@ private static function fixResultsIfEmptyArray($results)
*
* @param array<string, Promise|mixed> $assoc
*/
private function promiseForAssocArray(array $assoc): Promise
protected function promiseForAssocArray(array $assoc): Promise
{
$keys = array_keys($assoc);
$valuesAndPromises = array_values($assoc);
Expand All @@ -1300,7 +1300,7 @@ private function promiseForAssocArray(array $assoc): Promise
$resolvedResults[$keys[$i]] = $value;
}

return self::fixResultsIfEmptyArray($resolvedResults);
return static::fixResultsIfEmptyArray($resolvedResults);
});
}

Expand All @@ -1309,7 +1309,7 @@ private function promiseForAssocArray(array $assoc): Promise
* @param InterfaceType|UnionType $returnType
* @param mixed $result
*/
private function ensureValidRuntimeType(
protected function ensureValidRuntimeType(
$runtimeTypeOrName,
AbstractType $returnType,
ResolveInfo $info,
Expand Down