1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of Railt package. |
4
|
|
|
* |
5
|
|
|
* For the full copyright and license information, please view the LICENSE |
6
|
|
|
* file that was distributed with this source code. |
7
|
|
|
*/ |
8
|
|
|
declare(strict_types=1); |
9
|
|
|
|
10
|
|
|
namespace Railt\SDL\IR; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* @method static static|TypeInterface|Type scalar() |
14
|
|
|
* @method static static|TypeInterface|Type object() |
15
|
|
|
* @method static static|TypeInterface|Type directive() |
16
|
|
|
* @method static static|TypeInterface|Type directiveLocation() |
17
|
|
|
* @method static static|TypeInterface|Type interface() |
18
|
|
|
* @method static static|TypeInterface|Type union() |
19
|
|
|
* @method static static|TypeInterface|Type enum() |
20
|
|
|
* @method static static|TypeInterface|Type input() |
21
|
|
|
* @method static static|TypeInterface|Type inputUnion() |
22
|
|
|
* @method static static|TypeInterface|Type schema() |
23
|
|
|
* @method static static|TypeInterface|Type enumValue() |
24
|
|
|
* @method static static|TypeInterface|Type field() |
25
|
|
|
* @method static static|TypeInterface|Type argument() |
26
|
|
|
* @method static static|TypeInterface|Type inputField() |
27
|
|
|
* @method static static|TypeInterface|Type document() |
28
|
|
|
* @method static static|TypeInterface|Type any() |
29
|
|
|
*/ |
30
|
|
|
class Type implements TypeInterface |
31
|
|
|
{ |
32
|
|
|
/** |
33
|
|
|
* @var Type[] |
34
|
|
|
*/ |
35
|
|
|
private static $instances = []; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var array[]|string[][] |
39
|
|
|
*/ |
40
|
|
|
private static $inheritance = []; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @var string |
44
|
|
|
*/ |
45
|
|
|
protected $name; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @var array|string[] |
49
|
|
|
*/ |
50
|
|
|
private $parent; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* BaseType constructor. |
54
|
|
|
* @param string $name |
55
|
|
|
*/ |
56
|
|
|
private function __construct(string $name) |
57
|
|
|
{ |
58
|
|
|
\assert(self::isValid($name), 'Invalid type ' . $name); |
59
|
|
|
|
60
|
|
|
$this->name = $name; |
61
|
|
|
$this->parent = $this->getInheritanceSequence($name); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* @param string $name |
66
|
|
|
* @return array |
67
|
|
|
*/ |
68
|
|
|
private function getInheritanceSequence(string $name): array |
69
|
|
|
{ |
70
|
|
|
if (self::$inheritance === []) { |
71
|
|
|
$this->bootInheritance(new \SplStack(), static::INHERITANCE_TREE); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
return self::$inheritance[$name] ?? [static::ROOT_TYPE]; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @param \SplStack $stack |
79
|
|
|
* @param array $children |
80
|
|
|
*/ |
81
|
|
|
private function bootInheritance(\SplStack $stack, array $children = []): void |
82
|
|
|
{ |
83
|
|
|
$push = function (string $type) use ($stack): void { |
84
|
|
|
self::$inheritance[$type] = \array_values(\iterator_to_array($stack)); |
85
|
|
|
self::$inheritance[$type][] = static::ROOT_TYPE; |
86
|
|
|
|
87
|
|
|
$stack->push($type); |
88
|
|
|
}; |
89
|
|
|
|
90
|
|
|
foreach ($children as $type => $child) { |
91
|
|
|
switch (true) { |
92
|
|
|
case \is_string($child): |
93
|
|
|
$push($child); |
94
|
|
|
break; |
95
|
|
|
|
96
|
|
|
case \is_array($child): |
97
|
|
|
$push($type); |
98
|
|
|
$this->bootInheritance($stack, $child); |
99
|
|
|
break; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** @noinspection DisconnectedForeachInstructionInspection */ |
103
|
|
|
$stack->pop(); |
104
|
|
|
} |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @param string|ProvidesType $type |
109
|
|
|
* @return TypeInterface |
110
|
|
|
*/ |
111
|
|
|
public static function of($type): TypeInterface |
112
|
|
|
{ |
113
|
|
|
switch (true) { |
114
|
|
|
case \is_string($type): |
115
|
|
|
return self::$instances[$type] ?? (self::$instances[$type] = new static($type)); |
116
|
|
|
|
117
|
|
|
case $type instanceof TypeInterface: |
118
|
|
|
return $type; |
119
|
|
|
|
120
|
|
|
case $type instanceof ProvidesType: |
|
|
|
|
121
|
|
|
return $type->getType(); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
return static::of(static::ANY); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* {@inheritDoc} |
129
|
|
|
*/ |
130
|
|
|
public function isInputable(): bool |
131
|
|
|
{ |
132
|
|
|
return \in_array($this->name, static::ALLOWS_TO_INPUT, true); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* {@inheritDoc} |
137
|
|
|
*/ |
138
|
|
|
public function isReturnable(): bool |
139
|
|
|
{ |
140
|
|
|
return \in_array($this->name, static::ALLOWS_TO_OUTPUT, true); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* {@inheritDoc} |
145
|
|
|
*/ |
146
|
|
|
public function isDependent(): bool |
147
|
|
|
{ |
148
|
|
|
return \in_array($this->name, static::DEPENDENT_TYPES, true); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* {@inheritDoc} |
153
|
|
|
*/ |
154
|
|
|
public function instanceOf(TypeInterface $type): bool |
155
|
|
|
{ |
156
|
|
|
$needle = $type->getName(); |
157
|
|
|
|
158
|
|
|
return $this->is($needle) || \in_array($needle, $this->parent, true); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* {@inheritDoc} |
163
|
|
|
*/ |
164
|
|
|
public function is(string $type): bool |
165
|
|
|
{ |
166
|
|
|
return $this->getName() === $type; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* {@inheritDoc} |
171
|
|
|
*/ |
172
|
|
|
public function getName(): string |
173
|
|
|
{ |
174
|
|
|
return $this->name; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* {@inheritDoc} |
179
|
|
|
*/ |
180
|
|
|
public function __toString(): string |
181
|
|
|
{ |
182
|
|
|
return $this->getName(); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* {@inheritDoc} |
187
|
|
|
*/ |
188
|
|
|
public static function isValid(string $name): bool |
189
|
|
|
{ |
190
|
|
|
return \in_array($name, static::all(), true); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* @param string $name |
195
|
|
|
* @param array $arguments |
196
|
|
|
* @return TypeInterface |
197
|
|
|
*/ |
198
|
|
|
public static function __callStatic(string $name, array $arguments = []) |
199
|
|
|
{ |
200
|
|
|
foreach (static::all() as $type) { |
201
|
|
|
if (\strtolower($type) === \strtolower($name)) { |
202
|
|
|
return static::of($type); |
203
|
|
|
} |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
return static::of(static::ANY); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* @return array |
211
|
|
|
*/ |
212
|
|
|
public static function all(): array |
213
|
|
|
{ |
214
|
|
|
return \array_merge(static::DEPENDENT_TYPES, static::ROOT_TYPES); |
215
|
|
|
} |
216
|
|
|
} |
217
|
|
|
|
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.