Completed
Pull Request — master (#38)
by Christoffer
02:27
created

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