Passed
Push — master ( c6ed3e...c4773a )
by Christoffer
02:30
created

TypeInfo::pushDefaultValue()   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
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Digia\GraphQL\Util;
4
5
use Digia\GraphQL\Error\InvariantException;
6
use Digia\GraphQL\Language\Node\FieldNode;
7
use Digia\GraphQL\Schema\Schema;
8
use Digia\GraphQL\Type\Definition\Argument;
9
use Digia\GraphQL\Type\Definition\CompositeTypeInterface;
10
use Digia\GraphQL\Type\Definition\Directive;
11
use Digia\GraphQL\Type\Definition\EnumValue;
12
use Digia\GraphQL\Type\Definition\Field;
13
use Digia\GraphQL\Type\Definition\InputTypeInterface;
14
use Digia\GraphQL\Type\Definition\InterfaceType;
15
use Digia\GraphQL\Type\Definition\ObjectType;
16
use Digia\GraphQL\Type\Definition\OutputTypeInterface;
17
use Digia\GraphQL\Type\Definition\TypeInterface;
18
use function Digia\GraphQL\Type\SchemaMetaFieldDefinition;
19
use function Digia\GraphQL\Type\TypeMetaFieldDefinition;
20
use function Digia\GraphQL\Type\TypeNameMetaFieldDefinition;
21
22
class TypeInfo
23
{
24
    /**
25
     * @var Schema
26
     */
27
    protected $schema;
28
29
    /**
30
     * @var TypeInterface[]
31
     */
32
    protected $typeStack = [];
33
34
    /**
35
     * @var CompositeTypeInterface[]
36
     */
37
    protected $parentTypeStack = [];
38
39
    /**
40
     * @var TypeInterface[]
41
     */
42
    protected $inputTypeStack = [];
43
44
    /**
45
     * @var Field[]
46
     */
47
    protected $fieldDefinitionStack = [];
48
49
    /**
50
     * @var array
51
     */
52
    protected $defaultValueStack = [];
53
54
    /**
55
     * @var Directive
56
     */
57
    protected $directive;
58
59
    /**
60
     * @var Argument
61
     */
62
    protected $argument;
63
64
    /**
65
     * @var EnumValue
66
     */
67
    protected $enumValue;
68
69
    /**
70
     * @var callable|null
71
     */
72
    protected $getFieldDefinitionFunction;
73
74
    /**
75
     * TypeInfo constructor.
76
     * @param Schema             $schema
77
     * @param callable|null      $getFieldDefinitionFunction
78
     * @param TypeInterface|null $initialType
79
     */
80
    public function __construct(
81
        Schema $schema,
82
        ?callable $getFieldDefinitionFunction = null,
83
        ?TypeInterface $initialType = null
84
    ) {
85
        $this->schema                     = $schema;
86
        $this->getFieldDefinitionFunction = $getFieldDefinitionFunction ?? function (
87
                Schema $schema,
88
                TypeInterface $parentType,
89
                FieldNode $fieldNode
90
            ) {
91
                return getFieldDefinition($schema, $parentType, $fieldNode);
92
            };
93
94
        if ($initialType instanceof InputTypeInterface) {
95
            $this->inputTypeStack[] = $initialType;
96
        } elseif ($initialType instanceof CompositeTypeInterface) {
97
            $this->parentTypeStack[] = $initialType;
98
        } elseif ($initialType instanceof OutputTypeInterface) {
99
            $this->typeStack[] = $initialType;
100
        }
101
    }
102
103
    /**
104
     * @param Schema        $schema
105
     * @param TypeInterface $parentType
106
     * @param FieldNode     $fieldNode
107
     * @return Field|null
108
     */
109
    public function resolveFieldDefinition(
110
        Schema $schema,
111
        TypeInterface $parentType,
112
        FieldNode $fieldNode
113
    ): ?Field {
114
        return \call_user_func($this->getFieldDefinitionFunction, $schema, $parentType, $fieldNode);
115
    }
116
117
    /**
118
     * @param TypeInterface|null $type
119
     */
120
    public function pushType(?TypeInterface $type): void
121
    {
122
        $this->typeStack[] = $type;
123
    }
124
125
    /**
126
     *
127
     */
128
    public function popType(): void
129
    {
130
        \array_pop($this->typeStack);
131
    }
132
133
    /**
134
     * @return TypeInterface|TypeInterface|null
135
     */
136
    public function getType(): ?TypeInterface
137
    {
138
        return $this->getFromStack($this->typeStack, 1);
139
    }
140
141
    /**
142
     * @param CompositeTypeInterface|null $type
143
     */
144
    public function pushParentType(?CompositeTypeInterface $type): void
145
    {
146
        $this->parentTypeStack[] = $type;
147
    }
148
149
    /**
150
     *
151
     */
152
    public function popParentType(): void
153
    {
154
        \array_pop($this->parentTypeStack);
155
    }
156
157
    /**
158
     * @return CompositeTypeInterface|null
159
     */
160
    public function getParentType(): ?CompositeTypeInterface
161
    {
162
        return $this->getFromStack($this->parentTypeStack, 1);
163
    }
164
165
    /**
166
     * @param TypeInterface|null $type
167
     */
168
    public function pushInputType(?TypeInterface $type): void
169
    {
170
        $this->inputTypeStack[] = $type;
171
    }
172
173
    /**
174
     * 
175
     */
176
    public function popInputType(): void
177
    {
178
        \array_pop($this->inputTypeStack);
179
    }
180
181
    /**
182
     * @return TypeInterface|null
183
     */
184
    public function getInputType(): ?TypeInterface
185
    {
186
        return $this->getFromStack($this->inputTypeStack, 1);
187
    }
188
189
    /**
190
     * @return TypeInterface|null
191
     */
192
    public function getParentInputType(): ?TypeInterface
193
    {
194
        return $this->getFromStack($this->inputTypeStack, 2);
195
    }
196
197
    /**
198
     * @param Field|null $fieldDefinition
199
     */
200
    public function pushFieldDefinition(?Field $fieldDefinition): void
201
    {
202
        $this->fieldDefinitionStack[] = $fieldDefinition;
203
    }
204
205
    /**
206
     * 
207
     */
208
    public function popFieldDefinition(): void
209
    {
210
        \array_pop($this->fieldDefinitionStack);
211
    }
212
213
    /**
214
     * @return Field|null
215
     */
216
    public function getFieldDefinition(): ?Field
217
    {
218
        return $this->getFromStack($this->fieldDefinitionStack, 1);
219
    }
220
221
    /**
222
     * @return Schema
223
     */
224
    public function getSchema(): Schema
225
    {
226
        return $this->schema;
227
    }
228
229
    /**
230
     * @param mixed|null $defaultValue
231
     */
232
    public function pushDefaultValue($defaultValue): void
233
    {
234
        $this->defaultValueStack[] = $defaultValue;
235
    }
236
237
    /**
238
     *
239
     */
240
    public function popDefaultValue(): void
241
    {
242
        \array_pop($this->defaultValueStack);
243
    }
244
245
    /**
246
     * @return mixed|null
247
     */
248
    public function getDefaultValue()
249
    {
250
        return $this->getFromStack($this->defaultValueStack, 1);
251
    }
252
253
    /**
254
     * @return Directive|null
255
     */
256
    public function getDirective(): ?Directive
257
    {
258
        return $this->directive;
259
    }
260
261
    /**
262
     * @param Directive|null $directive
263
     */
264
    public function setDirective(?Directive $directive): void
265
    {
266
        $this->directive = $directive;
267
    }
268
269
    /**
270
     * @return Argument|null
271
     */
272
    public function getArgument(): ?Argument
273
    {
274
        return $this->argument;
275
    }
276
277
    /**
278
     * @param Argument|null $argument
279
     */
280
    public function setArgument(?Argument $argument): void
281
    {
282
        $this->argument = $argument;
283
    }
284
285
    /**
286
     * @return EnumValue|null
287
     */
288
    public function getEnumValue(): ?EnumValue
289
    {
290
        return $this->enumValue;
291
    }
292
293
    /**
294
     * @param EnumValue|null $enumValue
295
     */
296
    public function setEnumValue(?EnumValue $enumValue): void
297
    {
298
        $this->enumValue = $enumValue;
299
    }
300
301
    /**
302
     * @param array $stack
303
     * @param int   $depth
304
     * @return mixed|null
305
     */
306
    protected function getFromStack(array $stack, int $depth)
307
    {
308
        $count = \count($stack);
309
310
        return $count >= $depth ? $stack[$count - $depth] : null;
311
    }
312
}
313
314
/**
315
 * @param Schema        $schema
316
 * @param TypeInterface $parentType
317
 * @param FieldNode     $fieldNode
318
 * @return Field|null
319
 * @throws InvariantException
320
 */
321
function getFieldDefinition(Schema $schema, TypeInterface $parentType, FieldNode $fieldNode): ?Field
322
{
323
    $name = $fieldNode->getNameValue();
324
325
    $schemaDefinition = SchemaMetaFieldDefinition();
326
    if ($name === $schemaDefinition->getName() && $schema->getQueryType() === $parentType) {
327
        return $schemaDefinition;
328
    }
329
330
    $typeDefinition = TypeMetaFieldDefinition();
331
    if ($name === $typeDefinition->getName() && $schema->getQueryType() === $parentType) {
332
        return $typeDefinition;
333
    }
334
335
    $typeNameDefinition = TypeNameMetaFieldDefinition();
336
    if ($name === $typeNameDefinition->getName() && $parentType instanceof CompositeTypeInterface) {
337
        return $typeNameDefinition;
338
    }
339
340
    if ($parentType instanceof ObjectType || $parentType instanceof InterfaceType) {
341
        $fields = $parentType->getFields();
342
        if (isset($fields[$name])) {
343
            return $fields[$name];
344
        }
345
    }
346
347
    return null;
348
}
349