1 | <?php |
||||
2 | declare(strict_types=1); |
||||
3 | namespace Thunder\Platenum\Enum; |
||||
4 | |||||
5 | use Thunder\Platenum\Exception\PlatenumException; |
||||
6 | |||||
7 | /** |
||||
8 | * @template TMember |
||||
9 | * @template TValue |
||||
10 | * |
||||
11 | * @author Tomasz Kowalczyk <[email protected]> |
||||
12 | */ |
||||
13 | trait EnumTrait |
||||
14 | { |
||||
15 | /** @var TMember */ |
||||
0 ignored issues
–
show
|
|||||
16 | private $member; |
||||
17 | /** @var TValue */ |
||||
0 ignored issues
–
show
The type
Thunder\Platenum\Enum\TValue was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||
18 | private $value; |
||||
19 | |||||
20 | /** @var non-empty-array<string,non-empty-array<string,int|string>> */ |
||||
0 ignored issues
–
show
|
|||||
21 | protected static $members = []; |
||||
22 | /** @var array<string,array<string,static>> */ |
||||
23 | 26 | protected static $instances = []; |
|||
24 | |||||
25 | 26 | ||||
26 | 26 | /** |
|||
27 | 26 | * @param TMember $member |
|||
28 | * @param TValue $value |
||||
29 | */ |
||||
30 | /* final */ private function __construct(string $member, $value) |
||||
31 | 38 | { |
|||
32 | $this->member = $member; |
||||
0 ignored issues
–
show
It seems like
$member of type string is incompatible with the declared type Thunder\Platenum\Enum\TMember of property $member .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
33 | 38 | $this->value = $value; |
|||
34 | 38 | } |
|||
35 | 1 | ||||
36 | /* --- CREATE --- */ |
||||
37 | |||||
38 | 37 | final public static function __callStatic(string $member, array $arguments) |
|||
39 | { |
||||
40 | $class = static::class; |
||||
41 | 45 | if($arguments) { |
|||
0 ignored issues
–
show
The expression
$arguments of type array 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 ![]() |
|||||
42 | throw PlatenumException::fromConstantArguments($class); |
||||
43 | 45 | } |
|||
44 | 45 | ||||
45 | 9 | return static::fromMember($member); |
|||
46 | } |
||||
47 | |||||
48 | 44 | final public static function fromMember(string $member): self |
|||
49 | 36 | { |
|||
50 | 10 | $class = static::class; |
|||
51 | 6 | if(isset(static::$instances[$class][$member])) { |
|||
52 | return static::$instances[$class][$member]; |
||||
53 | } |
||||
54 | |||||
55 | 26 | static::resolveMembers(); |
|||
56 | if(false === array_key_exists($member, static::$members[$class])) { |
||||
57 | static::throwInvalidMemberException($member); |
||||
58 | static::throwDefaultInvalidMemberException($member); |
||||
59 | } |
||||
60 | |||||
61 | /** @psalm-suppress UnsafeInstantiation,ArgumentTypeCoercion,PropertyTypeCoercion */ |
||||
62 | 14 | return static::$instances[$class][$member] = new static($member, static::$members[$class][$member]); |
|||
63 | } |
||||
64 | 14 | ||||
65 | 14 | /** |
|||
66 | 1 | * @param mixed $value |
|||
67 | * @return static |
||||
68 | */ |
||||
69 | 13 | final public static function fromValue($value): self |
|||
70 | 11 | { |
|||
71 | 11 | $class = static::class; |
|||
72 | 5 | if(false === is_scalar($value)) { |
|||
73 | 3 | throw PlatenumException::fromIllegalValue($class, $value); |
|||
74 | } |
||||
75 | |||||
76 | static::resolveMembers(); |
||||
77 | 6 | $member = array_search($value, static::$members[$class], true); |
|||
78 | if(false === $member) { |
||||
79 | static::throwInvalidValueException($value); |
||||
80 | static::throwDefaultInvalidValueException($value); |
||||
81 | } |
||||
82 | |||||
83 | /** @var string $member */ |
||||
84 | 4 | return static::fromMember($member); |
|||
85 | } |
||||
86 | 4 | ||||
87 | 2 | /** |
|||
88 | * @param static $enum |
||||
89 | * @return static |
||||
90 | 2 | */ |
|||
91 | final public static function fromEnum($enum): self |
||||
92 | { |
||||
93 | if(false === $enum instanceof static) { |
||||
94 | throw PlatenumException::fromMismatchedClass(static::class, \get_class($enum)); |
||||
95 | } |
||||
96 | |||||
97 | 2 | return static::fromValue($enum->value); |
|||
98 | } |
||||
99 | 2 | ||||
100 | 1 | /** |
|||
101 | * @psalm-suppress ReferenceConstraintViolation |
||||
102 | * @param static $enum |
||||
103 | * @param-out AbstractConstantsEnum|AbstractDocblockEnum|AbstractStaticEnum|AbstractCallbackEnum|AbstractAttributeEnum $enum |
||||
104 | 3 | */ |
|||
105 | final public function fromInstance(&$enum): void |
||||
106 | 3 | { |
|||
107 | $enum = static::fromEnum($enum); |
||||
108 | 9 | } |
|||
109 | |||||
110 | 9 | /** |
|||
111 | * @psalm-suppress UnusedForeachValue |
||||
112 | * @return list<static> |
||||
0 ignored issues
–
show
The type
Thunder\Platenum\Enum\list was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||
113 | */ |
||||
114 | 2 | final public static function getInstances(): array |
|||
115 | { |
||||
116 | 2 | static::resolveMembers(); |
|||
117 | foreach(static::$members[static::class] as $member => $value) { |
||||
118 | static::fromMember($member); |
||||
119 | 6 | } |
|||
120 | |||||
121 | 6 | return array_values(static::$instances[static::class]); |
|||
0 ignored issues
–
show
|
|||||
122 | } |
||||
123 | |||||
124 | /* --- EXCEPTIONS --- */ |
||||
125 | |||||
126 | /** @psalm-suppress UnusedParam */ |
||||
127 | 3 | private static function throwInvalidMemberException(string $member): void |
|||
0 ignored issues
–
show
The parameter
$member is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
128 | { |
||||
129 | 3 | } |
|||
130 | |||||
131 | private static function throwDefaultInvalidMemberException(string $member): void |
||||
132 | { |
||||
133 | throw PlatenumException::fromInvalidMember(static::class, $member, static::$members[static::class]); |
||||
134 | 6 | } |
|||
135 | |||||
136 | 6 | /** |
|||
137 | * @param mixed $value |
||||
138 | * @psalm-suppress UnusedParam |
||||
139 | */ |
||||
140 | 9 | private static function throwInvalidValueException($value): void |
|||
0 ignored issues
–
show
The parameter
$value is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
141 | { |
||||
142 | 9 | } |
|||
143 | |||||
144 | /** @param mixed $value */ |
||||
145 | 1 | private static function throwDefaultInvalidValueException($value): void |
|||
146 | { |
||||
147 | 1 | throw PlatenumException::fromInvalidValue(static::class, $value); |
|||
148 | } |
||||
149 | |||||
150 | 1 | /* --- COMPARE --- */ |
|||
151 | |||||
152 | 1 | /** @param static $other */ |
|||
153 | final public function equals($other): bool |
||||
154 | { |
||||
155 | return $other instanceof $this && $this->value === $other->value; |
||||
156 | } |
||||
157 | 8 | ||||
158 | /* --- TRANSFORM --- */ |
||||
159 | 8 | ||||
160 | /** @return TMember */ |
||||
161 | 7 | final public function getMember(): string |
|||
162 | { |
||||
163 | return $this->member; |
||||
164 | } |
||||
165 | 8 | ||||
166 | /** @return TValue */ |
||||
167 | 8 | final public function getValue() |
|||
168 | { |
||||
169 | 8 | return $this->value; |
|||
170 | } |
||||
171 | |||||
172 | 1 | /** @psalm-suppress MissingReturnType */ |
|||
173 | #[\ReturnTypeWillChange] |
||||
174 | 1 | final public function jsonSerialize() |
|||
175 | { |
||||
176 | return $this->getValue(); |
||||
177 | } |
||||
178 | 1 | ||||
179 | final public function __toString(): string |
||||
180 | 1 | { |
|||
181 | return (string)$this->getValue(); |
||||
182 | } |
||||
183 | |||||
184 | /* --- CHECK --- */ |
||||
185 | |||||
186 | 6 | final public static function memberExists(string $member): bool |
|||
187 | { |
||||
188 | 6 | static::resolveMembers(); |
|||
189 | 5 | ||||
190 | 3 | return array_key_exists($member, static::$members[static::class]); |
|||
191 | } |
||||
192 | |||||
193 | 1 | /** @param int|string $value */ |
|||
194 | final public static function valueExists($value): bool |
||||
195 | { |
||||
196 | static::resolveMembers(); |
||||
197 | 7 | ||||
198 | return \in_array($value, static::$members[static::class], true); |
||||
199 | 7 | } |
|||
200 | 5 | ||||
201 | 3 | /** @param list<string> $members */ |
|||
202 | final public static function membersExist(array $members): bool |
||||
203 | { |
||||
204 | 2 | static::resolveMembers(); |
|||
205 | |||||
206 | return [] !== array_intersect(array_keys(static::$members[static::class]), $members); |
||||
207 | 1 | } |
|||
208 | |||||
209 | 1 | /** @param list<int|string> $values */ |
|||
210 | final public static function valuesExist(array $values): bool |
||||
211 | 1 | { |
|||
212 | static::resolveMembers(); |
||||
213 | |||||
214 | 1 | return [] !== array_intersect(static::$members[static::class], $values); |
|||
215 | } |
||||
216 | 1 | ||||
217 | /** @param TMember $member */ |
||||
218 | 1 | final public function hasMember(string $member): bool |
|||
219 | { |
||||
220 | return $member === $this->member; |
||||
221 | 5 | } |
|||
222 | |||||
223 | 5 | /** @param TValue $value */ |
|||
224 | final public function hasValue($value): bool |
||||
225 | 5 | { |
|||
226 | return $value === $this->value; |
||||
227 | } |
||||
228 | |||||
229 | /** @param list<TMember> $members */ |
||||
230 | 74 | final public function hasMemberIn(array $members): bool |
|||
231 | { |
||||
232 | 74 | return in_array($this->member, $members, true); |
|||
233 | 74 | } |
|||
234 | 15 | ||||
235 | /** @param list<TValue> $values */ |
||||
236 | final public function hasValueIn(array $values): bool |
||||
237 | 73 | { |
|||
238 | 1 | return in_array($this->value, $values, true); |
|||
239 | 73 | } |
|||
240 | |||||
241 | /** @param list<static> $enums */ |
||||
242 | 73 | final public function isIn(array $enums): bool |
|||
243 | { |
||||
244 | 73 | return in_array($this, $enums, true); |
|||
245 | 66 | } |
|||
246 | 1 | ||||
247 | final public static function isMemberWarm(string $member): bool |
||||
248 | 65 | { |
|||
249 | 1 | return self::memberExists($member) |
|||
250 | && array_key_exists(static::class, static::$instances) |
||||
251 | && array_key_exists($member, static::$instances[static::class]); |
||||
252 | 64 | } |
|||
253 | 1 | ||||
254 | /* --- INFO --- */ |
||||
255 | 63 | ||||
256 | 1 | /** @return int|string */ |
|||
257 | final public static function memberToValue(string $member) |
||||
258 | { |
||||
259 | 62 | if(false === static::memberExists($member)) { |
|||
260 | 62 | static::throwInvalidMemberException($member); |
|||
261 | static::throwDefaultInvalidMemberException($member); |
||||
262 | } |
||||
263 | |||||
264 | 1 | return static::$members[static::class][$member]; |
|||
265 | } |
||||
266 | 1 | ||||
267 | /** @param int|string $value */ |
||||
268 | final public static function valueToMember($value): string |
||||
269 | 1 | { |
|||
270 | if(false === static::valueExists($value)) { |
||||
271 | 1 | static::throwInvalidValueException($value); |
|||
272 | static::throwDefaultInvalidValueException($value); |
||||
273 | } |
||||
274 | 1 | ||||
275 | return (string)array_search($value, static::$members[static::class], true); |
||||
276 | 1 | } |
|||
277 | |||||
278 | final public static function getMembers(): array |
||||
279 | { |
||||
280 | 1 | static::resolveMembers(); |
|||
281 | |||||
282 | 1 | return array_keys(static::$members[static::class]); |
|||
283 | } |
||||
284 | |||||
285 | final public static function getValues(): array |
||||
286 | 1 | { |
|||
287 | static::resolveMembers(); |
||||
288 | 1 | ||||
289 | return array_values(static::$members[static::class]); |
||||
290 | } |
||||
291 | |||||
292 | 1 | final public static function getMembersAndValues(): array |
|||
293 | { |
||||
294 | 1 | static::resolveMembers(); |
|||
295 | |||||
296 | return static::$members[static::class]; |
||||
297 | 1 | } |
|||
298 | |||||
299 | 1 | /* --- SOURCE --- */ |
|||
300 | |||||
301 | private static function resolveMembers(): void |
||||
302 | { |
||||
303 | $class = static::class; |
||||
304 | if(isset(static::$members[$class])) { |
||||
305 | return; |
||||
306 | } |
||||
307 | |||||
308 | $throwMissingResolve = function(string $class): void { |
||||
309 | throw PlatenumException::fromMissingResolve($class); |
||||
310 | }; |
||||
311 | // reflection instead of method_exists because of PHP 7.4 bug #78632 |
||||
312 | // @see https://bugs.php.net/bug.php?id=78632 |
||||
313 | $hasResolve = (new \ReflectionClass($class))->hasMethod('resolve'); |
||||
314 | /** @var array<string,int|string> $members */ |
||||
315 | $members = $hasResolve ? static::resolve() : $throwMissingResolve($class); |
||||
0 ignored issues
–
show
The method
resolve() does not exist on Thunder\Platenum\Enum\EnumTrait . Since you implemented __callStatic , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
316 | if(empty($members)) { |
||||
317 | throw PlatenumException::fromEmptyMembers($class); |
||||
318 | } |
||||
319 | if(\count($members) !== \count(\array_unique($members))) { |
||||
320 | throw PlatenumException::fromNonUniqueMembers($class); |
||||
321 | } |
||||
322 | if(['string'] !== \array_unique(\array_map('gettype', array_keys($members)))) { |
||||
323 | throw PlatenumException::fromNonStringMembers($class); |
||||
324 | } |
||||
325 | if(1 !== \count(\array_unique(\array_map('gettype', $members)))) { |
||||
326 | throw PlatenumException::fromNonUniformMemberValues($class, $members); |
||||
327 | } |
||||
328 | |||||
329 | static::$members[$class] = $members; |
||||
330 | } |
||||
331 | |||||
332 | /* --- MAGIC --- */ |
||||
333 | |||||
334 | final public function __clone() |
||||
335 | { |
||||
336 | throw PlatenumException::fromMagicMethod(static::class, __FUNCTION__); |
||||
337 | } |
||||
338 | |||||
339 | final public function __call(string $name, array $arguments) |
||||
340 | { |
||||
341 | throw PlatenumException::fromMagicMethod(static::class, __FUNCTION__); |
||||
342 | } |
||||
343 | |||||
344 | final public function __invoke() |
||||
345 | { |
||||
346 | throw PlatenumException::fromMagicMethod(static::class, __FUNCTION__); |
||||
347 | } |
||||
348 | |||||
349 | /** @param mixed $name */ |
||||
350 | final public function __isset($name) |
||||
351 | { |
||||
352 | throw PlatenumException::fromMagicMethod(static::class, __FUNCTION__); |
||||
353 | } |
||||
354 | |||||
355 | /** @param mixed $name */ |
||||
356 | final public function __unset($name) |
||||
357 | { |
||||
358 | throw PlatenumException::fromMagicMethod(static::class, __FUNCTION__); |
||||
359 | } |
||||
360 | |||||
361 | /** @param mixed $value */ |
||||
362 | final public function __set(string $name, $value) |
||||
363 | { |
||||
364 | throw PlatenumException::fromMagicMethod(static::class, __FUNCTION__); |
||||
365 | } |
||||
366 | |||||
367 | final public function __get(string $name) |
||||
368 | { |
||||
369 | throw PlatenumException::fromMagicMethod(static::class, __FUNCTION__); |
||||
370 | } |
||||
371 | } |
||||
372 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths