@@ -37,6 +37,14 @@ abstract class Enum implements \JsonSerializable
37
37
*/
38
38
protected static $ cache = [];
39
39
40
+ /**
41
+ * Cache of instances of the Enum class
42
+ *
43
+ * @var array
44
+ * @psalm-var array<class-string, array<string, static>>
45
+ */
46
+ protected static $ instances = [];
47
+
40
48
/**
41
49
* Creates a new value of some type
42
50
*
@@ -53,15 +61,24 @@ public function __construct($value)
53
61
$ value = $ value ->getValue ();
54
62
}
55
63
56
- if (!$ this ->isValid ($ value )) {
57
- /** @psalm-suppress InvalidCast */
58
- throw new \UnexpectedValueException ("Value ' $ value' is not part of the enum " . static ::class);
59
- }
64
+ static ::assertValidValue ($ value );
60
65
61
66
/** @psalm-var T */
62
67
$ this ->value = $ value ;
63
68
}
64
69
70
+ /**
71
+ * @param mixed $value
72
+ * @return static
73
+ * @psalm-return static<T>
74
+ */
75
+ public static function from ($ value ): self
76
+ {
77
+ static ::assertValidValue ($ value );
78
+
79
+ return new static ($ value );
80
+ }
81
+
65
82
/**
66
83
* @psalm-pure
67
84
* @return mixed
@@ -167,13 +184,27 @@ public static function toArray()
167
184
* @param $value
168
185
* @psalm-param mixed $value
169
186
* @psalm-pure
187
+ * @psalm-assert-if-true T $value
170
188
* @return bool
171
189
*/
172
190
public static function isValid ($ value )
173
191
{
174
192
return \in_array ($ value , static ::toArray (), true );
175
193
}
176
194
195
+ /**
196
+ * Asserts valid enum value
197
+ *
198
+ * @psalm-pure
199
+ * @psalm-assert T $value
200
+ */
201
+ public static function assertValidValue ($ value ): void
202
+ {
203
+ if (!static ::isValid ($ value )) {
204
+ throw new \UnexpectedValueException ("Value ' $ value' is not part of the enum " . static ::class);
205
+ }
206
+ }
207
+
177
208
/**
178
209
* Check if is valid enum key
179
210
*
@@ -210,17 +241,20 @@ public static function search($value)
210
241
* @param array $arguments
211
242
*
212
243
* @return static
213
- * @psalm-pure
214
244
* @throws \BadMethodCallException
215
245
*/
216
246
public static function __callStatic ($ name , $ arguments )
217
247
{
218
- $ array = static ::toArray ();
219
- if (isset ($ array [$ name ]) || \array_key_exists ($ name , $ array )) {
220
- return new static ($ array [$ name ]);
248
+ $ class = static ::class;
249
+ if (!isset (self ::$ instances [$ class ][$ name ])) {
250
+ $ array = static ::toArray ();
251
+ if (!isset ($ array [$ name ]) && !\array_key_exists ($ name , $ array )) {
252
+ $ message = "No static method or enum constant ' $ name' in class " . static ::class;
253
+ throw new \BadMethodCallException ($ message );
254
+ }
255
+ return self ::$ instances [$ class ][$ name ] = new static ($ array [$ name ]);
221
256
}
222
-
223
- throw new \BadMethodCallException ("No static method or enum constant ' $ name' in class " . static ::class);
257
+ return clone self ::$ instances [$ class ][$ name ];
224
258
}
225
259
226
260
/**
0 commit comments