1 | <?php |
||||||
2 | |||||||
3 | namespace Cerbero\Dto\Traits; |
||||||
4 | |||||||
5 | use Cerbero\Dto\DtoPropertiesMapper; |
||||||
6 | use Cerbero\Dto\DtoProperty; |
||||||
7 | use Cerbero\Dto\Exceptions\UnknownDtoPropertyException; |
||||||
8 | |||||||
9 | /** |
||||||
10 | * Trait to interact with properties. |
||||||
11 | * |
||||||
12 | */ |
||||||
13 | trait HasProperties |
||||||
14 | { |
||||||
15 | /** |
||||||
16 | * The properties map. |
||||||
17 | * |
||||||
18 | * @var array |
||||||
19 | */ |
||||||
20 | protected $propertiesMap; |
||||||
21 | |||||||
22 | /** |
||||||
23 | * Retrieve the DTO properties map |
||||||
24 | * |
||||||
25 | * @return array |
||||||
26 | */ |
||||||
27 | 32 | public function getPropertiesMap(): array |
|||||
28 | { |
||||||
29 | 32 | return $this->propertiesMap; |
|||||
30 | } |
||||||
31 | |||||||
32 | /** |
||||||
33 | * Retrieve the DTO property names |
||||||
34 | * |
||||||
35 | * @return array |
||||||
36 | */ |
||||||
37 | 6 | public function getPropertyNames(): array |
|||||
38 | { |
||||||
39 | 6 | return array_keys($this->getPropertiesMap()); |
|||||
40 | } |
||||||
41 | |||||||
42 | /** |
||||||
43 | * Retrieve the DTO properties |
||||||
44 | * |
||||||
45 | * @return DtoProperty[] |
||||||
46 | */ |
||||||
47 | 2 | public function getProperties(): array |
|||||
48 | { |
||||||
49 | 2 | return array_values($this->getPropertiesMap()); |
|||||
50 | } |
||||||
51 | |||||||
52 | /** |
||||||
53 | * Determine whether the given property is set (even if its value is NULL) |
||||||
54 | * |
||||||
55 | * @param string $property |
||||||
56 | * @return bool |
||||||
57 | */ |
||||||
58 | 23 | public function hasProperty(string $property): bool |
|||||
59 | { |
||||||
60 | try { |
||||||
61 | 23 | return !!$this->getProperty($property); |
|||||
62 | 15 | } catch (UnknownDtoPropertyException $e) { |
|||||
63 | 15 | return false; |
|||||
64 | } |
||||||
65 | } |
||||||
66 | |||||||
67 | /** |
||||||
68 | * Retrieve the given DTO property (support dot notation) |
||||||
69 | * |
||||||
70 | * @param string $property |
||||||
71 | * @return DtoProperty |
||||||
72 | * @throws UnknownDtoPropertyException |
||||||
73 | */ |
||||||
74 | 43 | public function getProperty(string $property): DtoProperty |
|||||
75 | { |
||||||
76 | 43 | if (isset($this->propertiesMap[$property])) { |
|||||
77 | 28 | return $this->propertiesMap[$property]; |
|||||
78 | } |
||||||
79 | |||||||
80 | 26 | if (strpos($property, '.') === false) { |
|||||
81 | 24 | throw new UnknownDtoPropertyException(static::class, $property); |
|||||
82 | } |
||||||
83 | |||||||
84 | 8 | [$property, $nestedProperty] = explode('.', $property, 2); |
|||||
85 | 8 | $presumedDto = $this->get($property); |
|||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||||
86 | |||||||
87 | 7 | if ($presumedDto instanceof self) { |
|||||
88 | 6 | return $presumedDto->getProperty($nestedProperty); |
|||||
89 | } |
||||||
90 | |||||||
91 | 1 | throw new UnknownDtoPropertyException(static::class, $nestedProperty); |
|||||
92 | } |
||||||
93 | |||||||
94 | /** |
||||||
95 | * Retrieve the given DTO property or map it if not mapped yet |
||||||
96 | * |
||||||
97 | * @param string $property |
||||||
98 | * @param mixed $value |
||||||
99 | * @return void |
||||||
100 | */ |
||||||
101 | 14 | protected function setPropertyValueOrMap(string $property, $value): void |
|||||
102 | { |
||||||
103 | 14 | if ($this->hasProperty($property)) { |
|||||
104 | 7 | $this->getProperty($property)->setValue($value, $this->getFlags()); |
|||||
0 ignored issues
–
show
It seems like
getFlags() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
105 | 7 | return; |
|||||
106 | } |
||||||
107 | |||||||
108 | 7 | $data = $this->toArray(); |
|||||
0 ignored issues
–
show
It seems like
toArray() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
109 | |||||||
110 | 7 | if (strpos($property, '.') === false) { |
|||||
111 | 5 | $data[$property] = $value; |
|||||
112 | } else { |
||||||
113 | 2 | [$property, $nestedProperty] = explode('.', $property, 2); |
|||||
114 | 2 | $data[$property] = $this->resolveNestedValue($nestedProperty, $value); |
|||||
115 | } |
||||||
116 | |||||||
117 | 7 | $this->propertiesMap = $this->mapData($data); |
|||||
118 | 6 | } |
|||||
119 | |||||||
120 | /** |
||||||
121 | * Retrieve the DTO mapped properties for the given data |
||||||
122 | * |
||||||
123 | * @param array $data |
||||||
124 | * @return array |
||||||
125 | * @throws \Cerbero\Dto\Exceptions\DtoNotFoundException |
||||||
126 | * @throws \Cerbero\Dto\Exceptions\MissingValueException |
||||||
127 | * @throws \Cerbero\Dto\Exceptions\UnexpectedValueException |
||||||
128 | * @throws UnknownDtoPropertyException |
||||||
129 | */ |
||||||
130 | 81 | protected function mapData(array $data): array |
|||||
131 | { |
||||||
132 | 81 | $mergedData = array_merge(static::getDefaultValues(), $data); |
|||||
133 | |||||||
134 | 81 | return DtoPropertiesMapper::for(static::class)->map($mergedData, $this->getFlags()); |
|||||
135 | } |
||||||
136 | |||||||
137 | /** |
||||||
138 | * Retrieve a nested value following the dot notation |
||||||
139 | * |
||||||
140 | * @param string $property |
||||||
141 | * @param mixed $value |
||||||
142 | * @return array |
||||||
143 | */ |
||||||
144 | 2 | protected function resolveNestedValue(string $property, $value): array |
|||||
145 | { |
||||||
146 | 2 | if (strpos($property, '.') === false) { |
|||||
147 | 2 | return [$property => $value]; |
|||||
148 | } |
||||||
149 | |||||||
150 | 1 | [$property, $nestedProperty] = explode('.', $property, 2); |
|||||
151 | |||||||
152 | 1 | return [$property => $this->resolveNestedValue($nestedProperty, $value)]; |
|||||
153 | } |
||||||
154 | } |
||||||
155 |