mirror of
https://github.com/retailcrm/graphql-php.git
synced 2025-02-06 07:49:24 +03:00
Added DefinitionContainer interface to enable compositional use of user-land types (vs extending ObjectType, InterfaceType, etc). Very similar to IteratorAggregate vs Iterator
This commit is contained in:
parent
c11f25794a
commit
9941a0143a
@ -19,6 +19,7 @@ use GraphQL\Type\Definition\ObjectType;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\ScalarType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Type\Introspection;
|
||||
use GraphQL\Utils;
|
||||
|
||||
@ -744,6 +745,10 @@ class Executor
|
||||
$runtimeType = $exeContext->schema->getType($runtimeType);
|
||||
}
|
||||
|
||||
if ($runtimeType instanceof DefinitionContainer) {
|
||||
$runtimeType = $runtimeType->getDefinition();
|
||||
}
|
||||
|
||||
if (!($runtimeType instanceof ObjectType)) {
|
||||
throw new Error(
|
||||
"Abstract type {$returnType} must resolve to an Object type at runtime " .
|
||||
|
@ -9,6 +9,7 @@ use GraphQL\Type\Definition\ObjectType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use GraphQL\Type\Definition\UnionType;
|
||||
use GraphQL\Type\Definition\WrappingType;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Type\Introspection;
|
||||
|
||||
/**
|
||||
@ -113,6 +114,18 @@ class Schema
|
||||
'validate' => true
|
||||
];
|
||||
|
||||
if ($config['query'] instanceof DefinitionContainer) {
|
||||
$config['query'] = $config['query']->getDefinition();
|
||||
}
|
||||
|
||||
if ($config['mutation'] instanceof DefinitionContainer) {
|
||||
$config['mutation'] = $config['mutation']->getDefinition();
|
||||
}
|
||||
|
||||
if ($config['subscription'] instanceof DefinitionContainer) {
|
||||
$config['subscription'] = $config['subscription']->getDefinition();
|
||||
}
|
||||
|
||||
Utils::invariant(
|
||||
$config['query'] instanceof ObjectType,
|
||||
"Schema query must be Object Type but got: " . Utils::getVariableType($config['query'])
|
||||
@ -299,6 +312,9 @@ class Schema
|
||||
if (!$type) {
|
||||
return $this->typeMap;
|
||||
}
|
||||
if ($type instanceof DefinitionContainer) {
|
||||
$type = $type->getDefinition();
|
||||
}
|
||||
|
||||
if ($type instanceof WrappingType) {
|
||||
return $this->extractTypes($type->getWrappedType(true));
|
||||
|
@ -2,6 +2,7 @@
|
||||
namespace GraphQL\Type\Definition;
|
||||
|
||||
use GraphQL\Error\InvariantViolation;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Utils;
|
||||
|
||||
/**
|
||||
@ -188,6 +189,10 @@ class Config
|
||||
$err = 'Error in "'.$typeName.'" type definition: ' . "Each entry at '$pathStr' must be an array, but '%s' is '%s'";
|
||||
|
||||
foreach ($value as $arrKey => $arrValue) {
|
||||
if ($arrValue instanceof DefinitionContainer) {
|
||||
$arrValue = $arrValue->getDefinition();
|
||||
}
|
||||
|
||||
if (is_array($def->definition)) {
|
||||
if ($def->flags & self::MAYBE_TYPE && $arrValue instanceof Type) {
|
||||
$arrValue = ['type' => $arrValue];
|
||||
@ -220,6 +225,10 @@ class Config
|
||||
return ; // Allow nulls for non-required fields
|
||||
}
|
||||
|
||||
if ($value instanceof DefinitionContainer) {
|
||||
$value = $value->getDefinition();
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
case $def & self::ANY:
|
||||
break;
|
||||
|
@ -52,7 +52,7 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<FieldDefinition>
|
||||
* @return FieldDefinition[]
|
||||
*/
|
||||
public function getFields()
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace GraphQL\Type\Definition;
|
||||
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Utils;
|
||||
|
||||
/**
|
||||
@ -15,12 +16,12 @@ class ListOfType extends Type implements WrappingType, OutputType, InputType
|
||||
public $ofType;
|
||||
|
||||
/**
|
||||
* @param callable|Type $type
|
||||
* @param callable|Type|DefinitionContainer $type
|
||||
*/
|
||||
public function __construct($type)
|
||||
{
|
||||
Utils::invariant(
|
||||
$type instanceof Type || is_callable($type),
|
||||
$type instanceof Type || $type instanceof DefinitionContainer || is_callable($type),
|
||||
'Expecting instance of GraphQL\Type\Definition\Type or callable returning instance of that class'
|
||||
);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace GraphQL\Type\Definition;
|
||||
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Type\TypeKind;
|
||||
use GraphQL\Utils;
|
||||
|
||||
@ -16,13 +17,13 @@ class NonNull extends Type implements WrappingType, OutputType, InputType
|
||||
protected $ofType;
|
||||
|
||||
/**
|
||||
* @param callable|Type $type
|
||||
* @param callable|Type|DefinitionContainer $type
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($type)
|
||||
{
|
||||
Utils::invariant(
|
||||
$type instanceof Type || is_callable($type),
|
||||
$type instanceof Type || $type instanceof DefinitionContainer || is_callable($type),
|
||||
'Expecting instance of GraphQL\Type\Definition\Type or callable returning instance of that class'
|
||||
);
|
||||
Utils::invariant(
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
namespace GraphQL\Type\Definition;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Utils;
|
||||
|
||||
|
||||
@ -139,6 +140,12 @@ class ObjectType extends Type implements OutputType, CompositeType
|
||||
if (null === $this->interfaces) {
|
||||
$interfaces = isset($this->config['interfaces']) ? $this->config['interfaces'] : [];
|
||||
$interfaces = is_callable($interfaces) ? call_user_func($interfaces) : $interfaces;
|
||||
|
||||
// TODO: Return some sort of generator to avoid multiple loops
|
||||
$interfaces = Utils::map($interfaces, function($iface) {
|
||||
return $iface instanceof DefinitionContainer ? $iface->getDefinition() : $iface;
|
||||
});
|
||||
|
||||
$this->interfaces = $interfaces;
|
||||
}
|
||||
return $this->interfaces;
|
||||
|
@ -2,6 +2,7 @@
|
||||
namespace GraphQL\Type\Definition;
|
||||
|
||||
use GraphQL\Error\InvariantViolation;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Utils;
|
||||
|
||||
/*
|
||||
@ -198,6 +199,9 @@ abstract class Type
|
||||
);
|
||||
$type = $type();
|
||||
}
|
||||
if ($type instanceof DefinitionContainer) {
|
||||
$type = $type->getDefinition();
|
||||
}
|
||||
|
||||
if (!$type instanceof Type) {
|
||||
throw new InvariantViolation(sprintf(
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace GraphQL\Type\Definition;
|
||||
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Utils;
|
||||
|
||||
/**
|
||||
@ -42,8 +43,6 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType
|
||||
'description' => Config::STRING
|
||||
]);
|
||||
|
||||
Utils::invariant(!empty($config['types']), "");
|
||||
|
||||
/**
|
||||
* Optionally provide a custom type resolver function. If one is not provided,
|
||||
* the default implemenation will call `isTypeOf` on each implementing
|
||||
@ -51,7 +50,6 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType
|
||||
*/
|
||||
$this->name = $config['name'];
|
||||
$this->description = isset($config['description']) ? $config['description'] : null;
|
||||
$this->types = $config['types'];
|
||||
$this->resolveTypeFn = isset($config['resolveType']) ? $config['resolveType'] : null;
|
||||
$this->config = $config;
|
||||
}
|
||||
@ -70,13 +68,23 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType
|
||||
*/
|
||||
public function getTypes()
|
||||
{
|
||||
if ($this->types instanceof \Closure) {
|
||||
$this->types = call_user_func($this->types);
|
||||
if (null === $this->types) {
|
||||
if ($this->config['types'] instanceof \Closure) {
|
||||
$types = call_user_func($this->config['types']);
|
||||
} else {
|
||||
$types = $this->config['types'];
|
||||
}
|
||||
|
||||
Utils::invariant(
|
||||
is_array($this->types),
|
||||
'Closure for option "types" of union "%s" is expected to return array of types',
|
||||
is_array($types),
|
||||
'Option "types" of union "%s" is expected to return array of types (or closure returning array of types)',
|
||||
$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;
|
||||
});
|
||||
}
|
||||
return $this->types;
|
||||
}
|
||||
|
15
src/Type/DefinitionContainer.php
Normal file
15
src/Type/DefinitionContainer.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace GraphQL\Type;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
/**
|
||||
* Interface DefinitionContainer
|
||||
* @package GraphQL\Type
|
||||
*/
|
||||
interface DefinitionContainer
|
||||
{
|
||||
/**
|
||||
* @return Type
|
||||
*/
|
||||
public function getDefinition();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user