EntityMap::setName()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Darya\ORM;
4
5
use Darya\ORM\EntityMap\Strategy;
6
use InvalidArgumentException;
7
8
/**
9
 * Darya's abstract entity map.
10
 *
11
 * Describes an entity's mapping to a storage resource.
12
 *
13
 * TODO: EntityMapFactory for easy (read: dynamic) instantiation with sensible defaults
14
 *
15
 * TODO: Could an entity factory go here too?
16
 *       This would give the entity map control over how entities are instantiated.
17
 *
18
 * TODO: Storage name should be kept here too, for the EntityManager to use to create Mappers
19
 *
20
 * @author Chris Andrew <[email protected]>
21
 */
22
class EntityMap
23
{
24
	/**
25
	 * The name of the entity.
26
	 *
27
	 * @var string
28
	 */
29
	protected $name;
30
31
	/**
32
	 * The class name of the entity to map.
33
	 *
34
	 * @var string
35
	 */
36
	protected $class;
37
38
	/**
39
	 * The name of the resource the entity maps to in storage.
40
	 *
41
	 * @var string
42
	 */
43
	protected $resource;
44
45
	/**
46
	 * The mapping of entity attributes as keys to storage fields as values.
47
	 *
48
	 * @var array
49
	 */
50
	protected $mapping = [];
51
52
	/**
53
	 * The mapping strategy to use.
54
	 *
55
	 * @var Strategy
56
	 */
57
	protected $strategy;
58
59
	/**
60
	 * The entity's primary key attribute(s).
61
	 *
62
	 * @var string|string[]
63
	 */
64
	protected $key;
65
66
	/**
67
	 * Create a new entity map.
68
	 *
69
	 * @param string          $class    The class name of the entity to map.
70
	 * @param string          $resource The name of the resource the entity maps to in storage.
71
	 * @param array           $mapping  The mapping of entity attributes as keys to storage fields as values.
72
	 * @param Strategy        $strategy The mapping strategy to use.
73
	 * @param string|string[] $key      [optional] The entity's primary key attribute(s). Defaults to `'id'`.
74
	 */
75
	public function __construct(string $class, string $resource, array $mapping, Strategy $strategy, $key = 'id')
76
	{
77
		$this->class    = $class;
78
		$this->resource = $resource;
79
		$this->mapping  = $mapping;
80
		$this->strategy = $strategy;
81
		$this->setKey($key);
82
	}
83
84
	/**
85
	 * Get the name of the entity.
86
	 *
87
	 * @return string
88
	 */
89
	public function getName(): string
90
	{
91
		return $this->name ?: $this->getClass();
92
	}
93
94
	/**
95
	 * Set the name of the entity.
96
	 *
97
	 * @param string $name
98
	 */
99
	public function setName(string $name): void
100
	{
101
		$this->name = $name;
102
	}
103
104
	/**
105
	 * Get the mapped entity class name.
106
	 *
107
	 * @return string
108
	 */
109
	public function getClass(): string
110
	{
111
		return $this->class;
112
	}
113
114
	/**
115
	 * Get the resource the entity is mapped to.
116
	 *
117
	 * @return string
118
	 */
119
	public function getResource(): string
120
	{
121
		return $this->resource;
122
	}
123
124
	/**
125
	 * Get the mapping of entity attributes to storage fields.
126
	 *
127
	 * Returns an array with entity attributes for keys and corresponding
128
	 * storage fields for values.
129
	 *
130
	 * @return string[]
131
	 */
132
	public function getMapping(): array
133
	{
134
		return $this->mapping;
135
	}
136
137
	/**
138
	 * Get the mapping strategy.
139
	 *
140
	 * @return Strategy
141
	 */
142
	public function getStrategy(): Strategy
143
	{
144
		return $this->strategy;
145
	}
146
147
	/**
148
	 * Map from storage data to an entity.
149
	 *
150
	 * @param object $entity      The entity to map to.
151
	 * @param array  $storageData The storage data to map from.
152
	 * @return object The mapped entity.
153
	 */
154
	public function mapFromStorage($entity, array $storageData)
155
	{
156
		$mapping = $this->getMapping();
157
158
		foreach ($mapping as $entityKey => $storageKey) {
159
			if (array_key_exists($storageKey, $storageData)) {
160
				$this->writeAttribute($entity, $entityKey, $storageData[$storageKey]);
161
			}
162
		}
163
164
		return $entity;
165
	}
166
167
	/**
168
	 * Map from an entity to storage data.
169
	 *
170
	 * @param object $entity The entity to map from.
171
	 * @return array The mapped storage data.
172
	 */
173
	public function mapToStorage($entity): array
174
	{
175
		$mapping = $this->getMapping();
176
177
		$data = [];
178
179
		foreach ($mapping as $entityKey => $storageKey) {
180
			$data[$storageKey] = $this->readAttribute($entity, $entityKey);
181
		}
182
183
		return $data;
184
	}
185
186
	/**
187
	 * Get the entity's primary key attribute(s).
188
	 *
189
	 * @return string|string[]
190
	 */
191
	public function getKey()
192
	{
193
		return $this->key;
194
	}
195
196
	/**
197
	 * Set the entity's primary key attribute(s).
198
	 *
199
	 * @param string|string[]
200
	 */
201
	protected function setKey($key)
202
	{
203
		if (!is_string($key) && !is_array($key)) {
204
			throw new InvalidArgumentException("Entity key must be a string, or an array of strings");
205
		}
206
207
		$this->key = $key;
208
	}
209
210
	/**
211
	 * Get the storage field name of the entity's primary key.
212
	 *
213
	 * @return string
214
	 */
215
	public function getStorageKey(): string
216
	{
217
		return $this->getStorageField($this->getKey());
0 ignored issues
show
Bug introduced by
It seems like $this->getKey() can also be of type string[]; however, parameter $attribute of Darya\ORM\EntityMap::getStorageField() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

217
		return $this->getStorageField(/** @scrutinizer ignore-type */ $this->getKey());
Loading history...
218
	}
219
220
	/**
221
	 * Get the storage field name of the given entity attribute.
222
	 *
223
	 * @param string $attribute
224
	 * @return string
225
	 */
226
	public function getStorageField(string $attribute): string
227
	{
228
		if (array_key_exists($attribute, $this->mapping)) {
229
			return $this->mapping[$attribute];
230
		}
231
232
		return $attribute;
233
	}
234
235
	/**
236
	 * Get the storage field names of the given entity attributes.
237
	 *
238
	 * @param string[] $attributes
239
	 * @return string[]
240
	 */
241
	public function getStorageFields(array $attributes): array
242
	{
243
		$fields = [];
244
245
		foreach ($attributes as $attribute) {
246
			$fields[] = $this->getStorageField($attribute);
247
		}
248
249
		return $fields;
250
	}
251
252
	/**
253
	 * Get the attribute name for the given storage field.
254
	 *
255
	 * @param string $storageField
256
	 * @return string
257
	 */
258
	public function getAttribute(string $storageField): string
259
	{
260
		return array_search($storageField, $this->getMapping()) ?: $storageField;
261
	}
262
263
	/**
264
	 * Get the attribute names for the given storage fields.
265
	 *
266
	 * @param string[] $storageFields
267
	 * @return string[]
268
	 */
269
	public function getAttributes(array $storageFields): array
270
	{
271
		$attributes = [];
272
273
		$flippedMapping = array_flip($this->getMapping());
274
275
		foreach ($storageFields as $storageField) {
276
			$attributes[] = $flippedMapping[$storageField] ?? $storageField;
277
		}
278
279
		return $attributes;
280
	}
281
282
	/**
283
	 * Read an attribute from an entity.
284
	 *
285
	 * @param mixed  $entity    The entity to read the attribute from.
286
	 * @param string $attribute The name of the attribute to read.
287
	 * @return mixed The attribute's value.
288
	 */
289
	public function readAttribute($entity, string $attribute)
290
	{
291
		return $this->readAttributes($entity, [$attribute])[$attribute];
292
	}
293
294
	/**
295
	 * Read many attributes from an entity.
296
	 *
297
	 * @param mixed    $entity     The entity to read the attributes from.
298
	 * @param string[] $attributes The names of the attributes to read.
299
	 * @return mixed[] The attribute values.
300
	 */
301
	public function readAttributes($entity, array $attributes): array
302
	{
303
		return $this->getStrategy()->readAttributes($entity, $attributes);
304
	}
305
306
	/**
307
	 * Read an attribute from many entities.
308
	 *
309
	 * @param iterable $entities  The entities to read the attribute from.
310
	 * @param string   $attribute The name of the attribute to read.
311
	 * @return mixed[] The attribute values from each entity.
312
	 */
313
	public function readAttributeFromMany(iterable $entities, string $attribute): array
314
	{
315
		$values = [];
316
317
		foreach ($entities as $entity) {
318
			$values[] = $this->readAttribute($entity, $attribute);
319
		}
320
321
		return $values;
322
	}
323
324
	/**
325
	 * Write an attribute to an entity.
326
	 *
327
	 * @param object $entity    The entity to write the attribute to.
328
	 * @param string $attribute The name of the attribute to write.
329
	 * @param mixed  $value     The value of the attribute to write.
330
	 * @return void
331
	 */
332
	public function writeAttribute($entity, string $attribute, $value): void
333
	{
334
		$this->writeAttributes($entity, [$attribute => $value]);
335
	}
336
337
	/**
338
	 * Write many attributes to an entity.
339
	 *
340
	 * @param object  $entity     The entity to write the attributes to.
341
	 * @param mixed[] $attributes The names and values of the attributes to write.
342
	 * @return void
343
	 */
344
	public function writeAttributes($entity, array $attributes): void
345
	{
346
		$this->getStrategy()->writeAttributes($entity, $attributes);
347
	}
348
}
349