Completed
Pull Request — master (#118)
by Christoffer
03:27
created

DirectivesRule::getAllDirectiveArgumentNodes()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.2
c 0
b 0
f 0
cc 4
eloc 7
nc 2
nop 2
1
<?php
2
3
namespace Digia\GraphQL\SchemaValidator\Rule;
4
5
use Digia\GraphQL\Error\ValidationException;
6
use Digia\GraphQL\Language\Node\DirectiveNode;
7
use Digia\GraphQL\SchemaValidator\ValidationContext;
8
use Digia\GraphQL\Type\Definition\Directive;
9
use function Digia\GraphQL\Type\isInputType;
10
11
class DirectivesRule extends AbstractRule
12
{
13
    use ValidatesNamesTrait;
14
    
15
    /**
16
     * @inheritdoc
17
     */
18
    public function validate(ValidationContext $context): void
19
    {
20
        $directives = $context->getSchema()->getDirectives();
21
22
        foreach ($directives as $directive) {
23
            if (!($directive instanceof Directive)) {
24
                $context->reportError(
25
                    new ValidationException(
26
                        \sprintf('Expected directive but got: %s.', $directive->getAstNode())
27
                    )
28
                );
29
30
                return;
31
            }
32
33
            // Ensure they are named correctly.
34
            $this->validateName($context, $directive);
35
36
            // TODO: Ensure proper locations.
37
38
            // Ensure the arguments are valid.
39
            $argumentNames = [];
40
41
            foreach ($directive->getArguments() as $argument) {
42
                $argumentName = $argument->getName();
43
44
                // Ensure they are named correctly.
45
                $this->validateName($context, $argument);
46
47
                // Ensure they are unique per directive.
48
                if (isset($argumentNames[$argumentName])) {
49
                    $context->reportError(
50
                        new ValidationException(
51
                            \sprintf(
52
                                'Argument @%s(%s:) can only be defined once.',
53
                                $directive->getName(),
54
                                $argumentName
55
                            ),
56
                            $this->getAllDirectiveArgumentNodes($directive, $argumentName)
57
                        )
58
                    );
59
60
                    continue;
61
                }
62
63
                $argumentNames[$argumentName] = true;
64
65
                // Ensure the type is an input type.
66
                if (!isInputType($argument->getType())) {
67
                    $context->reportError(
68
                        new ValidationException(
69
                            \sprintf(
70
                                'The type of @%s(%s:) must be Input Type but got: %s.',
71
                                $directive->getName(),
72
                                $argumentName,
73
                                (string)$argument->getType()
74
                            ),
75
                            $this->getAllDirectiveArgumentNodes($directive, $argumentName)
76
                        )
77
                    );
78
                }
79
            }
80
        }
81
    }
82
83
    /**
84
     * @param Directive $directive
85
     * @param string    $argumentName
86
     * @return array
87
     */
88
    protected function getAllDirectiveArgumentNodes(Directive $directive, string $argumentName)
89
    {
90
        $nodes = [];
91
92
        /** @var DirectiveNode $directiveNode */
93
        $directiveNode = $directive->getAstNode();
94
95
        if (null !== $directiveNode) {
96
            foreach ($directiveNode->getArguments() as $node) {
97
                if ($node->getNameValue() === $argumentName) {
98
                    $nodes[] = $node;
99
                }
100
            }
101
        }
102
103
        return $nodes;
104
    }
105
}
106