Failed Conditions
Push — master ( a4f39b...12ee90 )
by Vladimir
11:17
created

KnownArgumentNamesOnDirectives   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 62
Duplicated Lines 0 %

Test Coverage

Coverage 85.29%

Importance

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

2 Methods

Rating   Name   Duplication   Size   Complexity  
A unknownDirectiveArgMessage() 0 3 1
B getSDLVisitor() 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\SDLValidationContext;
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 207
    public function getSDLVisitor(SDLValidationContext $context)
34
    {
35 207
        $directiveArgs     = [];
36 207
        $schema            = $context->getSchema();
37 207
        $definedDirectives = $schema !== null ? $schema->getDirectives() : Directive::getInternalDirectives();
38
39 207
        foreach ($definedDirectives as $directive) {
40 207
            $directiveArgs[$directive->name] = array_map(
41
                static function (FieldArgument $arg) : string {
42 207
                    return $arg->name;
43 207
                },
44 207
                $directive->args
45
            );
46
        }
47
48 207
        $astDefinitions = $context->getDocument()->definitions;
49 207
        foreach ($astDefinitions as $def) {
50 207
            if (! ($def instanceof DirectiveDefinitionNode)) {
51 188
                continue;
52
            }
53
54 37
            $name = $def->name->value;
55 37
            if ($def->arguments !== null) {
56 37
                $arguments = $def->arguments;
57
58 37
                if ($arguments instanceof NodeList) {
59 37
                    $arguments = iterator_to_array($arguments->getIterator());
60
                }
61
62
                $directiveArgs[$name] = array_map(static function (InputValueDefinitionNode $arg) : string {
63 9
                    return $arg->name->value;
64 37
                }, $arguments);
65
            } else {
66 37
                $directiveArgs[$name] = [];
67
            }
68
        }
69
70
        return [
71
            NodeKind::DIRECTIVE => static function (DirectiveNode $directiveNode) use ($directiveArgs, $context) {
72 17
                $directiveName = $directiveNode->name->value;
73 17
                $knownArgs     = $directiveArgs[$directiveName] ?? null;
74
75 17
                if ($directiveNode->arguments === null || ! $knownArgs) {
76 7
                    return;
77
                }
78
79 10
                foreach ($directiveNode->arguments as $argNode) {
80 4
                    $argName = $argNode->name->value;
81 4
                    if (in_array($argName, $knownArgs, true)) {
82 4
                        continue;
83
                    }
84
85
                    $context->reportError(new Error(
86
                        self::unknownDirectiveArgMessage($argName, $directiveName),
87
                        [$argNode]
88
                    ));
89
                }
90 207
            },
91
        ];
92
    }
93
}
94