1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Digia\GraphQL\Schema; |
4
|
|
|
|
5
|
|
|
use Digia\GraphQL\Error\InvalidTypeException; |
6
|
|
|
use Digia\GraphQL\Error\InvariantException; |
7
|
|
|
use Digia\GraphQL\Execution\ExecutionException; |
8
|
|
|
use Digia\GraphQL\Execution\ValuesResolver; |
9
|
|
|
use Digia\GraphQL\Language\LanguageException; |
10
|
|
|
use Digia\GraphQL\Language\Node\DirectiveDefinitionNode; |
11
|
|
|
use Digia\GraphQL\Language\Node\EnumTypeDefinitionNode; |
12
|
|
|
use Digia\GraphQL\Language\Node\EnumValueDefinitionNode; |
13
|
|
|
use Digia\GraphQL\Language\Node\FieldDefinitionNode; |
14
|
|
|
use Digia\GraphQL\Language\Node\InputObjectTypeDefinitionNode; |
15
|
|
|
use Digia\GraphQL\Language\Node\InputValueDefinitionNode; |
16
|
|
|
use Digia\GraphQL\Language\Node\InterfaceTypeDefinitionNode; |
17
|
|
|
use Digia\GraphQL\Language\Node\ListTypeNode; |
18
|
|
|
use Digia\GraphQL\Language\Node\NamedTypeNode; |
19
|
|
|
use Digia\GraphQL\Language\Node\NamedTypeNodeInterface; |
20
|
|
|
use Digia\GraphQL\Language\Node\NameNode; |
21
|
|
|
use Digia\GraphQL\Language\Node\NodeInterface; |
22
|
|
|
use Digia\GraphQL\Language\Node\NonNullTypeNode; |
23
|
|
|
use Digia\GraphQL\Language\Node\ObjectTypeDefinitionNode; |
24
|
|
|
use Digia\GraphQL\Language\Node\ScalarTypeDefinitionNode; |
25
|
|
|
use Digia\GraphQL\Language\Node\TypeNodeInterface; |
26
|
|
|
use Digia\GraphQL\Language\Node\UnionTypeDefinitionNode; |
27
|
|
|
use Digia\GraphQL\Schema\Resolver\ResolverRegistryInterface; |
28
|
|
|
use Digia\GraphQL\Type\Definition\Directive; |
29
|
|
|
use Digia\GraphQL\Type\Definition\EnumType; |
30
|
|
|
use Digia\GraphQL\Type\Definition\InputObjectType; |
31
|
|
|
use Digia\GraphQL\Type\Definition\InterfaceType; |
32
|
|
|
use Digia\GraphQL\Type\Definition\NamedTypeInterface; |
33
|
|
|
use Digia\GraphQL\Type\Definition\ObjectType; |
34
|
|
|
use Digia\GraphQL\Type\Definition\ScalarType; |
35
|
|
|
use Digia\GraphQL\Type\Definition\TypeInterface; |
36
|
|
|
use Digia\GraphQL\Type\Definition\UnionType; |
37
|
|
|
use Digia\GraphQL\Util\ValueASTConverter; |
38
|
|
|
use function Digia\GraphQL\Type\introspectionTypes; |
39
|
|
|
use function Digia\GraphQL\Type\newDirective; |
40
|
|
|
use function Digia\GraphQL\Type\newEnumType; |
41
|
|
|
use function Digia\GraphQL\Type\newInputObjectType; |
42
|
|
|
use function Digia\GraphQL\Type\newInterfaceType; |
43
|
|
|
use function Digia\GraphQL\Type\newList; |
44
|
|
|
use function Digia\GraphQL\Type\newNonNull; |
45
|
|
|
use function Digia\GraphQL\Type\newObjectType; |
46
|
|
|
use function Digia\GraphQL\Type\newScalarType; |
47
|
|
|
use function Digia\GraphQL\Type\newUnionType; |
48
|
|
|
use function Digia\GraphQL\Type\specifiedScalarTypes; |
49
|
|
|
use function Digia\GraphQL\Util\keyMap; |
50
|
|
|
use function Digia\GraphQL\Util\keyValueMap; |
51
|
|
|
|
52
|
|
|
class DefinitionBuilder implements DefinitionBuilderInterface |
53
|
|
|
{ |
54
|
|
|
/** |
55
|
|
|
* @var NamedTypeNodeInterface[] |
56
|
|
|
*/ |
57
|
|
|
protected $typeDefinitionsMap; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @var ResolverRegistryInterface |
61
|
|
|
*/ |
62
|
|
|
protected $resolverRegistry; |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* @var callable |
66
|
|
|
*/ |
67
|
|
|
protected $resolveTypeFunction; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @var NamedTypeInterface[] |
71
|
|
|
*/ |
72
|
|
|
protected $types; |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* @var Directive[] |
76
|
|
|
*/ |
77
|
|
|
protected $directives; |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* DefinitionBuilder constructor. |
81
|
|
|
* @param array $typeDefinitionsMap |
82
|
|
|
* @param ResolverRegistryInterface|null $resolverRegistry |
83
|
|
|
* @param array $types |
84
|
|
|
* @param array $directives |
85
|
|
|
* @param callable|null $resolveTypeCallback |
86
|
|
|
*/ |
87
|
|
|
public function __construct( |
88
|
|
|
array $typeDefinitionsMap, |
89
|
|
|
?ResolverRegistryInterface $resolverRegistry = null, |
90
|
|
|
array $types = [], |
91
|
|
|
array $directives = [], |
92
|
|
|
?callable $resolveTypeCallback = null |
93
|
|
|
) { |
94
|
|
|
$this->typeDefinitionsMap = $typeDefinitionsMap; |
95
|
|
|
$this->resolverRegistry = $resolverRegistry; |
96
|
|
|
$this->resolveTypeFunction = $resolveTypeCallback ?? [$this, 'defaultTypeResolver']; |
97
|
|
|
|
98
|
|
|
$this->registerTypes($types); |
99
|
|
|
$this->registerDirectives($directives); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* @inheritdoc |
104
|
|
|
*/ |
105
|
|
|
public function buildTypes(array $nodes): array |
106
|
|
|
{ |
107
|
|
|
return \array_map(function (NamedTypeNodeInterface $node) { |
108
|
|
|
return $this->buildType($node); |
109
|
|
|
}, $nodes); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* @inheritdoc |
114
|
|
|
*/ |
115
|
|
|
public function buildType(NamedTypeNodeInterface $node): NamedTypeInterface |
116
|
|
|
{ |
117
|
|
|
$typeName = $node->getNameValue(); |
118
|
|
|
|
119
|
|
|
if (isset($this->types[$typeName])) { |
120
|
|
|
return $this->types[$typeName]; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
if ($node instanceof NamedTypeNode) { |
124
|
|
|
$definition = $this->getTypeDefinition($typeName); |
|
|
|
|
125
|
|
|
|
126
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */ |
127
|
|
|
$type = null !== $definition |
128
|
|
|
? $this->buildNamedType($definition) |
129
|
|
|
: $this->resolveType($node); |
130
|
|
|
} else { |
131
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */ |
132
|
|
|
$type = $this->buildNamedType($node); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
return $this->types[$typeName] = $type; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* @inheritdoc |
140
|
|
|
*/ |
141
|
|
|
public function buildDirective(DirectiveDefinitionNode $node): Directive |
142
|
|
|
{ |
143
|
|
|
$directiveName = $node->getNameValue(); |
144
|
|
|
|
145
|
|
|
if (isset($this->directives[$directiveName])) { |
146
|
|
|
return $this->directives[$directiveName]; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */ |
150
|
|
|
$directive = newDirective([ |
151
|
|
|
'name' => $node->getNameValue(), |
152
|
|
|
'description' => $node->getDescriptionValue(), |
153
|
|
|
'locations' => \array_map(function (NameNode $node) { |
154
|
|
|
return $node->getValue(); |
155
|
|
|
}, $node->getLocations()), |
156
|
|
|
'args' => $node->hasArguments() ? $this->buildArguments($node->getArguments()) : [], |
157
|
|
|
'astNode' => $node, |
158
|
|
|
]); |
159
|
|
|
|
160
|
|
|
return $this->directives[$directiveName] = $directive; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* @inheritdoc |
165
|
|
|
*/ |
166
|
|
|
public function buildField($node, ?callable $resolve = null): array |
167
|
|
|
{ |
168
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */ |
169
|
|
|
return [ |
170
|
|
|
'type' => $this->buildWrappedType($node->getType()), |
171
|
|
|
'description' => $node->getDescriptionValue(), |
172
|
|
|
'args' => $node->hasArguments() ? $this->buildArguments($node->getArguments()) : [], |
173
|
|
|
'deprecationReason' => $this->getDeprecationReason($node), |
174
|
|
|
'resolve' => $resolve, |
175
|
|
|
'astNode' => $node, |
176
|
|
|
]; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* @param TypeNodeInterface $typeNode |
181
|
|
|
* @return TypeInterface |
182
|
|
|
* @throws InvariantException |
183
|
|
|
* @throws InvalidTypeException |
184
|
|
|
*/ |
185
|
|
|
protected function buildWrappedType(TypeNodeInterface $typeNode): TypeInterface |
186
|
|
|
{ |
187
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */ |
188
|
|
|
$typeDefinition = $this->buildType($this->getNamedTypeNode($typeNode)); |
189
|
|
|
return $this->buildWrappedTypeRecursive($typeDefinition, $typeNode); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* @param NamedTypeInterface $innerType |
194
|
|
|
* @param TypeNodeInterface $inputTypeNode |
195
|
|
|
* @return TypeInterface |
196
|
|
|
* @throws InvariantException |
197
|
|
|
* @throws InvalidTypeException |
198
|
|
|
*/ |
199
|
|
|
protected function buildWrappedTypeRecursive( |
200
|
|
|
NamedTypeInterface $innerType, |
201
|
|
|
TypeNodeInterface $inputTypeNode |
202
|
|
|
): TypeInterface { |
203
|
|
|
if ($inputTypeNode instanceof ListTypeNode) { |
204
|
|
|
return newList($this->buildWrappedTypeRecursive($innerType, $inputTypeNode->getType())); |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
if ($inputTypeNode instanceof NonNullTypeNode) { |
208
|
|
|
return newNonNull($this->buildWrappedTypeRecursive($innerType, $inputTypeNode->getType())); |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
return $innerType; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* @param array $customTypes |
216
|
|
|
*/ |
217
|
|
|
protected function registerTypes(array $customTypes) |
218
|
|
|
{ |
219
|
|
|
$typesMap = keyMap( |
220
|
|
|
\array_merge($customTypes, specifiedScalarTypes(), introspectionTypes()), |
221
|
|
|
function (NamedTypeInterface $type) { |
222
|
|
|
return $type->getName(); |
223
|
|
|
} |
224
|
|
|
); |
225
|
|
|
|
226
|
|
|
foreach ($typesMap as $typeName => $type) { |
227
|
|
|
$this->types[$typeName] = $type; |
228
|
|
|
} |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* @param array $customDirectives |
233
|
|
|
*/ |
234
|
|
|
protected function registerDirectives(array $customDirectives) |
235
|
|
|
{ |
236
|
|
|
$directivesMap = keyMap( |
237
|
|
|
\array_merge($customDirectives, specifiedDirectives()), |
238
|
|
|
function (Directive $directive) { |
239
|
|
|
return $directive->getName(); |
240
|
|
|
} |
241
|
|
|
); |
242
|
|
|
|
243
|
|
|
foreach ($directivesMap as $directiveName => $directive) { |
244
|
|
|
$this->directives[$directiveName] = $directive; |
245
|
|
|
} |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* @param array $nodes |
250
|
|
|
* @return array |
251
|
|
|
*/ |
252
|
|
|
protected function buildArguments(array $nodes): array |
253
|
|
|
{ |
254
|
|
|
return keyValueMap( |
255
|
|
|
$nodes, |
256
|
|
|
function (InputValueDefinitionNode $value) { |
257
|
|
|
return $value->getNameValue(); |
258
|
|
|
}, |
259
|
|
|
function (InputValueDefinitionNode $value): array { |
260
|
|
|
$type = $this->buildWrappedType($value->getType()); |
261
|
|
|
$defaultValue = $value->getDefaultValue(); |
262
|
|
|
return [ |
263
|
|
|
'type' => $type, |
264
|
|
|
'description' => $value->getDescriptionValue(), |
265
|
|
|
'defaultValue' => null !== $defaultValue |
266
|
|
|
? ValueASTConverter::convert($defaultValue, $type) |
267
|
|
|
: null, |
268
|
|
|
'astNode' => $value, |
269
|
|
|
]; |
270
|
|
|
}); |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* @param TypeNodeInterface $node |
275
|
|
|
* @return NamedTypeInterface |
276
|
|
|
* @throws LanguageException |
277
|
|
|
*/ |
278
|
|
|
protected function buildNamedType(TypeNodeInterface $node): NamedTypeInterface |
279
|
|
|
{ |
280
|
|
|
if ($node instanceof ObjectTypeDefinitionNode) { |
281
|
|
|
return $this->buildObjectType($node); |
282
|
|
|
} |
283
|
|
|
if ($node instanceof InterfaceTypeDefinitionNode) { |
284
|
|
|
return $this->buildInterfaceType($node); |
285
|
|
|
} |
286
|
|
|
if ($node instanceof EnumTypeDefinitionNode) { |
287
|
|
|
return $this->buildEnumType($node); |
288
|
|
|
} |
289
|
|
|
if ($node instanceof UnionTypeDefinitionNode) { |
290
|
|
|
return $this->buildUnionType($node); |
291
|
|
|
} |
292
|
|
|
if ($node instanceof ScalarTypeDefinitionNode) { |
293
|
|
|
return $this->buildScalarType($node); |
294
|
|
|
} |
295
|
|
|
if ($node instanceof InputObjectTypeDefinitionNode) { |
296
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */ |
297
|
|
|
return $this->buildInputObjectType($node); |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
throw new LanguageException(\sprintf('Type kind "%s" not supported.', $node->getKind())); |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* @param ObjectTypeDefinitionNode $node |
305
|
|
|
* @return ObjectType |
306
|
|
|
*/ |
307
|
|
|
protected function buildObjectType(ObjectTypeDefinitionNode $node): ObjectType |
308
|
|
|
{ |
309
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */ |
310
|
|
|
return newObjectType([ |
311
|
|
|
'name' => $node->getNameValue(), |
312
|
|
|
'description' => $node->getDescriptionValue(), |
313
|
|
|
'fields' => $node->hasFields() ? function () use ($node) { |
314
|
|
|
return $this->buildFields($node); |
315
|
|
|
} : [], |
316
|
|
|
// Note: While this could make early assertions to get the correctly |
317
|
|
|
// typed values, that would throw immediately while type system |
318
|
|
|
// validation with validateSchema() will produce more actionable results. |
319
|
|
|
'interfaces' => function () use ($node) { |
320
|
|
|
return $node->hasInterfaces() ? \array_map(function (NamedTypeNodeInterface $interface) { |
321
|
|
|
return $this->buildType($interface); |
322
|
|
|
}, $node->getInterfaces()) : []; |
323
|
|
|
}, |
324
|
|
|
'astNode' => $node, |
325
|
|
|
]); |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
/** |
329
|
|
|
* @param ObjectTypeDefinitionNode|InterfaceTypeDefinitionNode|InputObjectTypeDefinitionNode $node |
330
|
|
|
* @return array |
331
|
|
|
*/ |
332
|
|
|
protected function buildFields($node): array |
333
|
|
|
{ |
334
|
|
|
return keyValueMap( |
335
|
|
|
$node->getFields(), |
336
|
|
|
function ($value) { |
337
|
|
|
/** @var FieldDefinitionNode|InputValueDefinitionNode $value */ |
338
|
|
|
return $value->getNameValue(); |
339
|
|
|
}, |
340
|
|
|
function ($value) use ($node) { |
341
|
|
|
/** @var FieldDefinitionNode|InputValueDefinitionNode $value */ |
342
|
|
|
return $this->buildField($value, |
343
|
|
|
$this->getFieldResolver($node->getNameValue(), $value->getNameValue())); |
|
|
|
|
344
|
|
|
} |
345
|
|
|
); |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
/** |
349
|
|
|
* @param string $typeName |
350
|
|
|
* @param string $fieldName |
351
|
|
|
* @return callable|null |
352
|
|
|
*/ |
353
|
|
|
protected function getFieldResolver(string $typeName, string $fieldName): ?callable |
354
|
|
|
{ |
355
|
|
|
return null !== $this->resolverRegistry |
356
|
|
|
? $this->resolverRegistry->getFieldResolver($typeName, $fieldName) |
357
|
|
|
: null; |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* @param InterfaceTypeDefinitionNode $node |
362
|
|
|
* @return InterfaceType |
363
|
|
|
*/ |
364
|
|
|
protected function buildInterfaceType(InterfaceTypeDefinitionNode $node): InterfaceType |
365
|
|
|
{ |
366
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */ |
367
|
|
|
return newInterfaceType([ |
368
|
|
|
'name' => $node->getNameValue(), |
369
|
|
|
'description' => $node->getDescriptionValue(), |
370
|
|
|
'fields' => $node->hasFields() ? function () use ($node): array { |
371
|
|
|
return $this->buildFields($node); |
372
|
|
|
} : [], |
373
|
|
|
'resolveType' => $this->getTypeResolver($node->getNameValue()), |
|
|
|
|
374
|
|
|
'astNode' => $node, |
375
|
|
|
]); |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
/** |
379
|
|
|
* @param EnumTypeDefinitionNode $node |
380
|
|
|
* @return EnumType |
381
|
|
|
*/ |
382
|
|
|
protected function buildEnumType(EnumTypeDefinitionNode $node): EnumType |
383
|
|
|
{ |
384
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */ |
385
|
|
|
return newEnumType([ |
386
|
|
|
'name' => $node->getNameValue(), |
387
|
|
|
'description' => $node->getDescriptionValue(), |
388
|
|
|
'values' => $node->hasValues() ? keyValueMap( |
389
|
|
|
$node->getValues(), |
390
|
|
|
function (EnumValueDefinitionNode $value): ?string { |
391
|
|
|
return $value->getNameValue(); |
392
|
|
|
}, |
393
|
|
|
function (EnumValueDefinitionNode $value): array { |
394
|
|
|
return [ |
395
|
|
|
'description' => $value->getDescriptionValue(), |
396
|
|
|
'deprecationReason' => $this->getDeprecationReason($value), |
397
|
|
|
'astNode' => $value, |
398
|
|
|
]; |
399
|
|
|
} |
400
|
|
|
) : [], |
401
|
|
|
'astNode' => $node, |
402
|
|
|
]); |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
/** |
406
|
|
|
* @param UnionTypeDefinitionNode $node |
407
|
|
|
* @return UnionType |
408
|
|
|
*/ |
409
|
|
|
protected function buildUnionType(UnionTypeDefinitionNode $node): UnionType |
410
|
|
|
{ |
411
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */ |
412
|
|
|
return newUnionType([ |
413
|
|
|
'name' => $node->getNameValue(), |
414
|
|
|
'description' => $node->getDescriptionValue(), |
415
|
|
|
'types' => $node->hasTypes() ? \array_map(function (NamedTypeNodeInterface $type) { |
416
|
|
|
return $this->buildType($type); |
417
|
|
|
}, $node->getTypes()) : [], |
418
|
|
|
'resolveType' => $this->getTypeResolver($node->getNameValue()), |
|
|
|
|
419
|
|
|
'astNode' => $node, |
420
|
|
|
]); |
421
|
|
|
} |
422
|
|
|
|
423
|
|
|
/** |
424
|
|
|
* @param string $typeName |
425
|
|
|
* @return callable|null |
426
|
|
|
*/ |
427
|
|
|
protected function getTypeResolver(string $typeName): ?callable |
428
|
|
|
{ |
429
|
|
|
return null !== $this->resolverRegistry |
430
|
|
|
? $this->resolverRegistry->getTypeResolver($typeName) |
431
|
|
|
: null; |
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
/** |
435
|
|
|
* @param ScalarTypeDefinitionNode $node |
436
|
|
|
* @return ScalarType |
437
|
|
|
*/ |
438
|
|
|
protected function buildScalarType(ScalarTypeDefinitionNode $node): ScalarType |
439
|
|
|
{ |
440
|
|
|
/** @noinspection PhpUnhandledExceptionInspection */ |
441
|
|
|
return newScalarType([ |
442
|
|
|
'name' => $node->getNameValue(), |
443
|
|
|
'description' => $node->getDescriptionValue(), |
444
|
|
|
'serialize' => function ($value) { |
445
|
|
|
return $value; |
446
|
|
|
}, |
447
|
|
|
'astNode' => $node, |
448
|
|
|
]); |
449
|
|
|
} |
450
|
|
|
|
451
|
|
|
/** |
452
|
|
|
* @param InputObjectTypeDefinitionNode $node |
453
|
|
|
* @return InputObjectType |
454
|
|
|
* @throws InvariantException |
455
|
|
|
*/ |
456
|
|
|
protected function buildInputObjectType(InputObjectTypeDefinitionNode $node): InputObjectType |
457
|
|
|
{ |
458
|
|
|
return newInputObjectType([ |
459
|
|
|
'name' => $node->getNameValue(), |
460
|
|
|
'description' => $node->getDescriptionValue(), |
461
|
|
|
'fields' => $node->hasFields() ? function () use ($node) { |
462
|
|
|
return keyValueMap( |
463
|
|
|
$node->getFields(), |
464
|
|
|
function (InputValueDefinitionNode $value): ?string { |
465
|
|
|
return $value->getNameValue(); |
466
|
|
|
}, |
467
|
|
|
function (InputValueDefinitionNode $value): array { |
468
|
|
|
$type = $this->buildWrappedType($value->getType()); |
469
|
|
|
$defaultValue = $value->getDefaultValue(); |
470
|
|
|
return [ |
471
|
|
|
'type' => $type, |
472
|
|
|
'description' => $value->getDescriptionValue(), |
473
|
|
|
'defaultValue' => null !== $defaultValue |
474
|
|
|
? ValueASTConverter::convert($defaultValue, $type) |
475
|
|
|
: null, |
476
|
|
|
'astNode' => $value, |
477
|
|
|
]; |
478
|
|
|
} |
479
|
|
|
); |
480
|
|
|
} : [], |
481
|
|
|
'astNode' => $node, |
482
|
|
|
]); |
483
|
|
|
} |
484
|
|
|
|
485
|
|
|
/** |
486
|
|
|
* @param NamedTypeNode $node |
487
|
|
|
* @return NamedTypeInterface |
488
|
|
|
*/ |
489
|
|
|
protected function resolveType(NamedTypeNode $node): NamedTypeInterface |
490
|
|
|
{ |
491
|
|
|
return \call_user_func($this->resolveTypeFunction, $node); |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
/** |
495
|
|
|
* @param NamedTypeNode $node |
496
|
|
|
* @return NamedTypeInterface|null |
497
|
|
|
*/ |
498
|
|
|
public function defaultTypeResolver(NamedTypeNode $node): ?NamedTypeInterface |
499
|
|
|
{ |
500
|
|
|
return $this->types[$node->getNameValue()] ?? null; |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
/** |
504
|
|
|
* @param string $typeName |
505
|
|
|
* @return NamedTypeNodeInterface|null |
506
|
|
|
*/ |
507
|
|
|
protected function getTypeDefinition(string $typeName): ?NamedTypeNodeInterface |
508
|
|
|
{ |
509
|
|
|
return $this->typeDefinitionsMap[$typeName] ?? null; |
510
|
|
|
} |
511
|
|
|
|
512
|
|
|
/** |
513
|
|
|
* @param TypeNodeInterface $typeNode |
514
|
|
|
* @return NamedTypeNodeInterface |
515
|
|
|
*/ |
516
|
|
|
protected function getNamedTypeNode(TypeNodeInterface $typeNode): NamedTypeNodeInterface |
517
|
|
|
{ |
518
|
|
|
$namedType = $typeNode; |
519
|
|
|
|
520
|
|
|
while ($namedType instanceof ListTypeNode || $namedType instanceof NonNullTypeNode) { |
521
|
|
|
$namedType = $namedType->getType(); |
522
|
|
|
} |
523
|
|
|
|
524
|
|
|
/** @var NamedTypeNodeInterface $namedType */ |
525
|
|
|
return $namedType; |
526
|
|
|
} |
527
|
|
|
|
528
|
|
|
/** |
529
|
|
|
* @param NodeInterface|EnumValueDefinitionNode|FieldDefinitionNode $node |
530
|
|
|
* @return null|string |
531
|
|
|
* @throws InvariantException |
532
|
|
|
* @throws ExecutionException |
533
|
|
|
*/ |
534
|
|
|
protected function getDeprecationReason(NodeInterface $node): ?string |
535
|
|
|
{ |
536
|
|
|
if (isset($this->directives['deprecated'])) { |
537
|
|
|
$deprecated = ValuesResolver::coerceDirectiveValues($this->directives['deprecated'], $node); |
538
|
|
|
|
539
|
|
|
return $deprecated['reason'] ?? null; |
540
|
|
|
} |
541
|
|
|
|
542
|
|
|
return null; |
543
|
|
|
} |
544
|
|
|
} |
545
|
|
|
|