Completed
Pull Request — master (#349)
by Christoffer
03:02
created

ValuesResolver   F

Complexity

Total Complexity 82

Size/Duplication

Total Lines 572
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 249
dl 0
loc 572
rs 2
c 3
b 0
f 0
wmc 82

12 Methods

Rating   Name   Duplication   Size   Complexity  
A printPath() 0 14 4
A coerceDirectiveValues() 0 15 3
A isInputType() 0 6 5
A coerceValueForEnumType() 0 20 4
A coerceValueForNonNullType() 0 16 2
A coerceValueForListType() 0 29 5
A buildCoerceException() 0 19 3
C coerceVariableValues() 0 86 15
A coerceValueForScalarType() 0 22 3
B coerceValueForInputObjectType() 0 61 10
D coerceArgumentValues() 0 114 21
B coerceValue() 0 27 7

How to fix   Complexity   

Complex Class

Complex classes like ValuesResolver often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ValuesResolver, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Digia\GraphQL\Execution;
4
5
use Digia\GraphQL\Error\GraphQLException;
6
use Digia\GraphQL\Error\InvalidTypeException;
7
use Digia\GraphQL\Error\InvariantException;
8
use Digia\GraphQL\Language\Node\ArgumentNode;
9
use Digia\GraphQL\Language\Node\ArgumentsAwareInterface;
10
use Digia\GraphQL\Language\Node\NameAwareInterface;
11
use Digia\GraphQL\Language\Node\NodeInterface;
12
use Digia\GraphQL\Language\Node\NullValueNode;
13
use Digia\GraphQL\Language\Node\VariableDefinitionNode;
14
use Digia\GraphQL\Language\Node\VariableNode;
15
use Digia\GraphQL\Schema\Schema;
16
use Digia\GraphQL\Type\Coercer\CoercingException;
17
use Digia\GraphQL\Type\Definition\Directive;
18
use Digia\GraphQL\Type\Definition\EnumType;
19
use Digia\GraphQL\Type\Definition\EnumValue;
20
use Digia\GraphQL\Type\Definition\Field;
21
use Digia\GraphQL\Type\Definition\InputObjectType;
22
use Digia\GraphQL\Type\Definition\ListType;
23
use Digia\GraphQL\Type\Definition\NonNullType;
24
use Digia\GraphQL\Type\Definition\ScalarType;
25
use Digia\GraphQL\Type\Definition\TypeInterface;
26
use Digia\GraphQL\Type\Definition\WrappingTypeInterface;
27
use Digia\GraphQL\Util\ConversionException;
28
use Digia\GraphQL\Util\TypeASTConverter;
29
use Digia\GraphQL\Util\ValueASTConverter;
30
use Exception;
31
use Traversable;
32
use function array_key_exists;
33
use function array_keys;
34
use function array_map;
35
use function array_merge;
36
use function Digia\GraphQL\Test\jsonEncode;
37
use function Digia\GraphQL\Util\find;
38
use function Digia\GraphQL\Util\invariant;
39
use function Digia\GraphQL\Util\keyMap;
40
use function Digia\GraphQL\Util\suggestionList;
41
use function implode;
42
use function is_array;
43
use function is_string;
44
use function sprintf;
45
46
class ValuesResolver
47
{
48
    /**
49
     * Prepares an object map of argument values given a list of argument
50
     * definitions and list of argument AST nodes.
51
     *
52
     * @see https://facebook.github.io/graphql/October2016/#CoerceArgumentValues()
53
     *
54
     * @param Field|Directive         $definition
55
     * @param ArgumentsAwareInterface $node
56
     * @param array                   $variableValues
57
     * @return array
58
     * @throws ExecutionException
59
     * @throws InvariantException
60
     */
61
    public static function coerceArgumentValues(
62
        $definition,
63
        ArgumentsAwareInterface $node,
64
        array $variableValues = []
65
    ): array {
66
        $coercedValues       = [];
67
        $argumentDefinitions = $definition->getArguments();
68
        $argumentNodes       = $node->getArguments();
69
70
        if (empty($argumentDefinitions)) {
71
            return $coercedValues;
72
        }
73
74
        /** @var ArgumentNode[] $argumentNodeMap */
75
        $argumentNodeMap = keyMap($argumentNodes, function (ArgumentNode $value) {
76
            return $value->getNameValue();
77
        });
78
79
        foreach ($argumentDefinitions as $argumentDefinition) {
80
            $argumentName  = $argumentDefinition->getName();
81
            $argumentType  = $argumentDefinition->getType();
82
            $argumentNode  = $argumentNodeMap[$argumentName] ?? null;
83
            $defaultValue  = $argumentDefinition->getDefaultValue();
84
            $argumentValue = null !== $argumentNode ? $argumentNode->getValue() : null;
85
86
            if (null !== $argumentNode && $argumentValue instanceof VariableNode) {
87
                $variableName = $argumentValue->getNameValue();
88
                $hasValue     = !empty($variableValues) && array_key_exists($variableName, $variableValues);
89
                $isNull       = $hasValue && null === $variableValues[$variableName];
90
            } else {
91
                $hasValue = null !== $argumentNode;
92
                $isNull   = $hasValue && $argumentValue instanceof NullValueNode;
93
            }
94
95
            if (!$hasValue && null !== $defaultValue) {
96
                // If no argument was provided where the definition has a default value,
97
                // use the default value.
98
                $coercedValues[$argumentName] = $defaultValue;
99
            } elseif ((!$hasValue || $isNull) && $argumentType instanceof NonNullType) {
100
                // If no argument or a null value was provided to an argument with a
101
                // non-null type (required), produce a field error.
102
                if ($isNull) {
103
                    throw new ExecutionException(
104
                        sprintf(
105
                            'Argument "%s" of non-null type "%s" must not be null.',
106
                            $argumentName,
107
                            $argumentType
108
                        ),
109
                        [$argumentValue]
110
                    );
111
                } elseif (null !== $argumentNode && $argumentValue instanceof VariableNode) {
112
                    $variableName = $argumentValue->getNameValue();
113
                    throw new ExecutionException(
114
                        sprintf(
115
                            'Argument "%s" of required type "%s" was provided the variable "$%s" '
116
                            . 'which was not provided a runtime value.',
117
                            $argumentName,
118
                            $argumentType,
119
                            $variableName
120
                        ),
121
                        [$argumentValue]
122
                    );
123
                } else {
124
                    throw new ExecutionException(
125
                        sprintf(
126
                            'Argument "%s" of required type "%s" was not provided.',
127
                            $argumentName,
128
                            $argumentType
129
                        ),
130
                        [$node]
131
                    );
132
                }
133
            } elseif ($hasValue) {
134
                if ($argumentValue instanceof NullValueNode) {
135
                    // If the explicit value `null` was provided, an entry in the coerced
136
                    // values must exist as the value `null`.
137
                    $coercedValues[$argumentName] = null;
138
                } elseif ($argumentValue instanceof VariableNode) {
139
                    $variableName = $argumentValue->getNameValue();
140
                    invariant(!empty($variableValues), 'Must exist for hasValue to be true.');
141
                    // Note: This does no further checking that this variable is correct.
142
                    // This assumes that this query has been validated and the variable
143
                    // usage here is of the correct type.
144
                    $coercedValues[$argumentName] = $variableValues[$variableName];
145
                } else {
146
                    $valueNode = $argumentNode->getValue();
0 ignored issues
show
Bug introduced by
The method getValue() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

146
                    /** @scrutinizer ignore-call */ 
147
                    $valueNode = $argumentNode->getValue();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
147
                    try {
148
                        // Value nodes that cannot be resolved should be treated as invalid values
149
                        // because there is no undefined value in PHP so that we throw an exception
150
                        $coercedValue = ValueASTConverter::convert($valueNode, $argumentType, $variableValues);
0 ignored issues
show
Bug introduced by
It seems like $argumentType can also be of type null; however, parameter $type of Digia\GraphQL\Util\ValueASTConverter::convert() does only seem to accept Digia\GraphQL\Type\Definition\TypeInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

150
                        $coercedValue = ValueASTConverter::convert($valueNode, /** @scrutinizer ignore-type */ $argumentType, $variableValues);
Loading history...
151
                    } catch (Exception $ex) {
152
                        // Note: ValuesOfCorrectType validation should catch this before
153
                        // execution. This is a runtime check to ensure execution does not
154
                        // continue with an invalid argument value.
155
                        throw new ExecutionException(
156
                            sprintf(
157
                                'Argument "%s" has invalid value %s.',
158
                                $argumentName,
159
                                (string)$argumentValue
160
                            ),
161
                            [$argumentValue],
162
                            null,
163
                            null,
164
                            null,
165
                            null,
166
                            $ex
167
                        );
168
                    }
169
                    $coercedValues[$argumentName] = $coercedValue;
170
                }
171
            }
172
        }
173
174
        return $coercedValues;
175
    }
176
177
    /**
178
     * Prepares an object map of argument values given a directive definition
179
     * and a AST node which may contain directives. Optionally also accepts a map
180
     * of variable values.
181
     *
182
     * If the directive does not exist on the node, returns null.
183
     *
184
     * @param Directive $directive
185
     * @param mixed     $node
186
     * @param array     $variableValues
187
     * @return array|null
188
     * @throws ExecutionException
189
     * @throws InvariantException
190
     */
191
    public static function coerceDirectiveValues(
192
        Directive $directive,
193
        $node,
194
        array $variableValues = []
195
    ): ?array {
196
        $directiveNode = $node->hasDirectives()
197
            ? find($node->getDirectives(), function (NameAwareInterface $value) use ($directive) {
198
                return $value->getNameValue() === $directive->getName();
199
            }) : null;
200
201
        if (null !== $directiveNode) {
202
            return static::coerceArgumentValues($directive, $directiveNode, $variableValues);
203
        }
204
205
        return null;
206
    }
207
208
    /**
209
     * Prepares an object map of variableValues of the correct type based on the
210
     * provided variable definitions and arbitrary input. If the input cannot be
211
     * parsed to match the variable definitions, a GraphQLError will be thrown.
212
     *
213
     * @param Schema                         $schema
214
     * @param array|VariableDefinitionNode[] $variableDefinitionNodes
215
     * @param array                          $inputs
216
     * @return CoercedValue
217
     * @throws GraphQLException
218
     * @throws InvariantException
219
     * @throws ConversionException
220
     */
221
    public static function coerceVariableValues(
222
        Schema $schema,
223
        array $variableDefinitionNodes,
224
        array $inputs
225
    ): CoercedValue {
226
        $coercedValues = [];
227
        $errors        = [];
228
229
        foreach ($variableDefinitionNodes as $variableDefinitionNode) {
230
            $variableName     = $variableDefinitionNode->getVariable()->getNameValue();
231
            $variableType     = TypeASTConverter::convert($schema, $variableDefinitionNode->getType());
232
            $variableTypeName = (string)$variableType;
233
234
            if ($variableTypeName === '') {
235
                $variableTypeName = (string)$variableDefinitionNode;
236
            }
237
238
            if (!static::isInputType($variableType)) {
239
                // Must use input types for variables. This should be caught during
240
                // validation, however is checked again here for safety.
241
                $errors[] = static::buildCoerceException(
242
                    sprintf(
243
                        'Variable "$%s" expected value of type "%s" which cannot be used as an input type',
244
                        $variableName,
245
                        $variableTypeName
246
                    ),
247
                    $variableDefinitionNode,
248
                    null
249
                );
250
            } else {
251
                $hasValue = array_key_exists($variableName, $inputs);
252
                $value    = $hasValue ? $inputs[$variableName] : null;
253
                if (!$hasValue && $variableDefinitionNode->hasDefaultValue()) {
254
                    // If no value was provided to a variable with a default value,
255
                    // use the default value.
256
                    $coercedValues[$variableName] = ValueASTConverter::convert(
257
                        $variableDefinitionNode->getDefaultValue(),
258
                        $variableType
259
                    );
260
                } elseif ((!$hasValue || null === $value) && $variableType instanceof NonNullType) {
261
                    // If no value or a nullish value was provided to a variable with a
262
                    // non-null type (required), produce an error.
263
                    $errors[] = static::buildCoerceException(
264
                        sprintf(
265
                            $value
266
                                ? 'Variable "$%s" of non-null type "%s" must not be null'
267
                                : 'Variable "$%s" of required type "%s" was not provided',
268
                            $variableName,
269
                            $variableTypeName
270
                        ),
271
                        $variableDefinitionNode,
272
                        null
273
                    );
274
                } elseif ($hasValue) {
275
                    if (null === $value) {
276
                        // If the explicit value `null` was provided, an entry in the coerced
277
                        // values must exist as the value `null`.
278
                        $coercedValues[$variableName] = null;
279
                    } else {
280
                        // Otherwise, a non-null value was provided, coerce it to the expected
281
                        // type or report an error if coercion fails.
282
                        $coercedValue = static::coerceValue($value, $variableType, $variableDefinitionNode);
283
                        if ($coercedValue->hasErrors()) {
284
                            $message = sprintf(
285
                                'Variable "$%s" got invalid value %s',
286
                                $variableName,
287
                                jsonEncode($value)
288
                            );
289
                            foreach ($coercedValue->getErrors() as $error) {
290
                                $errors[] = static::buildCoerceException(
291
                                    $message,
292
                                    $variableDefinitionNode,
293
                                    null,
294
                                    $error->getMessage(),
295
                                    $error
296
                                );
297
                            }
298
                        } else {
299
                            $coercedValues[$variableName] = $coercedValue->getValue();
300
                        }
301
                    }
302
                }
303
            }
304
        }
305
306
        return new CoercedValue($coercedValues, $errors);
307
    }
308
309
    /**
310
     * @param TypeInterface|null $type
311
     * @return bool
312
     */
313
    protected static function isInputType(?TypeInterface $type)
314
    {
315
        return ($type instanceof ScalarType) ||
316
            ($type instanceof EnumType) ||
317
            ($type instanceof InputObjectType) ||
318
            (($type instanceof WrappingTypeInterface) && static::isInputType($type->getOfType()));
319
    }
320
321
    /**
322
     * Returns either a value which is valid for the provided type or a list of
323
     * encountered coercion errors.
324
     *
325
     * @param mixed|array   $value
326
     * @param mixed         $type
327
     * @param NodeInterface $blameNode
328
     * @param Path|null     $path
329
     * @return CoercedValue
330
     * @throws GraphQLException
331
     * @throws InvariantException
332
     */
333
    protected static function coerceValue($value, $type, $blameNode, ?Path $path = null): CoercedValue
334
    {
335
        if ($type instanceof NonNullType) {
336
            return static::coerceValueForNonNullType($value, $type, $blameNode, $path);
337
        }
338
339
        if (null === $value) {
340
            return new CoercedValue(null);
341
        }
342
343
        if ($type instanceof ScalarType) {
344
            return static::coerceValueForScalarType($value, $type, $blameNode, $path);
345
        }
346
347
        if ($type instanceof EnumType) {
348
            return static::coerceValueForEnumType($value, $type, $blameNode, $path);
349
        }
350
351
        if ($type instanceof ListType) {
352
            return static::coerceValueForListType($value, $type, $blameNode, $path);
353
        }
354
355
        if ($type instanceof InputObjectType) {
356
            return static::coerceValueForInputObjectType($value, $type, $blameNode, $path);
357
        }
358
359
        throw new GraphQLException('Unexpected type.');
360
    }
361
362
    /**
363
     * @param mixed         $value
364
     * @param NonNullType   $type
365
     * @param NodeInterface $blameNode
366
     * @param Path|null     $path
367
     * @return CoercedValue
368
     * @throws GraphQLException
369
     * @throws InvariantException
370
     */
371
    protected static function coerceValueForNonNullType(
372
        $value,
373
        NonNullType $type,
374
        NodeInterface $blameNode,
375
        ?Path $path
376
    ): CoercedValue {
377
        if (null === $value) {
378
            return new CoercedValue(null, [
379
                static::buildCoerceException(
380
                    sprintf('Expected non-nullable type %s not to be null', (string)$type),
381
                    $blameNode,
382
                    $path
383
                )
384
            ]);
385
        }
386
        return static::coerceValue($value, $type->getOfType(), $blameNode, $path);
387
    }
388
389
    /**
390
     * Scalars determine if a value is valid via parseValue(), which can
391
     * throw to indicate failure. If it throws, maintain a reference to
392
     * the original error.
393
     *
394
     * @param mixed         $value
395
     * @param ScalarType    $type
396
     * @param NodeInterface $blameNode
397
     * @param Path|null     $path
398
     * @return CoercedValue
399
     */
400
    protected static function coerceValueForScalarType(
401
        $value,
402
        ScalarType $type,
403
        NodeInterface $blameNode,
404
        ?Path $path
405
    ): CoercedValue {
406
        try {
407
            $parseResult = $type->parseValue($value);
408
            if (null === $parseResult) {
409
                return new CoercedValue(null, [
410
                    new GraphQLException(sprintf('Expected type %s', (string)$type))
411
                ]);
412
            }
413
            return new CoercedValue($parseResult);
414
        } /** @noinspection PhpRedundantCatchClauseInspection */ catch (InvalidTypeException|CoercingException $ex) {
415
            return new CoercedValue(null, [
416
                static::buildCoerceException(
417
                    sprintf('Expected type %s', (string)$type),
418
                    $blameNode,
419
                    $path,
420
                    $ex->getMessage(),
421
                    $ex
422
                )
423
            ]);
424
        }
425
    }
426
427
    /**
428
     * @param mixed         $value
429
     * @param EnumType      $type
430
     * @param NodeInterface $blameNode
431
     * @param Path|null     $path
432
     * @return CoercedValue
433
     * @throws InvariantException
434
     */
435
    protected static function coerceValueForEnumType(
436
        $value,
437
        EnumType $type,
438
        NodeInterface $blameNode,
439
        ?Path $path
440
    ): CoercedValue {
441
        if (is_string($value) && null !== ($enumValue = $type->getValue($value))) {
442
            return new CoercedValue($enumValue);
443
        }
444
445
        $suggestions = suggestionList((string)$value, array_map(function (EnumValue $enumValue) {
446
            return $enumValue->getName();
447
        }, $type->getValues()));
448
449
        $didYouMean = (!empty($suggestions))
450
            ? 'did you mean' . implode(',', $suggestions)
451
            : null;
452
453
        return new CoercedValue(null, [
454
            static::buildCoerceException(sprintf('Expected type %s', $type->getName()), $blameNode, $path, $didYouMean)
455
        ]);
456
    }
457
458
    /**
459
     * @param mixed           $value
460
     * @param InputObjectType $type
461
     * @param NodeInterface   $blameNode
462
     * @param Path|null       $path
463
     * @return CoercedValue
464
     * @throws InvariantException
465
     * @throws GraphQLException
466
     */
467
    protected static function coerceValueForInputObjectType(
468
        $value,
469
        InputObjectType $type,
470
        NodeInterface $blameNode,
471
        ?Path $path
472
    ): CoercedValue {
473
        $errors        = [];
474
        $coercedValues = [];
475
        $fields        = $type->getFields();
476
477
        // Ensure every defined field is valid.
478
        foreach ($fields as $field) {
479
            $fieldType = $field->getType();
480
481
            if (!isset($value[$field->getName()])) {
482
                if (!empty($field->getDefaultValue())) {
483
                    $coercedValue[$field->getName()] = $field->getDefaultValue();
484
                } elseif ($fieldType instanceof NonNullType) {
485
                    $errors[] = new GraphQLException(
486
                        sprintf(
487
                            "Field %s of required type %s! was not provided.",
488
                            static::printPath(new Path($path, $field->getName())),
489
                            (string)$fieldType->getOfType()
490
                        )
491
                    );
492
                }
493
            } else {
494
                $fieldValue   = $value[$field->getName()];
495
                $coercedValue = static::coerceValue(
496
                    $fieldValue,
497
                    $fieldType,
498
                    $blameNode,
499
                    new Path($path, $field->getName())
500
                );
501
502
                if ($coercedValue->hasErrors()) {
503
                    $errors = array_merge($errors, $coercedValue->getErrors());
504
                } elseif (empty($errors)) {
505
                    $coercedValues[$field->getName()] = $coercedValue->getValue();
506
                }
507
            }
508
        }
509
510
        // Ensure every provided field is defined.
511
        foreach ($value as $fieldName => $fieldValue) {
512
            if (!isset($fields[$fieldName])) {
513
                $suggestions = suggestionList($fieldName, array_keys($fields));
514
                $didYouMean  = (!empty($suggestions))
515
                    ? 'did you mean' . implode(',', $suggestions)
516
                    : null;
517
518
                $errors[] = static::buildCoerceException(
519
                    sprintf('Field "%s" is not defined by type %s', $fieldName, $type->getName()),
520
                    $blameNode,
521
                    $path,
522
                    $didYouMean
523
                );
524
            }
525
        }
526
527
        return new CoercedValue($coercedValues, $errors);
528
    }
529
530
    /**
531
     * @param mixed         $value
532
     * @param ListType      $type
533
     * @param NodeInterface $blameNode
534
     * @param Path|null     $path
535
     * @return CoercedValue
536
     * @throws GraphQLException
537
     * @throws InvariantException
538
     */
539
    protected static function coerceValueForListType(
540
        $value,
541
        ListType $type,
542
        NodeInterface $blameNode,
543
        ?Path $path
544
    ): CoercedValue {
545
        $itemType = $type->getOfType();
546
547
        if (is_array($value) || $value instanceof Traversable) {
548
            $errors        = [];
549
            $coercedValues = [];
550
551
            foreach ($value as $index => $itemValue) {
552
                $coercedValue = static::coerceValue($itemValue, $itemType, $blameNode, new Path($path, $index));
553
554
                if ($coercedValue->hasErrors()) {
555
                    $errors = array_merge($errors, $coercedValue->getErrors());
556
                } else {
557
                    $coercedValues[] = $coercedValue->getValue();
558
                }
559
            }
560
561
            return new CoercedValue($coercedValues, $errors);
562
        }
563
564
        // Lists accept a non-list value as a list of one.
565
        $coercedValue = static::coerceValue($value, $itemType, $blameNode);
566
567
        return new CoercedValue([$coercedValue->getValue()], $coercedValue->getErrors());
568
    }
569
570
    /**
571
     * @param string                $message
572
     * @param NodeInterface         $blameNode
573
     * @param Path|null             $path
574
     * @param null|string           $subMessage
575
     * @param GraphQLException|null $originalException
576
     * @return GraphQLException
577
     */
578
    protected static function buildCoerceException(
579
        string $message,
580
        NodeInterface $blameNode,
581
        ?Path $path,
582
        ?string $subMessage = null,
583
        ?GraphQLException $originalException = null
584
    ) {
585
        $stringPath = static::printPath($path);
586
587
        return new CoercingException(
588
            $message .
589
            (($stringPath !== '') ? ' at ' . $stringPath : $stringPath) .
590
            (($subMessage !== null) ? '; ' . $subMessage : '.'),
591
            [$blameNode],
592
            null,
593
            null,
594
            null,
595
            null,
596
            $originalException
597
        );
598
    }
599
600
    /**
601
     * @param Path|null $path
602
     * @return string
603
     */
604
    protected static function printPath(?Path $path)
605
    {
606
        $stringPath  = '';
607
        $currentPath = $path;
608
609
        while ($currentPath !== null) {
610
            $stringPath = is_string($currentPath->getKey())
611
                ? '.' . $currentPath->getKey() . $stringPath
612
                : '[' . (string)$currentPath->getKey() . ']' . $stringPath;
613
614
            $currentPath = $currentPath->getPrevious();
615
        }
616
617
        return !empty($stringPath) ? 'value' . $stringPath : '';
618
    }
619
620
    /**
621
     * @param VariableNode  $variableNode
622
     * @param TypeInterface $argumentType
623
     * @param string        $argumentName
624
     * @param array         $variableValues
625
     * @param mixed         $defaultValue
626
     * @return mixed
627
     * @throws ExecutionException
628
     */
629
//    protected static function coerceValueForVariableNode(
630
//        VariableNode $variableNode,
631
//        TypeInterface $argumentType,
632
//        string $argumentName,
633
//        array $variableValues,
634
//        $defaultValue
635
//    ) {
636
//        $variableName = $variableNode->getNameValue();
637
//
638
//        if (isset($variableValues[$variableName])) {
639
//            // Note: this does not check that this variable value is correct.
640
//            // This assumes that this query has been validated and the variable
641
//            // usage here is of the correct type.
642
//            return $variableValues[$variableName];
643
//        }
644
//
645
//        if (null !== $defaultValue) {
646
//            return $defaultValue;
647
//        }
648
//
649
//        if ($argumentType instanceof NonNullType) {
650
//            throw new ExecutionException(
651
//                sprintf(
652
//                    'Argument "%s" of required type "%s" was provided the variable "$%s" which was not provided a runtime value.',
653
//                    $argumentName,
654
//                    $argumentType,
655
//                    $variableName
656
//                ),
657
//                [$variableNode]
658
//            );
659
//        }
660
//
661
//        return null;
662
//    }
663
}
664