1
|
|
|
<?php declare(strict_types=1); |
2
|
|
|
|
3
|
|
|
namespace Igni\Storage\Mapping\MetaData; |
4
|
|
|
|
5
|
|
|
use Igni\Storage\Exception\MappingException; |
6
|
|
|
use Igni\Storage\Mapping\Strategy\Id; |
7
|
|
|
use ReflectionClass; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Keeps information how entity should be mapped. |
11
|
|
|
* |
12
|
|
|
* @package Igni\Storage\Mapping\MetaData |
13
|
|
|
*/ |
14
|
|
|
final class EntityMetaData |
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* Entity class (FQCN) |
18
|
|
|
* @var string |
19
|
|
|
*/ |
20
|
|
|
private $class; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Generated hydrator class name (not FQCN) |
24
|
|
|
* @var string string |
25
|
|
|
*/ |
26
|
|
|
private $hydratorClassName; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Entity's mapped properties metadata. |
30
|
|
|
* @var PropertyMetaData[] |
31
|
|
|
*/ |
32
|
|
|
private $properties = []; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var ReflectionClass |
36
|
|
|
*/ |
37
|
|
|
private $reflectionClass; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Either name of table or connection or any other namespace |
41
|
|
|
* where entity is stored. |
42
|
|
|
* @var string |
43
|
|
|
*/ |
44
|
|
|
private $source; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Connection that will be used when no repository is registered |
48
|
|
|
* for the entity. |
49
|
|
|
* @var string |
50
|
|
|
*/ |
51
|
|
|
private $connection = 'default'; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Provides information if entity is embed entity. |
55
|
|
|
* @var bool |
56
|
|
|
*/ |
57
|
|
|
private $embed = true; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Keeps user defined hydrator's class (FQCN). |
61
|
|
|
* @var string |
62
|
|
|
*/ |
63
|
|
|
private $customHydrator; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Keeps mapped properties to storage fields. |
67
|
|
|
* @var string[] |
68
|
|
|
*/ |
69
|
|
|
private $fields = []; |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Contains identifier property. |
73
|
|
|
* @var PropertyMetaData|null |
74
|
|
|
*/ |
75
|
|
|
private $identifier; |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @param string $class |
79
|
|
|
* |
80
|
|
|
* @throws \ReflectionException |
81
|
|
|
*/ |
82
|
29 |
|
public function __construct(string $class) |
83
|
|
|
{ |
84
|
29 |
|
$this->class = $class; |
85
|
29 |
|
$this->reflectionClass = new ReflectionClass($class); |
86
|
29 |
|
$this->hydratorClassName = '_' . str_replace('\\', '', $class) . 'Hydrator'; |
87
|
29 |
|
} |
88
|
|
|
|
89
|
3 |
|
public function makeEmbed(): void |
90
|
|
|
{ |
91
|
3 |
|
$this->source = null; |
92
|
3 |
|
$this->embed = true; |
93
|
3 |
|
} |
94
|
|
|
|
95
|
1 |
|
public function isEmbed(): bool |
96
|
|
|
{ |
97
|
1 |
|
return $this->embed; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
public function isStorable(): bool |
101
|
|
|
{ |
102
|
|
|
return $this->source !== null && $this->hasIdentifier(); |
103
|
|
|
} |
104
|
|
|
|
105
|
24 |
|
public function setSource(string $source): void |
106
|
|
|
{ |
107
|
24 |
|
$this->source = $source; |
108
|
24 |
|
$this->embed = false; |
109
|
24 |
|
} |
110
|
|
|
|
111
|
15 |
|
public function getSource(): string |
112
|
|
|
{ |
113
|
15 |
|
return $this->source; |
114
|
|
|
} |
115
|
|
|
|
116
|
23 |
|
public function setConnection(string $name = 'default'): void |
117
|
|
|
{ |
118
|
23 |
|
$this->connection = $name; |
119
|
23 |
|
} |
120
|
|
|
|
121
|
22 |
|
public function getConnection(): string |
122
|
|
|
{ |
123
|
22 |
|
return $this->connection; |
124
|
|
|
} |
125
|
|
|
|
126
|
24 |
|
public function setCustomHydratorClass(string $className): void |
127
|
|
|
{ |
128
|
24 |
|
if (!class_exists($className)) { |
129
|
|
|
throw new MappingException("Cannot set parent hydrator, class (${className}) does not exists."); |
130
|
|
|
} |
131
|
|
|
$this->customHydrator = $className; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
public function definesCustomHydrator(): bool |
135
|
|
|
{ |
136
|
25 |
|
return $this->customHydrator !== null; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
public function getCustomHydratorClass(): string |
140
|
|
|
{ |
141
|
24 |
|
return $this->customHydrator; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
public function getProperty(string $name): PropertyMetaData |
145
|
|
|
{ |
146
|
1 |
|
if (!isset($this->properties[$name])) { |
147
|
|
|
throw new MappingException("Property ${name} is undefined."); |
148
|
|
|
} |
149
|
1 |
|
return $this->properties[$name]; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
public function addProperty(PropertyMetaData $property): void |
153
|
|
|
{ |
154
|
27 |
|
$this->properties[$property->getName()] = $property; |
155
|
27 |
|
if ($property->getType() === Id::class) { |
156
|
24 |
|
$this->identifier = $property; |
157
|
|
|
} |
158
|
27 |
|
} |
159
|
|
|
|
160
|
|
|
public function hasIdentifier(): bool |
161
|
|
|
{ |
162
|
11 |
|
return $this->identifier !== null; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
public function getIdentifier(): PropertyMetaData |
166
|
|
|
{ |
167
|
11 |
|
if (!$this->hasIdentifier()) { |
168
|
|
|
throw new MappingException("Entity {$this->class} defines no identifier."); |
169
|
|
|
} |
170
|
|
|
|
171
|
11 |
|
return $this->identifier; |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
public function getHydratorClassName(): string |
175
|
|
|
{ |
176
|
25 |
|
return $this->hydratorClassName; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
public function definesProperties(): bool |
180
|
|
|
{ |
181
|
23 |
|
return !empty($this->properties); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* @return PropertyMetaData[] |
186
|
|
|
*/ |
187
|
|
|
public function getProperties(): array |
188
|
|
|
{ |
189
|
4 |
|
return $this->properties; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
public function getFields(): array |
193
|
|
|
{ |
194
|
|
|
return $this->fields; |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
public function getClass(): string |
198
|
|
|
{ |
199
|
27 |
|
return $this->class; |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
public function createInstance(...$arguments) |
203
|
|
|
{ |
204
|
1 |
|
if ($arguments) { |
|
|
|
|
205
|
|
|
return $this->reflectionClass->newInstanceArgs($arguments); |
206
|
|
|
} |
207
|
|
|
|
208
|
1 |
|
return $this->reflectionClass->newInstanceWithoutConstructor(); |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
public function __sleep() |
212
|
|
|
{ |
213
|
|
|
return [ |
214
|
1 |
|
'class', |
215
|
|
|
'hydratorClassName', |
216
|
|
|
'properties', |
217
|
|
|
'source', |
218
|
|
|
'connection', |
219
|
|
|
'customHydrator', |
220
|
|
|
]; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
public function __wakeup() |
224
|
|
|
{ |
225
|
1 |
|
$this->reflectionClass = new ReflectionClass($this->class); |
226
|
|
|
|
227
|
1 |
|
foreach ($this->properties as $property) { |
228
|
1 |
|
$this->fields[] = $property->getFieldName(); |
229
|
1 |
|
if ($property->getType() === Id::class) { |
230
|
1 |
|
$this->identifier = $property; |
231
|
|
|
} |
232
|
|
|
} |
233
|
1 |
|
} |
234
|
|
|
} |
235
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.