1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Part of SplTypes package. |
||
5 | * |
||
6 | * (c) Adrien Loyant <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | declare(strict_types=1); |
||
13 | |||
14 | namespace Ducks\Component\SplTypes; |
||
15 | |||
16 | use Ducks\Component\SplTypes\Reflection\SplReflectionEnumBackedCase; |
||
17 | |||
18 | /** |
||
19 | * Simplify SplBackedEnum integration |
||
20 | * |
||
21 | * @template T |
||
22 | * |
||
23 | * @property-read mixed $value |
||
24 | * |
||
25 | * @phpstan-require-implements SplBackedEnum |
||
26 | */ |
||
27 | trait SplBackedEnumTrait |
||
28 | { |
||
29 | use SplUnitEnumTrait; |
||
30 | |||
31 | /** |
||
32 | * Maps a scalar to an enum instance. |
||
33 | * |
||
34 | * @param int|string $value The scalar value to map to an enum case. |
||
35 | * |
||
36 | * @return static A case instance of this enumeration. |
||
37 | * |
||
38 | * @throws \ValueError if $value is not a valid backing value for enum |
||
39 | */ |
||
40 | final public static function from($value): self |
||
41 | { |
||
42 | $case = static::tryFrom($value); |
||
43 | |||
44 | if (null === $case) { |
||
45 | throw new \ValueError( |
||
46 | sprintf('%s is not a valid backing value for enum "%s"', \json_encode($value), static::class) |
||
47 | ); |
||
48 | } |
||
49 | |||
50 | return $case; |
||
51 | } |
||
52 | |||
53 | /** |
||
54 | * Maps a scalar to an enum instance or null. |
||
55 | * |
||
56 | * @param int|string|mixed $value e scalar value to map to an enum case. |
||
57 | * |
||
58 | * @return static|null A case instance of this enumeration, or null if not found. |
||
59 | * |
||
60 | * @psalm-suppress UnusedVariable |
||
61 | */ |
||
62 | final public static function tryFrom($value): ?self |
||
63 | { |
||
64 | foreach (static::cases() as $case) { |
||
65 | /** |
||
66 | * @var SplEnumBacked $case |
||
67 | * |
||
68 | * @phpstan-var SplEnumBacked<T> $case |
||
69 | */ |
||
70 | if ($case->value === $value) { |
||
71 | $result = $case; |
||
72 | break; |
||
73 | } |
||
74 | } |
||
75 | |||
76 | /** @var static|null $result */ |
||
77 | return $result ?? null; |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * Return a new instance of enum. |
||
82 | * |
||
83 | * @param string $name |
||
84 | * @param mixed[] $arguments |
||
85 | * |
||
86 | * @return static self keywords not an equivalent |
||
87 | * |
||
88 | * @throws \Error if $name is not a valid constant enum |
||
89 | * |
||
90 | * @phpstan-param string $name |
||
91 | * @phpstan-param list<mixed> $arguments |
||
92 | * @phpstan-return static |
||
93 | * @phpstan-ignore-next-line |
||
94 | * |
||
95 | * @psalm-suppress UnsafeInstantiation |
||
96 | */ |
||
97 | #[\ReturnTypeWillChange] |
||
98 | public static function __callStatic(string $name, array $arguments) |
||
99 | { |
||
100 | try { |
||
101 | $unit = new SplReflectionEnumBackedCase(static::class, $name); |
||
102 | $object = $unit->getValue(); |
||
103 | } catch (\ReflectionException $th) { |
||
104 | throw new \Error('Undefined constant ' . static::class . '::' . $name); |
||
105 | } |
||
106 | |||
107 | /** @var static $object */ |
||
108 | return $object; |
||
109 | } |
||
110 | } |
||
111 |