|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Charcoal\Config; |
|
4
|
|
|
|
|
5
|
|
|
// Dependencies from `PHP` |
|
6
|
|
|
use ArrayAccess; |
|
7
|
|
|
use InvalidArgumentException; |
|
8
|
|
|
|
|
9
|
|
|
/** |
|
10
|
|
|
* Default Charcoal core entity (data container). |
|
11
|
|
|
*/ |
|
12
|
|
|
abstract class AbstractEntity implements EntityInterface |
|
13
|
|
|
{ |
|
14
|
|
|
|
|
15
|
|
|
/** |
|
16
|
|
|
* Keep a list of all config keys available. |
|
17
|
|
|
* @var array $keys |
|
18
|
|
|
*/ |
|
19
|
|
|
protected $keys = []; |
|
20
|
|
|
|
|
21
|
|
|
/** |
|
22
|
|
|
* Get the configuration's available keys. |
|
23
|
|
|
* |
|
24
|
|
|
* @return array |
|
25
|
|
|
*/ |
|
26
|
|
|
public function keys() |
|
27
|
|
|
{ |
|
28
|
|
|
return array_keys($this->keys); |
|
29
|
|
|
} |
|
30
|
|
|
|
|
31
|
|
|
/** |
|
32
|
|
|
* Gets the entity data, as associative array map. |
|
33
|
|
|
* |
|
34
|
|
|
* @param array $filters Optional. Property filters. |
|
35
|
|
|
* @return array The data map. |
|
36
|
|
|
*/ |
|
37
|
|
|
public function data(array $filters = null) |
|
38
|
|
|
{ |
|
39
|
|
|
unset($filters); |
|
40
|
|
|
$ret = []; |
|
41
|
|
|
$keys = $this->keys(); |
|
42
|
|
|
foreach ($keys as $k) { |
|
43
|
|
|
if ($k == 'data') { |
|
44
|
|
|
// Avoid recursive call |
|
45
|
|
|
continue; |
|
46
|
|
|
} |
|
47
|
|
|
if (isset($this[$k])) { |
|
48
|
|
|
$ret[$k] = $this[$k]; |
|
49
|
|
|
} |
|
50
|
|
|
} |
|
51
|
|
|
return $ret; |
|
52
|
|
|
} |
|
53
|
|
|
|
|
54
|
|
|
/** |
|
55
|
|
|
* Sets the entity data, from associative array map. |
|
56
|
|
|
* |
|
57
|
|
|
* This function takes an array and fill the property with its value. |
|
58
|
|
|
* |
|
59
|
|
|
* @param array $data The entity data. Will call setters. |
|
60
|
|
|
* @return self |
|
61
|
|
|
* @see self::offsetSet() |
|
62
|
|
|
*/ |
|
63
|
|
|
public function setData(array $data) |
|
64
|
|
|
{ |
|
65
|
|
|
foreach ($data as $prop => $val) { |
|
66
|
|
|
$this[$prop] = $val; |
|
67
|
|
|
} |
|
68
|
|
|
return $this; |
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
|
|
/** |
|
72
|
|
|
* Returns true if the container can return an entry for the given identifier. |
|
73
|
|
|
* Returns false otherwise. |
|
74
|
|
|
* |
|
75
|
|
|
* `has($key)` returning true does not mean that `get($key)` will not throw an exception. |
|
76
|
|
|
* It does however mean that `get($id)` will not throw a `NotFoundException`. |
|
77
|
|
|
* |
|
78
|
|
|
* @param string $key Identifier of the entry to look for. |
|
79
|
|
|
* @return boolean |
|
80
|
|
|
*/ |
|
81
|
|
|
public function has($key) |
|
82
|
|
|
{ |
|
83
|
|
|
return isset($this[$key]); |
|
84
|
|
|
} |
|
85
|
|
|
|
|
86
|
|
|
/** |
|
87
|
|
|
* Find an entry of the configuration by its key and retrieve it. |
|
88
|
|
|
* |
|
89
|
|
|
* @see self::offsetGet() |
|
90
|
|
|
* @param string $key The key of the configuration item to look for. |
|
91
|
|
|
* @return mixed |
|
92
|
|
|
*/ |
|
93
|
|
|
public function get($key) |
|
94
|
|
|
{ |
|
95
|
|
|
return $this[$key]; |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
/** |
|
99
|
|
|
* Assign a value to the specified key of the configuration. |
|
100
|
|
|
* |
|
101
|
|
|
* Public method variant of setting by array key. |
|
102
|
|
|
* |
|
103
|
|
|
* @see self::offsetSet() |
|
104
|
|
|
* @param string $key The key to assign $value to. |
|
105
|
|
|
* @param mixed $value Value to assign to $key. |
|
106
|
|
|
* @return self |
|
107
|
|
|
*/ |
|
108
|
|
|
public function set($key, $value) |
|
109
|
|
|
{ |
|
110
|
|
|
$this[$key] = $value; |
|
111
|
|
|
return $this; |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
/** |
|
115
|
|
|
* Determine if a configuration key exists. |
|
116
|
|
|
* |
|
117
|
|
|
* @see ArrayAccess::offsetExists() |
|
118
|
|
|
* @param string $key The key of the configuration item to look for. |
|
119
|
|
|
* @throws InvalidArgumentException If the key argument is not a string or is a "numeric" value. |
|
120
|
|
|
* @return boolean |
|
121
|
|
|
*/ |
|
122
|
|
|
public function offsetExists($key) |
|
123
|
|
|
{ |
|
124
|
|
|
if (is_numeric($key)) { |
|
125
|
|
|
throw new InvalidArgumentException( |
|
126
|
|
|
'Entity array access only supports non-numeric keys.' |
|
127
|
|
|
); |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
$key = $this->camelize($key); |
|
131
|
|
View Code Duplication |
if (is_callable([$this, $key])) { |
|
|
|
|
|
|
132
|
|
|
$value = $this->{$key}(); |
|
133
|
|
|
} else { |
|
134
|
|
|
if (!isset($this->{$key})) { |
|
135
|
|
|
return false; |
|
136
|
|
|
} |
|
137
|
|
|
$value = $this->{$key}; |
|
138
|
|
|
} |
|
139
|
|
|
return ($value !== null); |
|
140
|
|
|
} |
|
141
|
|
|
|
|
142
|
|
|
/** |
|
143
|
|
|
* Find an entry of the configuration by its key and retrieve it. |
|
144
|
|
|
* |
|
145
|
|
|
* @see ArrayAccess::offsetGet() |
|
146
|
|
|
* @param string $key The key of the configuration item to look for. |
|
147
|
|
|
* @throws InvalidArgumentException If the key argument is not a string or is a "numeric" value. |
|
148
|
|
|
* @return mixed The value (or null) |
|
149
|
|
|
*/ |
|
150
|
|
|
public function offsetGet($key) |
|
151
|
|
|
{ |
|
152
|
|
|
if (is_numeric($key)) { |
|
153
|
|
|
throw new InvalidArgumentException( |
|
154
|
|
|
'Entity array access only supports non-numeric keys.' |
|
155
|
|
|
); |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
$key = $this->camelize($key); |
|
159
|
|
|
|
|
160
|
|
View Code Duplication |
if (is_callable([$this, $key])) { |
|
|
|
|
|
|
161
|
|
|
return $this->{$key}(); |
|
162
|
|
|
} else { |
|
163
|
|
|
if (isset($this->{$key})) { |
|
164
|
|
|
return $this->{$key}; |
|
165
|
|
|
} else { |
|
166
|
|
|
return null; |
|
167
|
|
|
} |
|
168
|
|
|
} |
|
169
|
|
|
} |
|
170
|
|
|
|
|
171
|
|
|
/** |
|
172
|
|
|
* Assign a value to the specified key of the configuration. |
|
173
|
|
|
* |
|
174
|
|
|
* Set the value either by: |
|
175
|
|
|
* - a setter method (`set_{$key}()`) |
|
176
|
|
|
* - setting (or overriding) |
|
177
|
|
|
* |
|
178
|
|
|
* @see ArrayAccess::offsetSet() |
|
179
|
|
|
* @param string $key The key to assign $value to. |
|
180
|
|
|
* @param mixed $value Value to assign to $key. |
|
181
|
|
|
* @throws InvalidArgumentException If the key argument is not a string or is a "numeric" value. |
|
182
|
|
|
* @return void |
|
183
|
|
|
*/ |
|
184
|
|
|
public function offsetSet($key, $value) |
|
185
|
|
|
{ |
|
186
|
|
|
if (is_numeric($key)) { |
|
187
|
|
|
throw new InvalidArgumentException( |
|
188
|
|
|
'Entity array access only supports non-numeric keys.' |
|
189
|
|
|
); |
|
190
|
|
|
} |
|
191
|
|
|
|
|
192
|
|
|
$key = $this->camelize($key); |
|
193
|
|
|
$setter = 'set'.ucfirst($key); |
|
194
|
|
|
|
|
195
|
|
|
// Case: url.com?_=something |
|
196
|
|
|
if ($setter === 'set') { |
|
197
|
|
|
return; |
|
198
|
|
|
} |
|
199
|
|
|
|
|
200
|
|
View Code Duplication |
if (is_callable([$this, $setter])) { |
|
|
|
|
|
|
201
|
|
|
$this->{$setter}($value); |
|
202
|
|
|
} else { |
|
203
|
|
|
$this->{$key} = $value; |
|
204
|
|
|
} |
|
205
|
|
|
$this->keys[$key] = true; |
|
206
|
|
|
} |
|
207
|
|
|
|
|
208
|
|
|
/** |
|
209
|
|
|
* ArrayAccess > offsetUnset() |
|
210
|
|
|
* |
|
211
|
|
|
* @param string $key The key of the configuration item to remove. |
|
212
|
|
|
* @throws InvalidArgumentException If the key argument is not a string or is a "numeric" value. |
|
213
|
|
|
* @return void |
|
214
|
|
|
*/ |
|
215
|
|
|
public function offsetUnset($key) |
|
216
|
|
|
{ |
|
217
|
|
|
if (is_numeric($key)) { |
|
218
|
|
|
throw new InvalidArgumentException( |
|
219
|
|
|
'Entity array access only supports non-numeric keys.' |
|
220
|
|
|
); |
|
221
|
|
|
} |
|
222
|
|
|
$key = $this->camelize($key); |
|
223
|
|
|
$this[$key] = null; |
|
224
|
|
|
unset($this->keys[$key]); |
|
225
|
|
|
} |
|
226
|
|
|
/** |
|
227
|
|
|
* JsonSerializable > jsonSerialize() |
|
228
|
|
|
* |
|
229
|
|
|
* @return array |
|
230
|
|
|
*/ |
|
231
|
|
|
public function jsonSerialize() |
|
232
|
|
|
{ |
|
233
|
|
|
return $this->data(); |
|
234
|
|
|
} |
|
235
|
|
|
|
|
236
|
|
|
/** |
|
237
|
|
|
* Serializable > serialize() |
|
238
|
|
|
* |
|
239
|
|
|
* @return string |
|
240
|
|
|
*/ |
|
241
|
|
|
public function serialize() |
|
242
|
|
|
{ |
|
243
|
|
|
return serialize($this->data()); |
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
|
|
/** |
|
247
|
|
|
* Serializable > unserialize() |
|
248
|
|
|
* |
|
249
|
|
|
* @param string $serialized The serialized data (with `serialize()`). |
|
250
|
|
|
* @return void |
|
251
|
|
|
*/ |
|
252
|
|
|
public function unserialize($serialized) |
|
253
|
|
|
{ |
|
254
|
|
|
$unserialized = unserialize($serialized); |
|
255
|
|
|
$this->setData($unserialized); |
|
|
|
|
|
|
256
|
|
|
} |
|
257
|
|
|
|
|
258
|
|
|
/** |
|
259
|
|
|
* Transform a snake_case string to camelCase. |
|
260
|
|
|
* |
|
261
|
|
|
* @param string $str The snake_case string to camelize. |
|
262
|
|
|
* @return string The camelcase'd string. |
|
263
|
|
|
*/ |
|
264
|
|
|
final protected function camelize($str) |
|
265
|
|
|
{ |
|
266
|
|
|
if (strstr($str, '_') === false) { |
|
267
|
|
|
return $str; |
|
268
|
|
|
} |
|
269
|
|
|
return lcfirst(implode('', array_map('ucfirst', explode('_', $str)))); |
|
270
|
|
|
} |
|
271
|
|
|
} |
|
272
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.