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

ValidationContext::getDirective()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Digia\GraphQL\Validation;
4
5
use Digia\GraphQL\Error\ValidationException;
6
use Digia\GraphQL\Language\AST\Node\DocumentNode;
7
use Digia\GraphQL\Language\AST\Node\FieldNode;
8
use Digia\GraphQL\Language\AST\Node\FragmentDefinitionNode;
9
use Digia\GraphQL\Language\AST\Node\FragmentSpreadNode;
10
use Digia\GraphQL\Language\AST\Node\SelectionNodeInterface;
11
use Digia\GraphQL\Language\AST\Node\SelectionSetNode;
12
use Digia\GraphQL\Type\Definition\Argument;
13
use Digia\GraphQL\Type\Definition\Directive;
14
use Digia\GraphQL\Type\Definition\Field;
15
use Digia\GraphQL\Type\Definition\TypeInterface;
16
use Digia\GraphQL\Type\SchemaInterface;
17
use Digia\GraphQL\Util\TypeInfo;
18
19
class ValidationContext
20
{
21
    /**
22
     * @var SchemaInterface
23
     */
24
    protected $schema;
25
26
    /**
27
     * @var DocumentNode
28
     */
29
    protected $documentNode;
30
31
    /**
32
     * @var TypeInfo
33
     */
34
    protected $typeInfo;
35
36
    /**
37
     * @var array|ValidationException[]
38
     */
39
    protected $errors = [];
40
41
    /**
42
     * @var array|FragmentDefinitionNode[]
43
     */
44
    protected $fragments = [];
45
46
    /**
47
     * @var array
48
     */
49
    protected $fragmentSpreads = [];
50
51
    /**
52
     * ValidationContext constructor.
53
     * @param SchemaInterface $schema
54
     * @param DocumentNode    $documentNode
55
     * @param TypeInfo        $typeInfo
56
     */
57
    public function __construct(SchemaInterface $schema, DocumentNode $documentNode, TypeInfo $typeInfo)
58
    {
59
        $this->schema       = $schema;
60
        $this->documentNode = $documentNode;
61
        $this->typeInfo     = $typeInfo;
62
    }
63
64
    /**
65
     * @param ValidationException $error
66
     */
67
    public function reportError(ValidationException $error): void
68
    {
69
        $this->errors[] = $error;
70
    }
71
72
    /**
73
     * @return array|ValidationException[]
74
     */
75
    public function getErrors(): array
76
    {
77
        return $this->errors;
78
    }
79
80
    /**
81
     * @return TypeInterface|null
82
     */
83
    public function getParentType(): ?TypeInterface
84
    {
85
        return $this->typeInfo->getParentType();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->typeInfo->getParentType() could return the type Digia\GraphQL\Type\Defin...\CompositeTypeInterface which is incompatible with the type-hinted return null|Digia\GraphQL\Type\Definition\TypeInterface. Consider adding an additional type-check to rule them out.
Loading history...
86
    }
87
88
    /**
89
     * @return Field|null
90
     */
91
    public function getFieldDefinition(): ?Field
92
    {
93
        return $this->typeInfo->getFieldDefinition();
94
    }
95
96
    /**
97
     * @return SchemaInterface
98
     */
99
    public function getSchema(): SchemaInterface
100
    {
101
        return $this->schema;
102
    }
103
104
    /**
105
     * @return Argument|null
106
     */
107
    public function getArgument(): ?Argument
108
    {
109
        return $this->typeInfo->getArgument();
110
    }
111
112
    /**
113
     * @return Directive|null
114
     */
115
    public function getDirective(): ?Directive
116
    {
117
        return $this->typeInfo->getDirective();
118
    }
119
120
    /**
121
     * @param string $name
122
     * @return FragmentDefinitionNode|null
123
     */
124
    public function getFragment(string $name): ?FragmentDefinitionNode
125
    {
126
        if (empty($this->fragments)) {
127
            $this->fragments = array_reduce($this->documentNode->getDefinitions(), function ($fragments, $definition) {
128
                if ($definition instanceof FragmentDefinitionNode) {
129
                    $fragments[$definition->getNameValue()] = $definition;
130
                }
131
                return $fragments;
132
            }, []);
133
        }
134
135
        return $this->fragments[$name] ?? null;
136
    }
137
138
    /**
139
     * @param SelectionSetNode $selectionSet
140
     * @return array|FragmentSpreadNode[]
141
     */
142
    public function getFragmentSpreads(SelectionSetNode $selectionSet): array
143
    {
144
        $spreads = $this->fragmentSpreads[(string)$selectionSet] ?? null;
145
146
        if (null === $spreads) {
147
            $spreads = [];
148
149
            $setsToVisit = [$selectionSet];
150
151
            while (!empty($setsToVisit)) {
152
                /** @var SelectionSetNode $set */
153
                $set = array_pop($setsToVisit);
154
155
                /** @var FieldNode $selection */
156
                foreach ($set->getSelections() as $selection) {
157
                    if ($selection instanceof FragmentSpreadNode) {
158
                        $spreads[] = $selection;
159
                    } elseif ($selection->hasSelectionSet()) {
160
                        $setsToVisit[] = $selection->getSelectionSet();
161
                    }
162
                }
163
            }
164
165
            $this->fragmentSpreads[(string)$selectionSet] = $spreads;
166
        }
167
168
        return $spreads;
169
    }
170
}
171