mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-25 06:16:05 +03:00
Reverted DefinitionContainer (YAGNI)
This commit is contained in:
parent
7c0aa4ceec
commit
0969073b8a
@ -26,7 +26,7 @@ $myType = new ObjectType([
|
||||
]);
|
||||
```
|
||||
|
||||
Class per type, using inheritance:
|
||||
Class per type:
|
||||
```php
|
||||
<?php
|
||||
namespace MyApp;
|
||||
@ -50,31 +50,6 @@ class MyType extends ObjectType
|
||||
}
|
||||
```
|
||||
|
||||
Class per type, using composition:
|
||||
```php
|
||||
<?php
|
||||
namespace MyApp;
|
||||
|
||||
use GraphQL\Type\Definition\ObjectType;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
|
||||
class MyType implements DefinitionContainer
|
||||
{
|
||||
private $definition;
|
||||
|
||||
public function getDefinition()
|
||||
{
|
||||
return $this->definition ?: ($this->definition = new ObjectType([
|
||||
'name' => 'MyType',
|
||||
'fields' => [
|
||||
'id' => Type::id()
|
||||
]
|
||||
]));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can also mix-and-match styles for convenience. For example:
|
||||
```php
|
||||
<?php
|
||||
|
@ -35,7 +35,7 @@ or hardcoded in source code) to **serialized** representation included in respon
|
||||
Those cases are covered by methods `serialize`, `parseValue` and `parseLiteral` of abstract `ScalarType`
|
||||
class respectively.
|
||||
|
||||
Here is an example of simple `Email` type (using inheritance):
|
||||
Here is an example of simple `Email` type:
|
||||
|
||||
```php
|
||||
<?php
|
||||
@ -109,30 +109,6 @@ class EmailType extends ScalarType
|
||||
}
|
||||
```
|
||||
|
||||
Same example, using composition over inheritance:
|
||||
```php
|
||||
<?php
|
||||
namespace MyApp;
|
||||
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Type\Definition\CustomScalarType;
|
||||
|
||||
class EmailType implements DefinitionContainer
|
||||
{
|
||||
private $definition;
|
||||
|
||||
public function getDefinition()
|
||||
{
|
||||
return $this->definition ?: ($this->definition = new CustomScalarType([
|
||||
'name' => 'Email',
|
||||
'serialize' => function($value) {/* See function body above */},
|
||||
'parseValue' => function($value) {/* See function body above */},
|
||||
'parseLiteral' => function($valueNode) {/* See function body above */},
|
||||
]));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Or with inline style:
|
||||
|
||||
```php
|
||||
|
@ -1,24 +0,0 @@
|
||||
<?php
|
||||
namespace GraphQL\Examples\Blog\Type;
|
||||
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
|
||||
abstract class BaseType implements DefinitionContainer
|
||||
{
|
||||
// Base class to reduce boilerplate for those who prefer own clean hierarchy of classes
|
||||
// (and avoids extending GraphQL classes directly)
|
||||
|
||||
/**
|
||||
* @var Type
|
||||
*/
|
||||
protected $definition;
|
||||
|
||||
/**
|
||||
* @return Type
|
||||
*/
|
||||
public function getDefinition()
|
||||
{
|
||||
return $this->definition;
|
||||
}
|
||||
}
|
@ -8,12 +8,11 @@ use GraphQL\Examples\Blog\Types;
|
||||
use GraphQL\Type\Definition\ObjectType;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
|
||||
class CommentType extends BaseType
|
||||
class CommentType extends ObjectType
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
|
||||
$this->definition = new ObjectType([
|
||||
$config = [
|
||||
'name' => 'Comment',
|
||||
'fields' => function() {
|
||||
return [
|
||||
@ -43,7 +42,8 @@ class CommentType extends BaseType
|
||||
return $value->{$info->fieldName};
|
||||
}
|
||||
}
|
||||
]);
|
||||
];
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
public function author(Comment $comment)
|
||||
|
@ -1,20 +1,19 @@
|
||||
<?php
|
||||
namespace GraphQL\Examples\Blog\Type\Enum;
|
||||
|
||||
use GraphQL\Examples\Blog\Type\BaseType;
|
||||
use GraphQL\Type\Definition\EnumType;
|
||||
|
||||
class ContentFormatEnum extends BaseType
|
||||
class ContentFormatEnum extends EnumType
|
||||
{
|
||||
const FORMAT_TEXT = 'TEXT';
|
||||
const FORMAT_HTML = 'HTML';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// Option #1: Define type using composition over inheritance, see ImageSizeEnumType for inheritance option
|
||||
$this->definition = new EnumType([
|
||||
$config = [
|
||||
'name' => 'ContentFormatEnum',
|
||||
'values' => [self::FORMAT_TEXT, self::FORMAT_HTML]
|
||||
]);
|
||||
];
|
||||
parent::__construct($config);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ class ImageSizeEnumType extends EnumType
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// Option #2: Define enum type using inheritance
|
||||
$config = [
|
||||
// Note: 'name' option is not needed in this form - it will be inferred from className
|
||||
'values' => [
|
||||
|
@ -11,7 +11,6 @@ class ImageType extends ObjectType
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// Option #2: define type using inheritance, see any other object type for compositional example
|
||||
$config = [
|
||||
'name' => 'ImageType',
|
||||
'fields' => [
|
||||
|
@ -7,21 +7,21 @@ use GraphQL\Examples\Blog\Data\Image;
|
||||
use GraphQL\Examples\Blog\Types;
|
||||
use GraphQL\Type\Definition\InterfaceType;
|
||||
|
||||
class NodeType extends BaseType
|
||||
class NodeType extends InterfaceType
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
|
||||
$this->definition = new InterfaceType([
|
||||
$config = [
|
||||
'name' => 'Node',
|
||||
'fields' => [
|
||||
'id' => Types::id()
|
||||
],
|
||||
'resolveType' => [$this, 'resolveType']
|
||||
]);
|
||||
'resolveType' => [$this, 'resolveNodeType']
|
||||
];
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
public function resolveType($object, Types $types)
|
||||
public function resolveNodeType($object)
|
||||
{
|
||||
if ($object instanceof User) {
|
||||
return Types::user();
|
||||
|
@ -8,12 +8,11 @@ use GraphQL\Type\Definition\ObjectType;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
class QueryType extends BaseType
|
||||
class QueryType extends ObjectType
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
|
||||
$this->definition = new ObjectType([
|
||||
$config = [
|
||||
'name' => 'Query',
|
||||
'fields' => [
|
||||
'user' => [
|
||||
@ -61,7 +60,8 @@ class QueryType extends BaseType
|
||||
'resolveField' => function($val, $args, $context, ResolveInfo $info) {
|
||||
return $this->{$info->fieldName}($val, $args, $context, $info);
|
||||
}
|
||||
]);
|
||||
];
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
public function user($rootValue, $args)
|
||||
|
@ -2,21 +2,19 @@
|
||||
namespace GraphQL\Examples\Blog\Type\Scalar;
|
||||
|
||||
use GraphQL\Error\Error;
|
||||
use GraphQL\Examples\Blog\Type\BaseType;
|
||||
use GraphQL\Language\AST\StringValueNode;
|
||||
use GraphQL\Type\Definition\CustomScalarType;
|
||||
use GraphQL\Utils;
|
||||
|
||||
class EmailType extends BaseType
|
||||
class EmailType
|
||||
{
|
||||
public function __construct()
|
||||
public static function create()
|
||||
{
|
||||
// Option #1: define scalar types using composition (see UrlType fo option #2 using inheritance)
|
||||
$this->definition = new CustomScalarType([
|
||||
return new CustomScalarType([
|
||||
'name' => 'Email',
|
||||
'serialize' => [$this, 'serialize'],
|
||||
'parseValue' => [$this, 'parseValue'],
|
||||
'parseLiteral' => [$this, 'parseLiteral'],
|
||||
'serialize' => [__CLASS__, 'serialize'],
|
||||
'parseValue' => [__CLASS__, 'parseValue'],
|
||||
'parseLiteral' => [__CLASS__, 'parseLiteral'],
|
||||
]);
|
||||
}
|
||||
|
||||
@ -26,7 +24,7 @@ class EmailType extends BaseType
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public function serialize($value)
|
||||
public static function serialize($value)
|
||||
{
|
||||
// Assuming internal representation of email is always correct:
|
||||
return $value;
|
||||
@ -42,7 +40,7 @@ class EmailType extends BaseType
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function parseValue($value)
|
||||
public static function parseValue($value)
|
||||
{
|
||||
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
|
||||
throw new \UnexpectedValueException("Cannot represent value as email: " . Utils::printSafe($value));
|
||||
@ -57,7 +55,7 @@ class EmailType extends BaseType
|
||||
* @return string
|
||||
* @throws Error
|
||||
*/
|
||||
public function parseLiteral($valueNode)
|
||||
public static function parseLiteral($valueNode)
|
||||
{
|
||||
// Note: throwing GraphQL\Error\Error vs \UnexpectedValueException to benefit from GraphQL
|
||||
// error location in query:
|
||||
|
@ -9,8 +9,6 @@ use GraphQL\Utils;
|
||||
|
||||
class UrlType extends ScalarType
|
||||
{
|
||||
// Option #2: Displays scalar type defined using inheritance. See EmailType for definition via composition
|
||||
|
||||
/**
|
||||
* Serializes an internal value to include in a response.
|
||||
*
|
||||
|
@ -6,12 +6,11 @@ use GraphQL\Examples\Blog\Data\User;
|
||||
use GraphQL\Examples\Blog\Types;
|
||||
use GraphQL\Type\Definition\UnionType;
|
||||
|
||||
class SearchResultType extends BaseType
|
||||
class SearchResultType extends UnionType
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
|
||||
$this->definition = new UnionType([
|
||||
$config = [
|
||||
'name' => 'SearchResultType',
|
||||
'types' => function() {
|
||||
return [
|
||||
@ -26,6 +25,7 @@ class SearchResultType extends BaseType
|
||||
return Types::user();
|
||||
}
|
||||
}
|
||||
]);
|
||||
];
|
||||
parent::__construct($config);
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ use GraphQL\Type\Definition\ResolveInfo;
|
||||
* Class StoryType
|
||||
* @package GraphQL\Examples\Social\Type
|
||||
*/
|
||||
class StoryType extends BaseType
|
||||
class StoryType extends ObjectType
|
||||
{
|
||||
const EDIT = 'EDIT';
|
||||
const DELETE = 'DELETE';
|
||||
@ -23,8 +23,7 @@ class StoryType extends BaseType
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
|
||||
$this->definition = new ObjectType([
|
||||
$config = [
|
||||
'name' => 'Story',
|
||||
'fields' => function() {
|
||||
return [
|
||||
@ -83,7 +82,8 @@ class StoryType extends BaseType
|
||||
return $value->{$info->fieldName};
|
||||
}
|
||||
}
|
||||
]);
|
||||
];
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
public function author(Story $story)
|
||||
|
@ -8,12 +8,11 @@ use GraphQL\Examples\Blog\Types;
|
||||
use GraphQL\Type\Definition\ObjectType;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
|
||||
class UserType extends BaseType
|
||||
class UserType extends ObjectType
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// Option #1: using composition over inheritance to define type, see ImageType for inheritance example
|
||||
$this->definition = new ObjectType([
|
||||
$config = [
|
||||
'name' => 'User',
|
||||
'description' => 'Our blog authors',
|
||||
'fields' => function() {
|
||||
@ -52,7 +51,8 @@ class UserType extends BaseType
|
||||
return $value->{$info->fieldName};
|
||||
}
|
||||
}
|
||||
]);
|
||||
];
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
public function photo(User $user, $args)
|
||||
|
@ -16,7 +16,6 @@ use GraphQL\Examples\Blog\Type\ImageType;
|
||||
use GraphQL\Type\Definition\ListOfType;
|
||||
use GraphQL\Type\Definition\NonNull;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
|
||||
/**
|
||||
* Class Types
|
||||
@ -128,7 +127,7 @@ class Types
|
||||
|
||||
public static function email()
|
||||
{
|
||||
return self::$emailType ?: (self::$emailType = new EmailType());
|
||||
return self::$emailType ?: (self::$emailType = EmailType::create());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,7 +190,7 @@ class Types
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Type|DefinitionContainer $type
|
||||
* @param Type $type
|
||||
* @return ListOfType
|
||||
*/
|
||||
public static function listOf($type)
|
||||
@ -200,7 +199,7 @@ class Types
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Type|DefinitionContainer $type
|
||||
* @param Type $type
|
||||
* @return NonNull
|
||||
*/
|
||||
public static function nonNull($type)
|
||||
|
@ -20,7 +20,6 @@ use GraphQL\Type\Definition\NonNull;
|
||||
use GraphQL\Type\Definition\ObjectType;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Type\Introspection;
|
||||
use GraphQL\Utils;
|
||||
|
||||
@ -754,11 +753,6 @@ class Executor
|
||||
$runtimeType = $exeContext->schema->getType($runtimeType);
|
||||
}
|
||||
|
||||
// FIXME: Executor should never face with DefinitionContainer - it should be unwrapped in Schema
|
||||
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,7 +9,6 @@ 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;
|
||||
|
||||
/**
|
||||
@ -114,18 +113,6 @@ 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'])
|
||||
@ -301,9 +288,6 @@ 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,7 +2,6 @@
|
||||
namespace GraphQL\Type\Definition;
|
||||
|
||||
use GraphQL\Error\InvariantViolation;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Utils;
|
||||
|
||||
/**
|
||||
@ -190,10 +189,6 @@ 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];
|
||||
@ -226,10 +221,6 @@ class Config
|
||||
return ; // Allow nulls for non-required fields
|
||||
}
|
||||
|
||||
if ($value instanceof DefinitionContainer) {
|
||||
$value = $value->getDefinition();
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
case $def & self::ANY:
|
||||
break;
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
namespace GraphQL\Type\Definition;
|
||||
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Utils;
|
||||
|
||||
/**
|
||||
@ -16,12 +15,12 @@ class ListOfType extends Type implements WrappingType, OutputType, InputType
|
||||
public $ofType;
|
||||
|
||||
/**
|
||||
* @param callable|Type|DefinitionContainer $type
|
||||
* @param callable|Type $type
|
||||
*/
|
||||
public function __construct($type)
|
||||
{
|
||||
Utils::invariant(
|
||||
$type instanceof Type || $type instanceof DefinitionContainer || is_callable($type),
|
||||
$type instanceof Type || is_callable($type),
|
||||
'Expecting instance of GraphQL\Type\Definition\Type or callable returning instance of that class'
|
||||
);
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace GraphQL\Type\Definition;
|
||||
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Type\TypeKind;
|
||||
use GraphQL\Utils;
|
||||
|
||||
/**
|
||||
@ -17,13 +15,13 @@ class NonNull extends Type implements WrappingType, OutputType, InputType
|
||||
private $ofType;
|
||||
|
||||
/**
|
||||
* @param callable|Type|DefinitionContainer $type
|
||||
* @param callable|Type $type
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __construct($type)
|
||||
{
|
||||
Utils::invariant(
|
||||
$type instanceof Type || $type instanceof DefinitionContainer || is_callable($type),
|
||||
$type instanceof Type || is_callable($type),
|
||||
'Expecting instance of GraphQL\Type\Definition\Type or callable returning instance of that class'
|
||||
);
|
||||
Utils::invariant(
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
namespace GraphQL\Type\Definition;
|
||||
use GraphQL\Error\InvariantViolation;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Utils;
|
||||
|
||||
|
||||
@ -155,7 +154,7 @@ class ObjectType extends Type implements OutputType, CompositeType
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InterfaceType|DefinitionContainer $iface
|
||||
* @param InterfaceType $iface
|
||||
* @return bool
|
||||
*/
|
||||
public function implementsInterface($iface)
|
||||
|
@ -2,7 +2,6 @@
|
||||
namespace GraphQL\Type\Definition;
|
||||
|
||||
use GraphQL\Error\InvariantViolation;
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Utils;
|
||||
|
||||
/*
|
||||
@ -198,9 +197,6 @@ abstract class Type implements \JsonSerializable
|
||||
);
|
||||
$type = $type();
|
||||
}
|
||||
if ($type instanceof DefinitionContainer) {
|
||||
$type = $type->getDefinition();
|
||||
}
|
||||
|
||||
if (!$type instanceof Type) {
|
||||
throw new InvariantViolation(sprintf(
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
namespace GraphQL\Type\Definition;
|
||||
|
||||
use GraphQL\Type\DefinitionContainer;
|
||||
use GraphQL\Utils;
|
||||
|
||||
/**
|
||||
|
@ -1,15 +0,0 @@
|
||||
<?php
|
||||
namespace GraphQL\Type;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
|
||||
/**
|
||||
* Interface DefinitionContainer
|
||||
* @package GraphQL\Type
|
||||
*/
|
||||
interface DefinitionContainer
|
||||
{
|
||||
/**
|
||||
* @return Type
|
||||
*/
|
||||
public function getDefinition();
|
||||
}
|
Loading…
Reference in New Issue
Block a user