diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index f767b98..81a895c 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -722,11 +722,11 @@ class Executor */ private static function completeAbstractValue(ExecutionContext $exeContext, AbstractType $returnType, $fieldASTs, ResolveInfo $info, $path, &$result) { - $resolveType = $returnType->getResolveTypeFn(); + $runtimeType = $returnType->resolveType($result, $exeContext->contextValue, $info); - $runtimeType = $resolveType ? - call_user_func($resolveType, $result, $exeContext->contextValue, $info) : - Type::getTypeOf($result, $exeContext->contextValue, $info, $returnType); + if (null === $runtimeType) { + $runtimeType = self::inferTypeOf($result, $exeContext->contextValue, $info, $returnType); + } // If resolveType returns a string, we assume it's a ObjectType name. if (is_string($runtimeType)) { @@ -849,4 +849,25 @@ class Executor return self::executeFields($exeContext, $returnType, $result, $path, $subFieldASTs); } + + /** + * Infer type of the value using isTypeOf of corresponding AbstractType + * + * @param $value + * @param $context + * @param ResolveInfo $info + * @param AbstractType $abstractType + * @return ObjectType|null + */ + private static function inferTypeOf($value, $context, ResolveInfo $info, AbstractType $abstractType) + { + $possibleTypes = $info->schema->getPossibleTypes($abstractType); + + foreach ($possibleTypes as $type) { + if ($type->isTypeOf($value, $context, $info)) { + return $type; + } + } + return null; + } } diff --git a/src/Type/Definition/AbstractType.php b/src/Type/Definition/AbstractType.php index 97fa1c3..dd27677 100644 --- a/src/Type/Definition/AbstractType.php +++ b/src/Type/Definition/AbstractType.php @@ -9,7 +9,12 @@ GraphQLUnionType; interface AbstractType { /** - * @return callable|null + * Resolves concrete ObjectType for given object value + * + * @param $objectValue + * @param $context + * @param ResolveInfo $info + * @return mixed */ - public function getResolveTypeFn(); + public function resolveType($objectValue, $context, ResolveInfo $info); } diff --git a/src/Type/Definition/InterfaceType.php b/src/Type/Definition/InterfaceType.php index 410de70..dfe65f6 100644 --- a/src/Type/Definition/InterfaceType.php +++ b/src/Type/Definition/InterfaceType.php @@ -19,11 +19,6 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT */ public $description; - /** - * @var callback - */ - private $resolveTypeFn; - /** * @var array */ @@ -51,7 +46,6 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT $this->name = $config['name']; $this->description = isset($config['description']) ? $config['description'] : null; - $this->resolveTypeFn = isset($config['resolveType']) ? $config['resolveType'] : null; $this->config = $config; } @@ -84,10 +78,19 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT } /** + * Resolves concrete ObjectType for given object value + * + * @param $objectValue + * @param $context + * @param ResolveInfo $info * @return callable|null */ - public function getResolveTypeFn() + public function resolveType($objectValue, $context, ResolveInfo $info) { - return $this->resolveTypeFn; + if (isset($this->config['resolveType'])) { + $fn = $this->config['resolveType']; + return $fn($objectValue, $context, $info); + } + return null; } } diff --git a/src/Type/Definition/Type.php b/src/Type/Definition/Type.php index 52a1f63..02908b0 100644 --- a/src/Type/Definition/Type.php +++ b/src/Type/Definition/Type.php @@ -211,26 +211,6 @@ abstract class Type return $type; } - /** - * @param $value - * @param mixed $context - * @param AbstractType $abstractType - * @return Type - * @throws \Exception - */ - public static function getTypeOf($value, $context, ResolveInfo $info, AbstractType $abstractType) - { - $possibleTypes = $info->schema->getPossibleTypes($abstractType); - - foreach ($possibleTypes as $type) { - /** @var ObjectType $type */ - if ($type->isTypeOf($value, $context, $info)) { - return $type; - } - } - return null; - } - /** * @var string */ diff --git a/src/Type/Definition/UnionType.php b/src/Type/Definition/UnionType.php index e113986..a5b9c9f 100644 --- a/src/Type/Definition/UnionType.php +++ b/src/Type/Definition/UnionType.php @@ -20,11 +20,6 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType */ private $possibleTypeNames; - /** - * @var callback - */ - private $resolveTypeFn; - /** * @var array */ @@ -54,7 +49,6 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType */ $this->name = $config['name']; $this->description = isset($config['description']) ? $config['description'] : null; - $this->resolveTypeFn = isset($config['resolveType']) ? $config['resolveType'] : null; $this->config = $config; } @@ -85,10 +79,10 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType $this->name ); - // TODO: Return some sort of generator to avoid multiple loops - $this->types = Utils::map($types, function($type) { - return $type instanceof DefinitionContainer ? $type->getDefinition() : $type; - }); + $this->types = []; + foreach ($types as $type) { + $this->types[] = Type::resolve($type); + } } return $this->types; } @@ -113,10 +107,19 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType } /** + * Resolves concrete ObjectType for given object value + * + * @param $objectValue + * @param $context + * @param ResolveInfo $info * @return callable|null */ - public function getResolveTypeFn() + public function resolveType($objectValue, $context, ResolveInfo $info) { - return $this->resolveTypeFn; + if (isset($this->config['resolveType'])) { + $fn = $this->config['resolveType']; + return $fn($objectValue, $context, $info); + } + return null; } }