1
|
|
|
<?php |
2
|
|
|
declare(strict_types=1); |
3
|
|
|
|
4
|
|
|
namespace Stratadox\Deserializer; |
5
|
|
|
|
6
|
|
|
use Stratadox\Hydrator\HydrationFailure; |
7
|
|
|
use Stratadox\Hydrator\Hydrator; |
8
|
|
|
use Stratadox\Instantiator\InstantiationFailure; |
9
|
|
|
use Stratadox\Instantiator\ObjectInstantiator; |
10
|
|
|
use Stratadox\Hydrator\ObjectHydrator; |
11
|
|
|
use Stratadox\Hydrator\ReflectiveHydrator; |
12
|
|
|
use Stratadox\Instantiator\Instantiator; |
13
|
|
|
use function class_parents; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Deserializes the input array into objects. |
17
|
|
|
* |
18
|
|
|
* @author Stratadox |
19
|
|
|
*/ |
20
|
|
|
final class ObjectDeserializer implements Deserializer |
21
|
|
|
{ |
22
|
|
|
/** @var Instantiator */ |
23
|
|
|
private $make; |
24
|
|
|
/** @var Hydrator */ |
25
|
|
|
private $hydrator; |
26
|
|
|
|
27
|
|
|
private function __construct(Instantiator $instance, Hydrator $hydrate) |
28
|
|
|
{ |
29
|
|
|
$this->make = $instance; |
30
|
|
|
$this->hydrator = $hydrate; |
31
|
|
|
} |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Makes a new deserializer for the class. |
35
|
|
|
* |
36
|
|
|
* Produces a default instantiator and hydrator for the class. If the class |
37
|
|
|
* uses inheritance, a reflective hydrator is used by default. This may not |
38
|
|
|
* always be necessary. (ie. when not inheriting private properties) In such |
39
|
|
|
* cases, @see ObjectDeserializer::using can be used instead. |
40
|
|
|
* |
41
|
|
|
* @param string $class The fully qualified collection class name. |
42
|
|
|
* @return Deserializer The object deserializer. |
43
|
|
|
* @throws InstantiationFailure When the class cannot be instantiated. |
44
|
|
|
*/ |
45
|
|
|
public static function forThe(string $class): Deserializer |
46
|
|
|
{ |
47
|
|
|
return new ObjectDeserializer( |
48
|
|
|
ObjectInstantiator::forThe($class), |
49
|
|
|
empty(class_parents($class)) |
50
|
|
|
? ObjectHydrator::default() |
51
|
|
|
: ReflectiveHydrator::default() |
52
|
|
|
); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* Makes a new deserializer for the class, using custom instantiator and |
57
|
|
|
* hydrator. |
58
|
|
|
* |
59
|
|
|
* @param Instantiator $instantiator The object that produces instances. |
60
|
|
|
* @param Hydrator $hydrator The object that writes properties. |
61
|
|
|
* @return Deserializer The object deserializer. |
62
|
|
|
*/ |
63
|
|
|
public static function using( |
64
|
|
|
Instantiator $instantiator, |
65
|
|
|
Hydrator $hydrator |
66
|
|
|
): Deserializer { |
67
|
|
|
return new ObjectDeserializer($instantiator, $hydrator); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** @inheritdoc */ |
71
|
|
|
public function from(array $input): object |
72
|
|
|
{ |
73
|
|
|
$object = $this->make->instance(); |
74
|
|
|
try { |
75
|
|
|
$this->hydrator->writeTo($object, $input); |
76
|
|
|
} catch (HydrationFailure $exception) { |
77
|
|
|
throw FailedToDeserializeTheObject::encountered($exception); |
78
|
|
|
} |
79
|
|
|
return $object; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** @inheritdoc */ |
83
|
|
|
public function typeFor(array $input): string |
84
|
|
|
{ |
85
|
|
|
return $this->make->class(); |
86
|
|
|
} |
87
|
|
|
} |
88
|
|
|
|