1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace As3\Modlr\Models; |
4
|
|
|
|
5
|
|
|
use As3\Modlr\Store\Store; |
6
|
|
|
use As3\Modlr\Metadata\EntityMetadata; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Represents the properties of a Model. |
10
|
|
|
* |
11
|
|
|
* @author Jacob Bare <[email protected]> |
12
|
|
|
*/ |
13
|
|
|
abstract class Properties |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* The original property values. |
17
|
|
|
* |
18
|
|
|
* @var array |
19
|
|
|
*/ |
20
|
|
|
protected $original = []; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* The current/modified property values. |
24
|
|
|
* |
25
|
|
|
* @var array |
26
|
|
|
*/ |
27
|
|
|
protected $current = []; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Any properties that have been flagged for removal. |
31
|
|
|
* |
32
|
|
|
* @var array |
33
|
|
|
*/ |
34
|
|
|
protected $remove = []; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* Constructor. |
38
|
|
|
* |
39
|
|
|
* @param array $original Any original properties to apply. |
40
|
|
|
*/ |
41
|
|
|
public function __construct(array $original = []) |
42
|
|
|
{ |
43
|
|
|
$this->original = $original; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Gets the current value of an property. |
48
|
|
|
* |
49
|
|
|
* @param string $key The property key. |
50
|
|
|
* @return mixed |
51
|
|
|
*/ |
52
|
|
|
public function get($key) |
53
|
|
|
{ |
54
|
|
|
if ($this->willRemove($key)) { |
55
|
|
|
return null; |
56
|
|
|
} |
57
|
|
|
if (true === $this->willChange($key)) { |
58
|
|
|
return $this->getCurrent($key); |
59
|
|
|
} |
60
|
|
|
return $this->getOriginal($key); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Sets a new value to an property. |
65
|
|
|
* |
66
|
|
|
* @param string $key The property key. |
67
|
|
|
* @param mixed $value The value to set. |
68
|
|
|
* @return mixed |
69
|
|
|
*/ |
70
|
|
|
public function set($key, $value) |
71
|
|
|
{ |
72
|
|
|
if (null === $value) { |
73
|
|
|
return $this->remove($key); |
74
|
|
|
} |
75
|
|
|
$this->clearRemoval($key); |
76
|
|
|
|
77
|
|
|
$original = $this->getOriginal($key); |
78
|
|
|
if ($value === $original) { |
79
|
|
|
$this->clearChange($key); |
80
|
|
|
} else { |
81
|
|
|
if (($value instanceof \DateTime && $original instanceof \DateTime) && ($value->getTimestamp() === $original->getTimestamp())) { |
82
|
|
|
$this->clearChange($key); |
83
|
|
|
} else { |
84
|
|
|
$this->current[$key] = $value; |
85
|
|
|
} |
86
|
|
|
} |
87
|
|
|
return $this; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Sets a new value to an property. |
92
|
|
|
* |
93
|
|
|
* @param string $key The property key. |
94
|
|
|
* @return self |
95
|
|
|
*/ |
96
|
|
|
public function remove($key) |
97
|
|
|
{ |
98
|
|
|
if (false === $this->willRemove($key)) { |
99
|
|
|
$this->clearChange($key); |
100
|
|
|
if (true === $this->hasOriginal($key)) { |
101
|
|
|
$this->remove[] = $key; |
102
|
|
|
} |
103
|
|
|
} |
104
|
|
|
return $this; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Rolls back the properties to their original state. |
109
|
|
|
* |
110
|
|
|
* @return self |
111
|
|
|
*/ |
112
|
|
|
public function rollback() |
113
|
|
|
{ |
114
|
|
|
$this->current = []; |
115
|
|
|
$this->remove = []; |
116
|
|
|
return $this; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* Replaces the current properties with new ones. |
121
|
|
|
* Will revert/rollback any current changes. |
122
|
|
|
* |
123
|
|
|
* @param array $original |
124
|
|
|
* @return self |
125
|
|
|
*/ |
126
|
|
|
public function replace(array $original) |
127
|
|
|
{ |
128
|
|
|
$this->rollback(); |
129
|
|
|
$this->original = $original; |
130
|
|
|
return $this; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Deteremines if the properties have different values from their original state. |
136
|
|
|
* |
137
|
|
|
* @return bool |
138
|
|
|
*/ |
139
|
|
|
public function areDirty() |
140
|
|
|
{ |
141
|
|
|
return !empty($this->current) || !empty($this->remove); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Calculates any property changes. |
146
|
|
|
* |
147
|
|
|
* @return array |
148
|
|
|
*/ |
149
|
|
View Code Duplication |
public function calculateChangeSet() |
|
|
|
|
150
|
|
|
{ |
151
|
|
|
$set = []; |
152
|
|
|
foreach ($this->current as $key => $current) { |
153
|
|
|
$original = isset($this->original[$key]) ? $this->original[$key] : null; |
154
|
|
|
$set[$key]['old'] = $original; |
155
|
|
|
$set[$key]['new'] = $current; |
156
|
|
|
} |
157
|
|
|
foreach ($this->remove as $key) { |
158
|
|
|
$set[$key]['old'] = $this->original[$key]; |
159
|
|
|
$set[$key]['new'] = null; |
160
|
|
|
} |
161
|
|
|
ksort($set); |
162
|
|
|
return $set; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Clears an property from the removal queue. |
167
|
|
|
* |
168
|
|
|
* @param string $key The field key. |
169
|
|
|
* @return self |
170
|
|
|
*/ |
171
|
|
|
protected function clearRemoval($key) |
172
|
|
|
{ |
173
|
|
|
if (false === $this->willRemove($key)) { |
174
|
|
|
return $this; |
175
|
|
|
} |
176
|
|
|
$key = array_search($key, $this->remove); |
177
|
|
|
unset($this->remove[$key]); |
178
|
|
|
$this->remove = array_values($this->remove); |
179
|
|
|
return $this; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Clears an property as having been changed. |
184
|
|
|
* |
185
|
|
|
* @param string $key The field key. |
186
|
|
|
* @return self |
187
|
|
|
*/ |
188
|
|
|
protected function clearChange($key) |
189
|
|
|
{ |
190
|
|
|
if (true === $this->willChange($key)) { |
191
|
|
|
unset($this->current[$key]); |
192
|
|
|
} |
193
|
|
|
return $this; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* Determines if an property is in the removal queue. |
198
|
|
|
* |
199
|
|
|
* @param string $key The field key. |
200
|
|
|
* @return bool |
201
|
|
|
*/ |
202
|
|
|
protected function willRemove($key) |
203
|
|
|
{ |
204
|
|
|
return in_array($key, $this->remove); |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* Determines if an property has a new value. |
209
|
|
|
* |
210
|
|
|
* @param string $key The field key. |
211
|
|
|
* @return bool |
212
|
|
|
*/ |
213
|
|
|
protected function willChange($key) |
214
|
|
|
{ |
215
|
|
|
return null !== $this->getCurrent($key); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Determines if an property has an original value. |
220
|
|
|
* |
221
|
|
|
* @param string $key The field key. |
222
|
|
|
* @return bool |
223
|
|
|
*/ |
224
|
|
|
protected function hasOriginal($key) |
225
|
|
|
{ |
226
|
|
|
return null !== $this->getOriginal($key); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Gets the property's original value. |
231
|
|
|
* |
232
|
|
|
* @param string $key The field key. |
233
|
|
|
* @return mixed |
234
|
|
|
*/ |
235
|
|
|
protected function getOriginal($key) |
236
|
|
|
{ |
237
|
|
|
if (isset($this->original[$key])) { |
238
|
|
|
return $this->original[$key]; |
239
|
|
|
} |
240
|
|
|
return null; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* Gets all original properties. |
245
|
|
|
* |
246
|
|
|
* @return array |
247
|
|
|
*/ |
248
|
|
|
protected function getOriginalAll() |
249
|
|
|
{ |
250
|
|
|
return $this->original; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Gets all current properties. |
255
|
|
|
* |
256
|
|
|
* @return array |
257
|
|
|
*/ |
258
|
|
|
protected function getCurrentAll() |
259
|
|
|
{ |
260
|
|
|
return $this->current; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
/** |
264
|
|
|
* Gets the property's current value. |
265
|
|
|
* |
266
|
|
|
* @param string $key The field key. |
267
|
|
|
* @return mixed |
268
|
|
|
*/ |
269
|
|
|
protected function getCurrent($key) |
270
|
|
|
{ |
271
|
|
|
if (isset($this->current[$key])) { |
272
|
|
|
return $this->current[$key]; |
273
|
|
|
} |
274
|
|
|
return null; |
275
|
|
|
} |
276
|
|
|
} |
277
|
|
|
|
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.