-
-
Notifications
You must be signed in to change notification settings - Fork 564
/
Copy pathUnionType.php
140 lines (116 loc) · 3.9 KB
/
UnionType.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<?php declare(strict_types=1);
namespace GraphQL\Type\Definition;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\UnionTypeDefinitionNode;
use GraphQL\Language\AST\UnionTypeExtensionNode;
use GraphQL\Type\Schema;
use GraphQL\Utils\Utils;
/**
* @phpstan-import-type ResolveType from AbstractType
*
* @phpstan-type ObjectTypeReference ObjectType|callable(): ObjectType
* @phpstan-type UnionConfig array{
* name?: string|null,
* description?: string|null,
* types: iterable<ObjectTypeReference>|callable(): iterable<ObjectTypeReference>,
* resolveType?: ResolveType|null,
* astNode?: UnionTypeDefinitionNode|null,
* extensionASTNodes?: array<UnionTypeExtensionNode>|null
* }
*/
class UnionType extends Type implements AbstractType, OutputType, CompositeType, NullableType, NamedType
{
use NamedTypeImplementation;
public ?UnionTypeDefinitionNode $astNode;
/** @var array<UnionTypeExtensionNode> */
public array $extensionASTNodes;
/** @phpstan-var UnionConfig */
public array $config;
/**
* Lazily initialized.
*
* @var array<int, ObjectType>
*/
private array $types;
/**
* Lazily initialized.
*
* @var array<string, bool>
*/
private array $possibleTypeNames;
/**
* @throws InvariantViolation
*
* @phpstan-param UnionConfig $config
*/
public function __construct(array $config)
{
$this->name = $config['name'] ?? $this->inferName();
$this->description = $config['description'] ?? $this->description ?? null;
$this->astNode = $config['astNode'] ?? null;
$this->extensionASTNodes = $config['extensionASTNodes'] ?? [];
$this->config = $config;
}
/** @throws InvariantViolation */
public function isPossibleType(Type $type): bool
{
if (! $type instanceof ObjectType) {
return false;
}
if (! isset($this->possibleTypeNames)) {
$this->possibleTypeNames = [];
foreach ($this->getTypes() as $possibleType) {
$this->possibleTypeNames[$possibleType->name] = true;
}
}
return isset($this->possibleTypeNames[$type->name]);
}
/**
* @throws InvariantViolation
*
* @return array<int, ObjectType>
*/
public function getTypes(): array
{
if (! isset($this->types)) {
$this->types = [];
$types = $this->config['types'] ?? null;
if (is_callable($types)) {
$types = $types();
}
if (! is_iterable($types)) {
throw new InvariantViolation("Must provide iterable of types or a callable which returns such an iterable for Union {$this->name}.");
}
foreach ($types as $type) {
$this->types[] = Schema::resolveType($type);
}
}
return $this->types;
}
public function resolveType($objectValue, $context, ResolveInfo $info)
{
if (isset($this->config['resolveType'])) {
return ($this->config['resolveType'])($objectValue, $context, $info);
}
return null;
}
public function assertValid(): void
{
Utils::assertValidName($this->name);
$resolveType = $this->config['resolveType'] ?? null;
// @phpstan-ignore-next-line not necessary according to types, but can happen during runtime
if (isset($resolveType) && ! is_callable($resolveType)) {
$notCallable = Utils::printSafe($resolveType);
throw new InvariantViolation("{$this->name} must provide \"resolveType\" as null or a callable, but got: {$notCallable}.");
}
}
public function astNode(): ?UnionTypeDefinitionNode
{
return $this->astNode;
}
/** @return array<UnionTypeExtensionNode> */
public function extensionASTNodes(): array
{
return $this->extensionASTNodes;
}
}