2
2
3
3
namespace Aternos \Serializer ;
4
4
5
+ use Aternos \Serializer \Exceptions \InvalidEnumBackingException ;
5
6
use Aternos \Serializer \Exceptions \SerializationException ;
6
7
use Aternos \Serializer \Exceptions \IncorrectTypeException ;
7
8
use Aternos \Serializer \Exceptions \MissingPropertyException ;
8
9
use Aternos \Serializer \Exceptions \UnsupportedTypeException ;
9
10
use InvalidArgumentException ;
10
11
use ReflectionClass ;
12
+ use ReflectionEnum ;
11
13
use ReflectionException ;
12
14
use ReflectionIntersectionType ;
13
15
use ReflectionNamedType ;
14
16
use ReflectionProperty ;
15
17
use ReflectionUnionType ;
16
18
use TypeError ;
19
+ use ValueError ;
17
20
18
21
/**
19
22
* Deserializes arrays into objects using the Serialize attribute.
@@ -48,22 +51,29 @@ public function __construct(
48
51
* @throws IncorrectTypeException if the type of the property is incorrect
49
52
* @throws MissingPropertyException if a required property is missing
50
53
* @throws UnsupportedTypeException if the type of the property is unsupported
54
+ * @throws InvalidEnumBackingException if the target class is an enum, but the serialized data is not a valid backing value
51
55
*/
52
56
public function deserialize (
53
57
mixed $ data ,
54
58
string $ path = "" ,
55
59
): object
56
60
{
57
- if (!is_array ($ data )) {
58
- throw new InvalidArgumentException ("Data must be an array. " );
59
- }
60
61
try {
61
62
$ reflectionClass = new ReflectionClass ($ this ->class );
62
- $ result = new $ this ->class ;
63
63
} catch (ReflectionException ) {
64
64
throw new InvalidArgumentException ("Class ' " . $ this ->class . "' does not exist. " );
65
65
}
66
66
67
+ if ($ reflectionClass ->isEnum ()) {
68
+ return $ this ->parseEnum ($ data , $ path );
69
+ }
70
+
71
+ if (!is_array ($ data )) {
72
+ throw new IncorrectTypeException ($ path , $ this ->class , $ data );
73
+ }
74
+
75
+ $ result = new $ this ->class ;
76
+
67
77
foreach ($ reflectionClass ->getProperties () as $ property ) {
68
78
$ this ->deserializeProperty ($ data , $ path , $ property , $ result );
69
79
}
@@ -81,6 +91,7 @@ public function deserialize(
81
91
* @throws IncorrectTypeException if the type of the property is incorrect
82
92
* @throws MissingPropertyException if the property is required but missing
83
93
* @throws UnsupportedTypeException if the type of the property is unsupported
94
+ * @throws InvalidEnumBackingException if the target class is an enum, but the serialized data is not a valid backing value
84
95
*/
85
96
protected function deserializeProperty (
86
97
array $ data ,
@@ -208,6 +219,7 @@ protected function parseUnionType(ReflectionUnionType $unionType, mixed $value,
208
219
* @throws IncorrectTypeException if the type of the property is incorrect
209
220
* @throws UnsupportedTypeException if the type of the property is unsupported
210
221
* @throws MissingPropertyException if a required property is missing
222
+ * @throws InvalidEnumBackingException if the target class is an enum, but the serialized data is not a valid backing value
211
223
*/
212
224
protected function parseNamedType (
213
225
ReflectionNamedType $ type ,
@@ -226,10 +238,6 @@ protected function parseNamedType(
226
238
return $ value ;
227
239
}
228
240
229
- if (!is_array ($ value )) {
230
- throw new IncorrectTypeException ($ propertyPath , $ type ->getName (), $ value );
231
- }
232
-
233
241
if ($ type ->getName () === "self " ) {
234
242
$ deserializer = $ this ;
235
243
} else {
@@ -261,4 +269,33 @@ protected function isBuiltInTypeValid(string $type, mixed $value, string $path):
261
269
default => throw new UnsupportedTypeException ($ path , $ type ),
262
270
};
263
271
}
272
+
273
+ /**
274
+ * @param mixed $value
275
+ * @param string $path
276
+ * @return mixed
277
+ * @throws InvalidEnumBackingException
278
+ * @throws UnsupportedTypeException
279
+ * @noinspection PhpDocMissingThrowsInspection
280
+ */
281
+ protected function parseEnum (mixed $ value , string $ path ): mixed
282
+ {
283
+ /** @noinspection PhpUnhandledExceptionInspection - It has already been verified that the enum exists */
284
+ $ reflectionEnum = new ReflectionEnum ($ this ->class );
285
+
286
+ if (!$ reflectionEnum ->isBacked ()) {
287
+ throw new UnsupportedTypeException ($ path , $ this ->class , "Enums must be backed by a scalar type. " );
288
+ }
289
+
290
+ $ backingType = $ reflectionEnum ->getBackingType ();
291
+ if (!$ backingType ->isBuiltin () || !$ this ->isBuiltInTypeValid ($ backingType ->getName (), $ value , $ path )) {
292
+ throw new InvalidEnumBackingException ($ this ->class , $ backingType ->getName (), $ value );
293
+ }
294
+
295
+ try {
296
+ return $ this ->class ::from ($ value );
297
+ } catch (ValueError ) {
298
+ throw new InvalidEnumBackingException ($ this ->class , $ backingType ->getName (), $ value );
299
+ }
300
+ }
264
301
}
0 commit comments