Skip to content

Commit b17c976

Browse files
committed
Add InputUnionType
1 parent 7bdead7 commit b17c976

File tree

2 files changed

+407
-0
lines changed

2 files changed

+407
-0
lines changed
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Core\GraphQl\Type\Definition;
15+
16+
use GraphQL\Error\Error;
17+
use GraphQL\Error\InvariantViolation;
18+
use GraphQL\Type\Definition\Config;
19+
use GraphQL\Type\Definition\InputObjectType;
20+
use GraphQL\Type\Definition\InputType;
21+
use GraphQL\Type\Definition\LeafType;
22+
use GraphQL\Type\Definition\Type;
23+
use GraphQL\Utils\Utils;
24+
25+
/**
26+
* Represents an union of other input types.
27+
*
28+
* @experimental
29+
*
30+
* @author Alan Poulain <[email protected]>
31+
*/
32+
class InputUnionType extends Type implements InputType, LeafType
33+
{
34+
/**
35+
* @var InputObjectType[]
36+
*/
37+
private $types;
38+
39+
/**
40+
* @var array
41+
*/
42+
public $config;
43+
44+
/**
45+
* @throws InvariantViolation
46+
*/
47+
public function __construct(array $config)
48+
{
49+
if (!isset($config['name'])) {
50+
$config['name'] = $this->tryInferName();
51+
}
52+
53+
Utils::assertValidName($config['name']);
54+
55+
Config::validate($config, [
56+
'name' => Config::NAME | Config::REQUIRED,
57+
'types' => Config::arrayOf(Config::INPUT_TYPE, Config::MAYBE_THUNK | Config::REQUIRED),
58+
'description' => Config::STRING,
59+
]);
60+
61+
$this->name = $config['name'];
62+
$this->description = $config['description'] ?? null;
63+
$this->config = $config;
64+
}
65+
66+
67+
/**
68+
* @return InputObjectType[]
69+
*
70+
* @throws InvariantViolation
71+
*/
72+
public function getTypes(): array
73+
{
74+
if (null === $this->types) {
75+
if (!isset($this->config['types'])) {
76+
$types = null;
77+
} elseif (\is_callable($this->config['types'])) {
78+
$types = \call_user_func($this->config['types']);
79+
} else {
80+
$types = $this->config['types'];
81+
}
82+
83+
if (!\is_array($types)) {
84+
throw new InvariantViolation(
85+
"{$this->name} types must be an Array or a callable which returns an Array."
86+
);
87+
}
88+
89+
$this->types = $types;
90+
}
91+
92+
return $this->types;
93+
}
94+
95+
/**
96+
* @throws InvariantViolation
97+
*/
98+
public function assertValid()
99+
{
100+
parent::assertValid();
101+
102+
$types = $this->getTypes();
103+
Utils::invariant(
104+
!empty($types),
105+
"{$this->name} types must not be empty"
106+
);
107+
108+
$includedTypeNames = [];
109+
foreach ($types as $inputType) {
110+
Utils::invariant(
111+
$inputType instanceof InputType,
112+
"{$this->name} may only contain input types, it cannot contain: %s.",
113+
Utils::printSafe($inputType)
114+
);
115+
Utils::invariant(
116+
!isset($includedTypeNames[$inputType->name]),
117+
"{$this->name} can include {$inputType->name} type only once."
118+
);
119+
$includedTypeNames[$inputType->name] = true;
120+
}
121+
}
122+
123+
/**
124+
* {@inheritdoc}
125+
*/
126+
public function serialize($value)
127+
{
128+
foreach ($this->getTypes() as $type) {
129+
if ($type instanceof LeafType) {
130+
try {
131+
return $type->serialize($value);
132+
} catch (\Exception $e) {
133+
}
134+
}
135+
}
136+
137+
throw new InvariantViolation(sprintf('Types in union cannot represent value: %s', Utils::printSafe($value)));
138+
}
139+
140+
/**
141+
* {@inheritdoc}
142+
*/
143+
public function parseValue($value)
144+
{
145+
foreach ($this->getTypes() as $type) {
146+
if ($type instanceof LeafType) {
147+
try {
148+
return $type->parseValue($value);
149+
} catch (\Exception $e) {
150+
}
151+
}
152+
}
153+
154+
throw new Error(sprintf('Types in union cannot represent value: %s', Utils::printSafeJson($value)));
155+
}
156+
157+
/**
158+
* {@inheritdoc}
159+
*/
160+
public function parseLiteral($valueNode)
161+
{
162+
foreach ($this->getTypes() as $type) {
163+
if ($type instanceof LeafType) {
164+
if (null !== $parsed = $type->parseLiteral($valueNode)) {
165+
return $parsed;
166+
}
167+
}
168+
}
169+
170+
return null;
171+
}
172+
173+
/**
174+
* {@inheritdoc}
175+
*/
176+
public function isValidValue($value): bool
177+
{
178+
foreach ($this->getTypes() as $type) {
179+
if ($type instanceof LeafType) {
180+
if ($type->isValidValue($value)) {
181+
return true;
182+
}
183+
}
184+
}
185+
186+
return false;
187+
}
188+
189+
/**
190+
* {@inheritdoc}
191+
*/
192+
public function isValidLiteral($valueNode): bool
193+
{
194+
foreach ($this->getTypes() as $type) {
195+
if ($type instanceof LeafType) {
196+
if ($type->isValidLiteral($valueNode)) {
197+
return true;
198+
}
199+
}
200+
}
201+
202+
return false;
203+
}
204+
}

0 commit comments

Comments
 (0)