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

NoUndefinedVariablesRule   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 48
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 48
rs 10
c 0
b 0
f 0
wmc 8

2 Methods

Rating   Name   Duplication   Size   Complexity  
A enterNode() 0 11 3
B leaveNode() 0 22 5
1
<?php
2
3
namespace Digia\GraphQL\Validation\Rule;
4
5
use Digia\GraphQL\Error\ValidationException;
6
use Digia\GraphQL\Language\AST\Node\NodeInterface;
7
use Digia\GraphQL\Language\AST\Node\OperationDefinitionNode;
8
use Digia\GraphQL\Language\AST\Node\VariableDefinitionNode;
9
use Digia\GraphQL\Language\AST\Node\VariableNode;
10
11
/**
12
 * No undefined variables
13
 *
14
 * A GraphQL operation is only valid if all variables encountered, both directly
15
 * and via fragment spreads, are defined by that operation.
16
 */
17
class NoUndefinedVariablesRule extends AbstractRule
18
{
19
    /**
20
     * @var array
21
     */
22
    protected $definedVariableNames;
23
24
    /**
25
     * @inheritdoc
26
     */
27
    public function enterNode(NodeInterface $node): ?NodeInterface
28
    {
29
        if ($node instanceof OperationDefinitionNode) {
30
            $this->definedVariableNames = [];
31
        }
32
33
        if ($node instanceof VariableDefinitionNode) {
34
            $this->definedVariableNames[$node->getVariable()->getNameValue()] = true;
35
        }
36
37
        return $node;
38
    }
39
40
    /**
41
     * @inheritdoc
42
     */
43
    public function leaveNode(NodeInterface $node): ?NodeInterface
44
    {
45
        if ($node instanceof OperationDefinitionNode) {
46
            $usages = $this->context->getRecursiveVariableUsages($node);
47
48
            foreach ($usages as ['node' => $variableNode]) {
49
                /** @var VariableNode $variableNode */
50
                $variableName = $variableNode->getNameValue();
51
52
                if (!isset($this->definedVariableNames[$variableName])) {
53
                    $operationName = $node->getName();
54
                    $this->context->reportError(
55
                        new ValidationException(
56
                            undefinedVariableMessage($variableName, $operationName ? $operationName->getValue() : null),
57
                            [$variableNode, $node]
58
                        )
59
                    );
60
                }
61
            }
62
        }
63
64
        return $node;
65
    }
66
}
67