Failed Conditions
Push — master ( 7ff3e9...e7de06 )
by Vladimir
04:33 queued 01:54
created

KnownArgumentNamesOnDirectives   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 62
Duplicated Lines 0 %

Test Coverage

Coverage 85.29%

Importance

Changes 0
Metric Value
wmc 12
eloc 36
dl 0
loc 62
ccs 29
cts 34
cp 0.8529
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A unknownDirectiveArgMessage() 0 3 1
B getVisitor() 0 55 11
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Validator\Rules;
6
7
use GraphQL\Error\Error;
8
use GraphQL\Language\AST\DirectiveDefinitionNode;
9
use GraphQL\Language\AST\DirectiveNode;
10
use GraphQL\Language\AST\InputValueDefinitionNode;
11
use GraphQL\Language\AST\NodeKind;
12
use GraphQL\Language\AST\NodeList;
13
use GraphQL\Type\Definition\Directive;
14
use GraphQL\Type\Definition\FieldArgument;
15
use GraphQL\Validator\ValidationContext;
16
use function array_map;
17
use function in_array;
18
use function iterator_to_array;
19
20
/**
21
 * Known argument names on directives
22
 *
23
 * A GraphQL directive is only valid if all supplied arguments are defined by
24
 * that field.
25
 */
26
class KnownArgumentNamesOnDirectives extends ValidationRule
27
{
28
    protected static function unknownDirectiveArgMessage(string $argName, string $directionName)
29
    {
30
        return 'Unknown argument "' . $argName . '" on directive "@' . $directionName . '".';
31
    }
32
33 52
    public function getVisitor(ValidationContext $context)
34
    {
35 52
        $directiveArgs     = [];
36 52
        $schema            = $context->getSchema();
37 52
        $definedDirectives = $schema !== null ? $schema->getDirectives() : Directive::getInternalDirectives();
38
39 52
        foreach ($definedDirectives as $directive) {
40 52
            $directiveArgs[$directive->name] = array_map(
41
                static function (FieldArgument $arg) : string {
42 52
                    return $arg->name;
43 52
                },
44 52
                $directive->args
45
            );
46
        }
47
48 52
        $astDefinitions = $context->getDocument()->definitions;
49 52
        foreach ($astDefinitions as $def) {
50 52
            if (! ($def instanceof DirectiveDefinitionNode)) {
51 46
                continue;
52
            }
53
54 7
            $name = $def->name->value;
55 7
            if ($def->arguments !== null) {
56 7
                $arguments = $def->arguments;
57
58 7
                if ($arguments instanceof NodeList) {
59 7
                    $arguments = iterator_to_array($arguments->getIterator());
60
                }
61
62
                $directiveArgs[$name] = array_map(static function (InputValueDefinitionNode $arg) : string {
63 4
                    return $arg->name->value;
64 7
                }, $arguments);
65
            } else {
66 7
                $directiveArgs[$name] = [];
67
            }
68
        }
69
70
        return [
71
            NodeKind::DIRECTIVE => static function (DirectiveNode $directiveNode) use ($directiveArgs, $context) {
72 10
                $directiveName = $directiveNode->name->value;
73 10
                $knownArgs     = $directiveArgs[$directiveName] ?? null;
74
75 10
                if ($directiveNode->arguments === null || ! $knownArgs) {
76 1
                    return;
77
                }
78
79 9
                foreach ($directiveNode->arguments as $argNode) {
80 3
                    $argName = $argNode->name->value;
81 3
                    if (in_array($argName, $knownArgs)) {
82 3
                        continue;
83
                    }
84
85
                    $context->reportError(new Error(
86
                        self::unknownDirectiveArgMessage($argName, $directiveName),
87
                        [$argNode]
88
                    ));
89
                }
90 52
            },
91
        ];
92
    }
93
}
94