Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
22 / 22 |
|
100.00% |
4 / 4 |
CRAP | |
100.00% |
1 / 1 |
DTOTrait | |
100.00% |
22 / 22 |
|
100.00% |
4 / 4 |
10 | |
100.00% |
1 / 1 |
permitExtraProperties | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
extraPropertiesPermitted | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hydrateFromArray | |
100.00% |
19 / 19 |
|
100.00% |
1 / 1 |
7 | |||
toArray | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | /** |
4 | * @author: Doug Wilbourne (dougwilbourne@gmail.com) |
5 | */ |
6 | declare(strict_types=1); |
7 | |
8 | namespace pvc\html\htmlBuilder\definitions\dto; |
9 | |
10 | use pvc\html\err\DTOExtraPropertyException; |
11 | use pvc\html\err\DTOInvalidPropertyValueException; |
12 | use pvc\html\err\DTOMissingPropertyException; |
13 | use ReflectionClass; |
14 | use ReflectionProperty; |
15 | use Stringable; |
16 | use Throwable; |
17 | |
18 | /** |
19 | * Class DTOTrait |
20 | */ |
21 | trait DTOTrait |
22 | { |
23 | private readonly bool $extraPropertiesPermitted; |
24 | |
25 | public function permitExtraProperties(): void |
26 | { |
27 | $this->extraPropertiesPermitted = true; |
28 | } |
29 | |
30 | public function extraPropertiesPermitted(): bool |
31 | { |
32 | return $this->extraPropertiesPermitted ?? false; |
33 | } |
34 | |
35 | /** |
36 | * @param array<string, mixed> $constructorProperties |
37 | * @throws DTOExtraPropertyException |
38 | * @throws DTOMissingPropertyException |
39 | * @throws DTOInvalidPropertyValueException |
40 | */ |
41 | public function hydrateFromArray(array $constructorProperties): void |
42 | { |
43 | $reflection = new ReflectionClass(static::class); |
44 | |
45 | $className = $reflection->getName(); |
46 | |
47 | $requiredProperties = array_map( |
48 | function (ReflectionProperty $value): string { |
49 | return $value->getName(); |
50 | }, |
51 | $reflection->getProperties(ReflectionProperty::IS_PUBLIC) |
52 | ); |
53 | |
54 | $missingProperties = array_diff($requiredProperties, array_keys($constructorProperties)); |
55 | if ($missingProperties) { |
56 | throw new DTOMissingPropertyException(implode(',', $missingProperties), $className); |
57 | } |
58 | |
59 | $extraProperties = array_diff(array_keys($constructorProperties), $requiredProperties); |
60 | if ($extraProperties && !$this->extraPropertiesPermitted()) { |
61 | throw new DTOExtraPropertyException(implode(',', $extraProperties), $className); |
62 | } |
63 | |
64 | foreach ($constructorProperties as $propertyName => $propertyValue) { |
65 | if (in_array($propertyName, $requiredProperties)) { |
66 | try { |
67 | $this->{$propertyName} = $propertyValue; |
68 | } catch (Throwable $e) { |
69 | throw new DTOInvalidPropertyValueException($propertyName, $propertyValue, $className); |
70 | } |
71 | } |
72 | } |
73 | } |
74 | |
75 | /** |
76 | * toArray |
77 | * @return array<string, mixed> |
78 | */ |
79 | public function toArray(): array |
80 | { |
81 | return (array) $this; |
82 | } |
83 | } |