Failed Conditions
Push — master ( cc39b3...a3ef1b )
by Šimon
10s
created

AST::valueFromAST()   D

Complexity

Conditions 30
Paths 27

Size

Total Lines 140
Code Lines 72

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 67
CRAP Score 30.1606

Importance

Changes 0
Metric Value
eloc 72
dl 0
loc 140
rs 4.1666
c 0
b 0
f 0
ccs 67
cts 71
cp 0.9437
cc 30
nc 27
nop 3
crap 30.1606

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Utils;
6
7
use GraphQL\Error\Error;
8
use GraphQL\Error\InvariantViolation;
9
use GraphQL\Language\AST\BooleanValueNode;
10
use GraphQL\Language\AST\DocumentNode;
11
use GraphQL\Language\AST\EnumValueNode;
12
use GraphQL\Language\AST\FloatValueNode;
13
use GraphQL\Language\AST\IntValueNode;
14
use GraphQL\Language\AST\ListTypeNode;
15
use GraphQL\Language\AST\ListValueNode;
16
use GraphQL\Language\AST\Location;
17
use GraphQL\Language\AST\NamedTypeNode;
18
use GraphQL\Language\AST\NameNode;
19
use GraphQL\Language\AST\Node;
20
use GraphQL\Language\AST\NodeKind;
21
use GraphQL\Language\AST\NodeList;
22
use GraphQL\Language\AST\NonNullTypeNode;
23
use GraphQL\Language\AST\NullValueNode;
24
use GraphQL\Language\AST\ObjectFieldNode;
25
use GraphQL\Language\AST\ObjectValueNode;
26
use GraphQL\Language\AST\OperationDefinitionNode;
27
use GraphQL\Language\AST\StringValueNode;
28
use GraphQL\Language\AST\ValueNode;
29
use GraphQL\Language\AST\VariableNode;
30
use GraphQL\Type\Definition\EnumType;
31
use GraphQL\Type\Definition\IDType;
32
use GraphQL\Type\Definition\InputObjectType;
33
use GraphQL\Type\Definition\InputType;
34
use GraphQL\Type\Definition\ListOfType;
35
use GraphQL\Type\Definition\NonNull;
36
use GraphQL\Type\Definition\ScalarType;
37
use GraphQL\Type\Definition\Type;
38
use GraphQL\Type\Schema;
39
use function array_combine;
40
use function array_key_exists;
41
use function array_map;
42
use function count;
43
use function floatval;
44
use function intval;
45
use function is_array;
46
use function is_bool;
47
use function is_float;
48
use function is_int;
49
use function is_object;
50
use function is_string;
51
use function iterator_to_array;
52
use function json_encode;
53
use function property_exists;
54
use function substr;
55
56
/**
57
 * Various utilities dealing with AST
58
 */
59
class AST
60
{
61
    /**
62
     * Convert representation of AST as an associative array to instance of GraphQL\Language\AST\Node.
63
     *
64
     * For example:
65
     *
66
     * ```php
67
     * AST::fromArray([
68
     *     'kind' => 'ListValue',
69
     *     'values' => [
70
     *         ['kind' => 'StringValue', 'value' => 'my str'],
71
     *         ['kind' => 'StringValue', 'value' => 'my other str']
72
     *     ],
73
     *     'loc' => ['start' => 21, 'end' => 25]
74
     * ]);
75
     * ```
76
     *
77
     * Will produce instance of `ListValueNode` where `values` prop is a lazily-evaluated `NodeList`
78
     * returning instances of `StringValueNode` on access.
79
     *
80
     * This is a reverse operation for AST::toArray($node)
81
     *
82
     * @api
83
     * @param mixed[] $node
84
     * @return Node
85
     */
86 2
    public static function fromArray(array $node)
87
    {
88 2
        if (! isset($node['kind']) || ! isset(NodeKind::$classMap[$node['kind']])) {
89
            throw new InvariantViolation('Unexpected node structure: ' . Utils::printSafeJson($node));
90
        }
91
92 2
        $kind     = $node['kind'] ?? null;
93 2
        $class    = NodeKind::$classMap[$kind];
94 2
        $instance = new $class([]);
95
96 2
        if (isset($node['loc'], $node['loc']['start'], $node['loc']['end'])) {
97 1
            $instance->loc = Location::create($node['loc']['start'], $node['loc']['end']);
98
        }
99
100 2
        foreach ($node as $key => $value) {
101 2
            if ($key === 'loc' || $key === 'kind') {
102 2
                continue;
103
            }
104 2
            if (is_array($value)) {
105 2
                if (isset($value[0]) || empty($value)) {
106 2
                    $value = new NodeList($value);
107
                } else {
108 2
                    $value = self::fromArray($value);
109
                }
110
            }
111 2
            $instance->{$key} = $value;
112
        }
113
114 2
        return $instance;
115
    }
116
117
    /**
118
     * Convert AST node to serializable array
119
     *
120
     * @api
121
     * @return mixed[]
122
     */
123
    public static function toArray(Node $node)
124
    {
125
        return $node->toArray(true);
126
    }
127
128
    /**
129
     * Produces a GraphQL Value AST given a PHP value.
130
     *
131
     * Optionally, a GraphQL type may be provided, which will be used to
132
     * disambiguate between value primitives.
133
     *
134
     * | PHP Value     | GraphQL Value        |
135
     * | ------------- | -------------------- |
136
     * | Object        | Input Object         |
137
     * | Assoc Array   | Input Object         |
138
     * | Array         | List                 |
139
     * | Boolean       | Boolean              |
140
     * | String        | String / Enum Value  |
141
     * | Int           | Int                  |
142
     * | Float         | Int / Float          |
143
     * | Mixed         | Enum Value           |
144
     * | null          | NullValue            |
145
     *
146
     * @api
147
     * @param Type|mixed|null $value
148
     * @return ObjectValueNode|ListValueNode|BooleanValueNode|IntValueNode|FloatValueNode|EnumValueNode|StringValueNode|NullValueNode
149
     */
150 26
    public static function astFromValue($value, InputType $type)
151
    {
152 26
        if ($type instanceof NonNull) {
153 4
            $astValue = self::astFromValue($value, $type->getWrappedType());
0 ignored issues
show
Bug introduced by
It seems like $type->getWrappedType() can also be of type GraphQL\Type\Definition\UnionType and GraphQL\Type\Definition\ObjectType and GraphQL\Type\Definition\InterfaceType; however, parameter $type of GraphQL\Utils\AST::astFromValue() does only seem to accept GraphQL\Type\Definition\InputType, 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

153
            $astValue = self::astFromValue($value, /** @scrutinizer ignore-type */ $type->getWrappedType());
Loading history...
154 4
            if ($astValue instanceof NullValueNode) {
155 4
                return null;
156
            }
157
158 1
            return $astValue;
159
        }
160
161 26
        if ($value === null) {
162 7
            return new NullValueNode([]);
163
        }
164
165
        // Convert PHP array to GraphQL list. If the GraphQLType is a list, but
166
        // the value is not an array, convert the value using the list's item type.
167 24
        if ($type instanceof ListOfType) {
168 2
            $itemType = $type->getWrappedType();
169 2
            if (is_array($value) || ($value instanceof \Traversable)) {
170 1
                $valuesNodes = [];
171 1
                foreach ($value as $item) {
172 1
                    $itemNode = self::astFromValue($item, $itemType);
173 1
                    if (! $itemNode) {
174
                        continue;
175
                    }
176
177 1
                    $valuesNodes[] = $itemNode;
178
                }
179
180 1
                return new ListValueNode(['values' => $valuesNodes]);
181
            }
182
183 1
            return self::astFromValue($value, $itemType);
184
        }
185
186
        // Populate the fields of the input object by creating ASTs from each value
187
        // in the PHP object according to the fields in the input type.
188 24
        if ($type instanceof InputObjectType) {
189 2
            $isArray     = is_array($value);
190 2
            $isArrayLike = $isArray || $value instanceof \ArrayAccess;
191 2
            if ($value === null || (! $isArrayLike && ! is_object($value))) {
192
                return null;
193
            }
194 2
            $fields     = $type->getFields();
195 2
            $fieldNodes = [];
196 2
            foreach ($fields as $fieldName => $field) {
197 2
                if ($isArrayLike) {
198 2
                    $fieldValue = $value[$fieldName] ?? null;
199
                } else {
200 1
                    $fieldValue = $value->{$fieldName} ?? null;
201
                }
202
203
                // Have to check additionally if key exists, since we differentiate between
204
                // "no key" and "value is null":
205 2
                if ($fieldValue !== null) {
206 1
                    $fieldExists = true;
207 1
                } elseif ($isArray) {
208 1
                    $fieldExists = array_key_exists($fieldName, $value);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type ArrayAccess and GraphQL\Type\Definition\Type and GraphQL\Type\Definition\Type&ArrayAccess; however, parameter $search of array_key_exists() does only seem to accept array, 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

208
                    $fieldExists = array_key_exists($fieldName, /** @scrutinizer ignore-type */ $value);
Loading history...
209
                } elseif ($isArrayLike) {
210
                    /** @var \ArrayAccess $value */
211
                    $fieldExists = $value->offsetExists($fieldName);
212
                } else {
213
                    $fieldExists = property_exists($value, $fieldName);
214
                }
215
216 2
                if (! $fieldExists) {
217 1
                    continue;
218
                }
219
220 2
                $fieldNode = self::astFromValue($fieldValue, $field->getType());
0 ignored issues
show
Bug introduced by
It seems like $field->getType() can also be of type callable; however, parameter $type of GraphQL\Utils\AST::astFromValue() does only seem to accept GraphQL\Type\Definition\InputType, 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

220
                $fieldNode = self::astFromValue($fieldValue, /** @scrutinizer ignore-type */ $field->getType());
Loading history...
221
222 2
                if (! $fieldNode) {
223
                    continue;
224
                }
225
226 2
                $fieldNodes[] = new ObjectFieldNode([
227 2
                    'name'  => new NameNode(['value' => $fieldName]),
228 2
                    'value' => $fieldNode,
229
                ]);
230
            }
231
232 2
            return new ObjectValueNode(['fields' => $fieldNodes]);
233
        }
234
235 23
        if ($type instanceof ScalarType || $type instanceof EnumType) {
236
            // Since value is an internally represented value, it must be serialized
237
            // to an externally represented value before converting into an AST.
238
            try {
239 23
                $serialized = $type->serialize($value);
240 3
            } catch (\Exception $error) {
241 3
                if ($error instanceof Error && $type instanceof EnumType) {
242 1
                    return null;
243
                }
244 2
                throw $error;
245
            } catch (\Throwable $error) {
246
                if ($error instanceof Error && $type instanceof EnumType) {
247
                    return null;
248
                }
249
                throw $error;
250
            }
251
252
            // Others serialize based on their corresponding PHP scalar types.
253 21
            if (is_bool($serialized)) {
254 6
                return new BooleanValueNode(['value' => $serialized]);
255
            }
256 19
            if (is_int($serialized)) {
257 5
                return new IntValueNode(['value' => $serialized]);
258
            }
259 14
            if (is_float($serialized)) {
260
                // int cast with == used for performance reasons
261
                // @codingStandardsIgnoreLine
262 2
                if ((int) $serialized == $serialized) {
263 2
                    return new IntValueNode(['value' => $serialized]);
264
                }
265
266 1
                return new FloatValueNode(['value' => $serialized]);
267
            }
268 13
            if (is_string($serialized)) {
269
                // Enum types use Enum literals.
270 13
                if ($type instanceof EnumType) {
271 4
                    return new EnumValueNode(['value' => $serialized]);
272
                }
273
274
                // ID types can use Int literals.
275 11
                $asInt = (int) $serialized;
276 11
                if ($type instanceof IDType && (string) $asInt === $serialized) {
277 1
                    return new IntValueNode(['value' => $serialized]);
278
                }
279
280
                // Use json_encode, which uses the same string encoding as GraphQL,
281
                // then remove the quotes.
282 11
                return new StringValueNode([
283 11
                    'value' => substr(json_encode($serialized), 1, -1),
284
                ]);
285
            }
286
287
            throw new InvariantViolation('Cannot convert value to AST: ' . Utils::printSafe($serialized));
288
        }
289
290
        throw new Error('Unknown type: ' . Utils::printSafe($type) . '.');
291
    }
292
293
    /**
294
     * Produces a PHP value given a GraphQL Value AST.
295
     *
296
     * A GraphQL type must be provided, which will be used to interpret different
297
     * GraphQL Value literals.
298
     *
299
     * Returns `null` when the value could not be validly coerced according to
300
     * the provided type.
301
     *
302
     * | GraphQL Value        | PHP Value     |
303
     * | -------------------- | ------------- |
304
     * | Input Object         | Assoc Array   |
305
     * | List                 | Array         |
306
     * | Boolean              | Boolean       |
307
     * | String               | String        |
308
     * | Int / Float          | Int / Float   |
309
     * | Enum Value           | Mixed         |
310
     * | Null Value           | null          |
311
     *
312
     * @api
313
     * @param ValueNode|null $valueNode
314
     * @param mixed[]|null   $variables
315
     * @return mixed[]|null|\stdClass
316
     * @throws \Exception
317
     */
318 73
    public static function valueFromAST($valueNode, InputType $type, $variables = null)
319
    {
320 73
        $undefined = Utils::undefined();
321
322 73
        if ($valueNode === null) {
323
            // When there is no AST, then there is also no value.
324
            // Importantly, this is different from returning the GraphQL null value.
325 1
            return $undefined;
326
        }
327
328 72
        if ($type instanceof NonNull) {
329 36
            if ($valueNode instanceof NullValueNode) {
330
                // Invalid: intentionally return no value.
331 5
                return $undefined;
332
            }
333
334 35
            return self::valueFromAST($valueNode, $type->getWrappedType(), $variables);
0 ignored issues
show
Bug introduced by
It seems like $type->getWrappedType() can also be of type GraphQL\Type\Definition\UnionType and GraphQL\Type\Definition\ObjectType and GraphQL\Type\Definition\InterfaceType; however, parameter $type of GraphQL\Utils\AST::valueFromAST() does only seem to accept GraphQL\Type\Definition\InputType, 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

334
            return self::valueFromAST($valueNode, /** @scrutinizer ignore-type */ $type->getWrappedType(), $variables);
Loading history...
335
        }
336
337 72
        if ($valueNode instanceof NullValueNode) {
338
            // This is explicitly returning the value null.
339 7
            return null;
340
        }
341
342 71
        if ($valueNode instanceof VariableNode) {
343 3
            $variableName = $valueNode->name->value;
344
345 3
            if (! $variables || ! array_key_exists($variableName, $variables)) {
346
                // No valid return value.
347 1
                return $undefined;
348
            }
349
            // Note: we're not doing any checking that this variable is correct. We're
350
            // assuming that this query has been validated and the variable usage here
351
            // is of the correct type.
352 3
            return $variables[$variableName];
353
        }
354
355 70
        if ($type instanceof ListOfType) {
356 7
            $itemType = $type->getWrappedType();
357
358 7
            if ($valueNode instanceof ListValueNode) {
359 7
                $coercedValues = [];
360 7
                $itemNodes     = $valueNode->values;
361 7
                foreach ($itemNodes as $itemNode) {
362 7
                    if (self::isMissingVariable($itemNode, $variables)) {
363
                        // If an array contains a missing variable, it is either coerced to
364
                        // null or if the item type is non-null, it considered invalid.
365 1
                        if ($itemType instanceof NonNull) {
366
                            // Invalid: intentionally return no value.
367 1
                            return $undefined;
368
                        }
369 1
                        $coercedValues[] = null;
370
                    } else {
371 7
                        $itemValue = self::valueFromAST($itemNode, $itemType, $variables);
372 7
                        if ($undefined === $itemValue) {
373
                            // Invalid: intentionally return no value.
374 4
                            return $undefined;
375
                        }
376 7
                        $coercedValues[] = $itemValue;
377
                    }
378
                }
379
380 7
                return $coercedValues;
381
            }
382 5
            $coercedValue = self::valueFromAST($valueNode, $itemType, $variables);
383 5
            if ($undefined === $coercedValue) {
384
                // Invalid: intentionally return no value.
385 4
                return $undefined;
386
            }
387
388 5
            return [$coercedValue];
389
        }
390
391 69
        if ($type instanceof InputObjectType) {
392 4
            if (! $valueNode instanceof ObjectValueNode) {
393
                // Invalid: intentionally return no value.
394 2
                return $undefined;
395
            }
396
397 4
            $coercedObj = [];
398 4
            $fields     = $type->getFields();
399 4
            $fieldNodes = Utils::keyMap(
400 4
                $valueNode->fields,
401
                function ($field) {
402 4
                    return $field->name->value;
403 4
                }
404
            );
405 4
            foreach ($fields as $field) {
406
                /** @var ValueNode $fieldNode */
407 4
                $fieldName = $field->name;
408 4
                $fieldNode = $fieldNodes[$fieldName] ?? null;
409
410 4
                if (! $fieldNode || self::isMissingVariable($fieldNode->value, $variables)) {
411 4
                    if ($field->defaultValueExists()) {
412 2
                        $coercedObj[$fieldName] = $field->defaultValue;
413 4
                    } elseif ($field->getType() instanceof NonNull) {
414
                        // Invalid: intentionally return no value.
415 2
                        return $undefined;
416
                    }
417 4
                    continue;
418
                }
419
420 4
                $fieldValue = self::valueFromAST($fieldNode ? $fieldNode->value : null, $field->getType(), $variables);
0 ignored issues
show
Bug introduced by
It seems like $field->getType() can also be of type callable; however, parameter $type of GraphQL\Utils\AST::valueFromAST() does only seem to accept GraphQL\Type\Definition\InputType, 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

420
                $fieldValue = self::valueFromAST($fieldNode ? $fieldNode->value : null, /** @scrutinizer ignore-type */ $field->getType(), $variables);
Loading history...
421
422 4
                if ($undefined === $fieldValue) {
423
                    // Invalid: intentionally return no value.
424 1
                    return $undefined;
425
                }
426 4
                $coercedObj[$fieldName] = $fieldValue;
427
            }
428
429 4
            return $coercedObj;
430
        }
431
432 69
        if ($type instanceof EnumType) {
433 6
            if (! $valueNode instanceof EnumValueNode) {
434 1
                return $undefined;
435
            }
436 6
            $enumValue = $type->getValue($valueNode->value);
437 6
            if (! $enumValue) {
438
                return $undefined;
439
            }
440
441 6
            return $enumValue->value;
442
        }
443
444 64
        if ($type instanceof ScalarType) {
445
            // Scalars fulfill parsing a literal value via parseLiteral().
446
            // Invalid values represent a failure to parse correctly, in which case
447
            // no value is returned.
448
            try {
449 64
                return $type->parseLiteral($valueNode, $variables);
450 8
            } catch (\Exception $error) {
451 8
                return $undefined;
452
            } catch (\Throwable $error) {
453
                return $undefined;
454
            }
455
        }
456
457
        throw new Error('Unknown type: ' . Utils::printSafe($type) . '.');
458
    }
459
460
    /**
461
     * Produces a PHP value given a GraphQL Value AST.
462
     *
463
     * Unlike `valueFromAST()`, no type is provided. The resulting PHP value
464
     * will reflect the provided GraphQL value AST.
465
     *
466
     * | GraphQL Value        | PHP Value     |
467
     * | -------------------- | ------------- |
468
     * | Input Object         | Assoc Array   |
469
     * | List                 | Array         |
470
     * | Boolean              | Boolean       |
471
     * | String               | String        |
472
     * | Int / Float          | Int / Float   |
473
     * | Enum                 | Mixed         |
474
     * | Null                 | null          |
475
     *
476
     * @api
477
     * @param Node         $valueNode
478
     * @param mixed[]|null $variables
479
     * @return mixed
480
     * @throws \Exception
481
     */
482 6
    public static function valueFromASTUntyped($valueNode, ?array $variables = null)
483
    {
484
        switch (true) {
485 6
            case $valueNode instanceof NullValueNode:
486 2
                return null;
487 6
            case $valueNode instanceof IntValueNode:
488 3
                return intval($valueNode->value, 10);
489 5
            case $valueNode instanceof FloatValueNode:
490 2
                return floatval($valueNode->value);
491 5
            case $valueNode instanceof StringValueNode:
492 5
            case $valueNode instanceof EnumValueNode:
493 5
            case $valueNode instanceof BooleanValueNode:
494 4
                return $valueNode->value;
495 4
            case $valueNode instanceof ListValueNode:
496 4
                return array_map(
497
                    function ($node) use ($variables) {
498 4
                        return self::valueFromASTUntyped($node, $variables);
499 4
                    },
500 4
                    iterator_to_array($valueNode->values)
501
                );
502 2
            case $valueNode instanceof ObjectValueNode:
503 2
                return array_combine(
504 2
                    array_map(
505
                        function ($field) {
506 2
                            return $field->name->value;
507 2
                        },
508 2
                        iterator_to_array($valueNode->fields)
509
                    ),
510 2
                    array_map(
511
                        function ($field) use ($variables) {
512 2
                            return self::valueFromASTUntyped($field->value, $variables);
513 2
                        },
514 2
                        iterator_to_array($valueNode->fields)
515
                    )
516
                );
517 1
            case $valueNode instanceof VariableNode:
518 1
                $variableName = $valueNode->name->value;
519
520 1
                return ($variables && isset($variables[$variableName]))
521 1
                    ? $variables[$variableName]
522 1
                    : null;
523
        }
524
525
        throw new Error('Unexpected value kind: ' . $valueNode->kind . '.');
526
    }
527
528
    /**
529
     * Returns type definition for given AST Type node
530
     *
531
     * @api
532
     * @param NamedTypeNode|ListTypeNode|NonNullTypeNode $inputTypeNode
533
     * @return Type|null
534
     * @throws \Exception
535
     */
536 331
    public static function typeFromAST(Schema $schema, $inputTypeNode)
537
    {
538 331
        if ($inputTypeNode instanceof ListTypeNode) {
539 18
            $innerType = self::typeFromAST($schema, $inputTypeNode->type);
540
541 18
            return $innerType ? new ListOfType($innerType) : null;
542
        }
543 331
        if ($inputTypeNode instanceof NonNullTypeNode) {
544 44
            $innerType = self::typeFromAST($schema, $inputTypeNode->type);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $innerType is correct as self::typeFromAST($schema, $inputTypeNode->type) targeting GraphQL\Utils\AST::typeFromAST() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
It seems like $inputTypeNode->type can also be of type GraphQL\Language\AST\NameNode; however, parameter $inputTypeNode of GraphQL\Utils\AST::typeFromAST() does only seem to accept GraphQL\Language\AST\Lis...guage\AST\NamedTypeNode, 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

544
            $innerType = self::typeFromAST($schema, /** @scrutinizer ignore-type */ $inputTypeNode->type);
Loading history...
545
546 44
            return $innerType ? new NonNull($innerType) : null;
0 ignored issues
show
introduced by
$innerType is of type null, thus it always evaluated to false.
Loading history...
547
        }
548 331
        if ($inputTypeNode instanceof NamedTypeNode) {
0 ignored issues
show
introduced by
$inputTypeNode is always a sub-type of GraphQL\Language\AST\NamedTypeNode.
Loading history...
549 331
            return $schema->getType($inputTypeNode->name->value);
550
        }
551
552
        throw new Error('Unexpected type kind: ' . $inputTypeNode->kind . '.');
553
    }
554
555
    /**
556
     * Returns true if the provided valueNode is a variable which is not defined
557
     * in the set of variables.
558
     * @param ValueNode $valueNode
559
     * @param mixed[]   $variables
560
     * @return bool
561
     */
562 9
    private static function isMissingVariable($valueNode, $variables)
563
    {
564 9
        return $valueNode instanceof VariableNode &&
565 9
            (count($variables) === 0 || ! array_key_exists($valueNode->name->value, $variables));
566
    }
567
568
    /**
569
     * Returns operation type ("query", "mutation" or "subscription") given a document and operation name
570
     *
571
     * @api
572
     * @param string $operationName
573
     * @return bool
574
     */
575 22
    public static function getOperation(DocumentNode $document, $operationName = null)
576
    {
577 22
        if ($document->definitions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $document->definitions of type GraphQL\Language\AST\DefinitionNode[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
578 22
            foreach ($document->definitions as $def) {
579 22
                if (! ($def instanceof OperationDefinitionNode)) {
580
                    continue;
581
                }
582
583 22
                if (! $operationName || (isset($def->name->value) && $def->name->value === $operationName)) {
584 22
                    return $def->operation;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $def->operation returns the type string which is incompatible with the documented return type boolean.
Loading history...
585
                }
586
            }
587
        }
588
589
        return false;
590
    }
591
}
592