getDirectiveLocationFromASTPath()   D
last analyzed

Complexity

Conditions 27
Paths 20

Size

Total Lines 63
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 27
eloc 43
c 1
b 0
f 0
nc 20
nop 1
dl 0
loc 63
rs 4.1666

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
namespace Digia\GraphQL\Validation\Rule;
4
5
use Digia\GraphQL\Language\DirectiveLocationEnum;
6
use Digia\GraphQL\Language\Node\DirectiveNode;
7
use Digia\GraphQL\Language\Node\EnumTypeDefinitionNode;
8
use Digia\GraphQL\Language\Node\EnumTypeExtensionNode;
9
use Digia\GraphQL\Language\Node\EnumValueDefinitionNode;
10
use Digia\GraphQL\Language\Node\FieldDefinitionNode;
11
use Digia\GraphQL\Language\Node\FieldNode;
12
use Digia\GraphQL\Language\Node\FragmentDefinitionNode;
13
use Digia\GraphQL\Language\Node\FragmentSpreadNode;
14
use Digia\GraphQL\Language\Node\InlineFragmentNode;
15
use Digia\GraphQL\Language\Node\InputObjectTypeDefinitionNode;
16
use Digia\GraphQL\Language\Node\InputObjectTypeExtensionNode;
17
use Digia\GraphQL\Language\Node\InputValueDefinitionNode;
18
use Digia\GraphQL\Language\Node\InterfaceTypeDefinitionNode;
19
use Digia\GraphQL\Language\Node\InterfaceTypeExtensionNode;
20
use Digia\GraphQL\Language\Node\NodeInterface;
21
use Digia\GraphQL\Language\Node\ObjectTypeDefinitionNode;
22
use Digia\GraphQL\Language\Node\ObjectTypeExtensionNode;
23
use Digia\GraphQL\Language\Node\OperationDefinitionNode;
24
use Digia\GraphQL\Language\Node\ScalarTypeDefinitionNode;
25
use Digia\GraphQL\Language\Node\ScalarTypeExtensionNode;
26
use Digia\GraphQL\Language\Node\SchemaDefinitionNode;
27
use Digia\GraphQL\Language\Node\SchemaExtensionNode;
28
use Digia\GraphQL\Language\Node\UnionTypeDefinitionNode;
29
use Digia\GraphQL\Language\Node\UnionTypeExtensionNode;
30
use Digia\GraphQL\Language\Visitor\VisitorResult;
31
use Digia\GraphQL\Type\Definition\Directive;
32
use Digia\GraphQL\Validation\ValidationException;
33
use function Digia\GraphQL\Util\find;
34
use function Digia\GraphQL\Validation\misplacedDirectiveMessage;
35
use function Digia\GraphQL\Validation\unknownDirectiveMessage;
36
37
/**
38
 * Known directives
39
 *
40
 * A GraphQL document is only valid if all `@directives` are known by the
41
 * schema and legally positioned.
42
 */
43
class KnownDirectivesRule extends AbstractRule
44
{
45
    /**
46
     * @inheritdoc
47
     */
48
    protected function enterDirective(DirectiveNode $node): VisitorResult
49
    {
50
        /** @var Directive $directiveDefinition */
51
        $directiveDefinition = find(
52
            $this->context->getSchema()->getDirectives(),
53
            function (Directive $definition) use ($node) {
54
                return $definition->getName() === $node->getNameValue();
55
            }
56
        );
57
58
        if (null == $directiveDefinition) {
59
            $this->context->reportError(
60
                new ValidationException(unknownDirectiveMessage((string)$node), [$node])
61
            );
62
63
            return new VisitorResult($node);
64
        }
65
66
        $location = $this->getDirectiveLocationFromASTPath($node);
67
68
        if (null !== $location && !\in_array($location, $directiveDefinition->getLocations())) {
69
            $this->context->reportError(
70
                new ValidationException(misplacedDirectiveMessage((string)$node, $location), [$node])
71
            );
72
        }
73
74
        return new VisitorResult($node);
75
    }
76
77
    /**
78
     * @param NodeInterface $node
79
     * @return string|null
80
     */
81
    protected function getDirectiveLocationFromASTPath(NodeInterface $node): ?string
82
    {
83
        $appliedTo = $node->getAncestor();
84
85
        if ($appliedTo instanceof OperationDefinitionNode) {
86
            switch ($appliedTo->getOperation()) {
87
                case 'query':
88
                    return DirectiveLocationEnum::QUERY;
89
                case 'mutation':
90
                    return DirectiveLocationEnum::MUTATION;
91
                case 'subscription':
92
                    return DirectiveLocationEnum::SUBSCRIPTION;
93
                default:
94
                    return null;
95
            }
96
        }
97
        if ($appliedTo instanceof FieldNode) {
98
            return DirectiveLocationEnum::FIELD;
99
        }
100
        if ($appliedTo instanceof FragmentSpreadNode) {
101
            return DirectiveLocationEnum::FRAGMENT_SPREAD;
102
        }
103
        if ($appliedTo instanceof InlineFragmentNode) {
104
            return DirectiveLocationEnum::INLINE_FRAGMENT;
105
        }
106
        if ($appliedTo instanceof FragmentDefinitionNode) {
107
            return DirectiveLocationEnum::FRAGMENT_DEFINITION;
108
        }
109
        if ($appliedTo instanceof SchemaDefinitionNode || $appliedTo instanceof SchemaExtensionNode) {
110
            return DirectiveLocationEnum::SCHEMA;
111
        }
112
        if ($appliedTo instanceof ScalarTypeDefinitionNode || $appliedTo instanceof ScalarTypeExtensionNode) {
113
            return DirectiveLocationEnum::SCALAR;
114
        }
115
        if ($appliedTo instanceof ObjectTypeDefinitionNode || $appliedTo instanceof ObjectTypeExtensionNode) {
116
            return DirectiveLocationEnum::OBJECT;
117
        }
118
        if ($appliedTo instanceof FieldDefinitionNode) {
119
            return DirectiveLocationEnum::FIELD_DEFINITION;
120
        }
121
        if ($appliedTo instanceof InterfaceTypeDefinitionNode || $appliedTo instanceof InterfaceTypeExtensionNode) {
122
            return DirectiveLocationEnum::INTERFACE;
123
        }
124
        if ($appliedTo instanceof UnionTypeDefinitionNode || $appliedTo instanceof UnionTypeExtensionNode) {
125
            return DirectiveLocationEnum::UNION;
126
        }
127
        if ($appliedTo instanceof EnumTypeDefinitionNode || $appliedTo instanceof EnumTypeExtensionNode) {
128
            return DirectiveLocationEnum::ENUM;
129
        }
130
        if ($appliedTo instanceof EnumValueDefinitionNode) {
131
            return DirectiveLocationEnum::ENUM_VALUE;
132
        }
133
        if ($appliedTo instanceof InputObjectTypeDefinitionNode || $appliedTo instanceof InputObjectTypeExtensionNode) {
134
            return DirectiveLocationEnum::INPUT_OBJECT;
135
        }
136
        if ($appliedTo instanceof InputValueDefinitionNode) {
137
            $parentNode = $node->getAncestor(2);
138
            return $parentNode instanceof InputObjectTypeDefinitionNode
139
                ? DirectiveLocationEnum::INPUT_FIELD_DEFINITION
140
                : DirectiveLocationEnum::ARGUMENT_DEFINITION;
141
        }
142
143
        return null;
144
    }
145
}
146