GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

ValidationContext::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 8
ccs 7
cts 7
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Validator;
6
7
use GraphQL\Error\InvariantViolation;
8
use GraphQL\Language\AST\DocumentNode;
9
use GraphQL\Language\AST\FieldNode;
10
use GraphQL\Language\AST\FragmentDefinitionNode;
11
use GraphQL\Language\AST\FragmentSpreadNode;
12
use GraphQL\Language\AST\HasSelectionSet;
13
use GraphQL\Language\AST\InlineFragmentNode;
14
use GraphQL\Language\AST\NodeKind;
15
use GraphQL\Language\AST\OperationDefinitionNode;
16
use GraphQL\Language\AST\SelectionSetNode;
17
use GraphQL\Language\AST\VariableNode;
18
use GraphQL\Language\Visitor;
19
use GraphQL\Type\Definition\CompositeType;
20
use GraphQL\Type\Definition\EnumType;
21
use GraphQL\Type\Definition\FieldDefinition;
22
use GraphQL\Type\Definition\InputObjectType;
23
use GraphQL\Type\Definition\InputType;
24
use GraphQL\Type\Definition\ListOfType;
25
use GraphQL\Type\Definition\NonNull;
26
use GraphQL\Type\Definition\OutputType;
27
use GraphQL\Type\Definition\ScalarType;
28
use GraphQL\Type\Definition\Type;
29
use GraphQL\Type\Schema;
30
use GraphQL\Utils\TypeInfo;
31
use SplObjectStorage;
32
use function array_pop;
33
use function call_user_func_array;
34
use function count;
35
36
/**
37
 * An instance of this class is passed as the "this" context to all validators,
38
 * allowing access to commonly useful contextual information from within a
39
 * validation rule.
40
 */
41
class ValidationContext extends ASTValidationContext
42
{
43
    /** @var TypeInfo */
44
    private $typeInfo;
45
46
    /** @var FragmentDefinitionNode[] */
47
    private $fragments;
48
49
    /** @var SplObjectStorage */
50
    private $fragmentSpreads;
51
52
    /** @var SplObjectStorage */
53
    private $recursivelyReferencedFragments;
54
55
    /** @var SplObjectStorage */
56
    private $variableUsages;
57
58
    /** @var SplObjectStorage */
59
    private $recursiveVariableUsages;
60
61 533
    public function __construct(Schema $schema, DocumentNode $ast, TypeInfo $typeInfo)
62
    {
63 533
        parent::__construct($ast, $schema);
64 533
        $this->typeInfo                       = $typeInfo;
65 533
        $this->fragmentSpreads                = new SplObjectStorage();
66 533
        $this->recursivelyReferencedFragments = new SplObjectStorage();
67 533
        $this->variableUsages                 = new SplObjectStorage();
68 533
        $this->recursiveVariableUsages        = new SplObjectStorage();
69 533
    }
70
71
    /**
72
     * @return mixed[][] List of ['node' => VariableNode, 'type' => ?InputObjectType]
73
     */
74 170
    public function getRecursiveVariableUsages(OperationDefinitionNode $operation)
75
    {
76 170
        $usages = $this->recursiveVariableUsages[$operation] ?? null;
77
78 170
        if ($usages === null) {
79 170
            $usages    = $this->getVariableUsages($operation);
80 170
            $fragments = $this->getRecursivelyReferencedFragments($operation);
81
82 170
            $tmp = [$usages];
83 170
            foreach ($fragments as $i => $fragment) {
84 35
                $tmp[] = $this->getVariableUsages($fragments[$i]);
85
            }
86 170
            $usages                                    = call_user_func_array('array_merge', $tmp);
87 170
            $this->recursiveVariableUsages[$operation] = $usages;
88
        }
89
90 170
        return $usages;
91
    }
92
93
    /**
94
     * @return mixed[][] List of ['node' => VariableNode, 'type' => ?InputObjectType]
95
     */
96 170
    private function getVariableUsages(HasSelectionSet $node)
97
    {
98 170
        $usages = $this->variableUsages[$node] ?? null;
99
100 170
        if ($usages === null) {
101 170
            $newUsages = [];
102 170
            $typeInfo  = new TypeInfo($this->schema);
103 170
            Visitor::visit(
104 170
                $node,
105 170
                Visitor::visitWithTypeInfo(
106 170
                    $typeInfo,
107
                    [
108
                        NodeKind::VARIABLE_DEFINITION => static function () {
109 62
                            return false;
110 170
                        },
111
                        NodeKind::VARIABLE            => static function (VariableNode $variable) use (
112 64
                            &$newUsages,
113 64
                            $typeInfo
114
                        ) {
115 64
                            $newUsages[] = [
116 64
                                'node' => $variable,
117 64
                                'type' => $typeInfo->getInputType(),
118 64
                                'defaultValue' => $typeInfo->getDefaultValue(),
119
                            ];
120 170
                        },
121
                    ]
122
                )
123
            );
124 170
            $usages                      = $newUsages;
125 170
            $this->variableUsages[$node] = $usages;
126
        }
127
128 170
        return $usages;
129
    }
130
131
    /**
132
     * @return FragmentDefinitionNode[]
133
     */
134 175
    public function getRecursivelyReferencedFragments(OperationDefinitionNode $operation)
135
    {
136 175
        $fragments = $this->recursivelyReferencedFragments[$operation] ?? null;
137
138 175
        if ($fragments === null) {
139 175
            $fragments      = [];
140 175
            $collectedNames = [];
141 175
            $nodesToVisit   = [$operation];
142 175
            while (! empty($nodesToVisit)) {
143 175
                $node    = array_pop($nodesToVisit);
144 175
                $spreads = $this->getFragmentSpreads($node);
145 175
                foreach ($spreads as $spread) {
146 40
                    $fragName = $spread->name->value;
147
148 40
                    if (! empty($collectedNames[$fragName])) {
149 7
                        continue;
150
                    }
151
152 40
                    $collectedNames[$fragName] = true;
153 40
                    $fragment                  = $this->getFragment($fragName);
154 40
                    if (! $fragment) {
155 1
                        continue;
156
                    }
157
158 39
                    $fragments[]    = $fragment;
159 39
                    $nodesToVisit[] = $fragment;
160
                }
161
            }
162 175
            $this->recursivelyReferencedFragments[$operation] = $fragments;
163
        }
164
165 175
        return $fragments;
166
    }
167
168
    /**
169
     * @param OperationDefinitionNode|FragmentDefinitionNode $node
170
     *
171
     * @return FragmentSpreadNode[]
172
     */
173 191
    public function getFragmentSpreads(HasSelectionSet $node) : array
174
    {
175 191
        $spreads = $this->fragmentSpreads[$node] ?? null;
176 191
        if ($spreads === null) {
177 191
            $spreads = [];
178
            /** @var SelectionSetNode[] $setsToVisit */
179 191
            $setsToVisit = [$node->selectionSet];
180 191
            while (! empty($setsToVisit)) {
181 191
                $set = array_pop($setsToVisit);
182
183 191
                for ($i = 0, $selectionCount = count($set->selections); $i < $selectionCount; $i++) {
184 191
                    $selection = $set->selections[$i];
185 191
                    if ($selection instanceof FragmentSpreadNode) {
186 55
                        $spreads[] = $selection;
187 183
                    } elseif ($selection instanceof FieldNode || $selection instanceof InlineFragmentNode) {
188 183
                        if ($selection->selectionSet) {
189 183
                            $setsToVisit[] = $selection->selectionSet;
190
                        }
191
                    } else {
192
                        throw InvariantViolation::shouldNotHappen();
193
                    }
194
                }
195
            }
196 191
            $this->fragmentSpreads[$node] = $spreads;
197
        }
198
199 191
        return $spreads;
200
    }
201
202
    /**
203
     * @param string $name
204
     *
205
     * @return FragmentDefinitionNode|null
206
     */
207 86
    public function getFragment($name)
208
    {
209 86
        $fragments = $this->fragments;
210 86
        if (! $fragments) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $fragments of type GraphQL\Language\AST\FragmentDefinitionNode[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
211 86
            $fragments = [];
212 86
            foreach ($this->getDocument()->definitions as $statement) {
213 86
                if (! ($statement instanceof FragmentDefinitionNode)) {
214 51
                    continue;
215
                }
216
217 86
                $fragments[$statement->name->value] = $statement;
218
            }
219 86
            $this->fragments = $fragments;
220
        }
221
222 86
        return $fragments[$name] ?? null;
223
    }
224
225 132
    public function getType() : ?OutputType
226
    {
227 132
        return $this->typeInfo->getType();
228
    }
229
230
    /**
231
     * @return (CompositeType & Type) | null
0 ignored issues
show
Documentation Bug introduced by
The doc comment (CompositeType at position 1 could not be parsed: Expected ')' at position 1, but found 'CompositeType'.
Loading history...
232
     */
233 225
    public function getParentType() : ?CompositeType
234
    {
235 225
        return $this->typeInfo->getParentType();
236
    }
237
238
    /**
239
     * @return (Type & InputType) | null
0 ignored issues
show
Documentation Bug introduced by
The doc comment (Type at position 1 could not be parsed: Expected ')' at position 1, but found 'Type'.
Loading history...
240
     */
241 119
    public function getInputType() : ?InputType
242
    {
243 119
        return $this->typeInfo->getInputType();
244
    }
245
246
    /**
247
     * @return ScalarType|EnumType|InputObjectType|ListOfType|NonNull
248
     */
249 19
    public function getParentInputType() : ?InputType
250
    {
251 19
        return $this->typeInfo->getParentInputType();
252
    }
253
254
    /**
255
     * @return FieldDefinition
256
     */
257 160
    public function getFieldDef()
258
    {
259 160
        return $this->typeInfo->getFieldDef();
260
    }
261
262 5
    public function getDirective()
263
    {
264 5
        return $this->typeInfo->getDirective();
265
    }
266
267 107
    public function getArgument()
268
    {
269 107
        return $this->typeInfo->getArgument();
270
    }
271
}
272