1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Silk\Type; |
4
|
|
|
|
5
|
|
|
use Silk\Meta\ObjectMeta; |
6
|
|
|
use Illuminate\Support\Collection; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* @property-read int $id |
10
|
|
|
* @property-read object $object |
11
|
|
|
*/ |
12
|
|
|
abstract class Model |
13
|
|
|
{ |
14
|
|
|
/** |
15
|
|
|
* The core model object |
16
|
|
|
* @var object |
17
|
|
|
*/ |
18
|
|
|
protected $object; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Type object property aliases |
22
|
|
|
* @var array |
23
|
|
|
*/ |
24
|
|
|
protected $objectAliases = [ |
25
|
|
|
// 'aliasName' => 'propertyNameOnObject' |
|
|
|
|
26
|
|
|
]; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* The object type in WordPress |
30
|
|
|
*/ |
31
|
|
|
const OBJECT_TYPE = ''; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* The name of the primary ID property on the object |
35
|
|
|
*/ |
36
|
|
|
const ID_PROPERTY = ''; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Get a new query builder for the model. |
40
|
|
|
* |
41
|
|
|
* @return \Silk\Contracts\BuildsQueries |
42
|
|
|
*/ |
43
|
|
|
abstract public function newQuery(); |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Save the changes to the database. |
47
|
|
|
* |
48
|
|
|
* @return $this |
49
|
|
|
*/ |
50
|
|
|
abstract public function save(); |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Delete the modeled record from the database. |
54
|
|
|
* |
55
|
|
|
* @return $this |
56
|
|
|
*/ |
57
|
|
|
abstract public function delete(); |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Reload the object from the database. |
61
|
|
|
* |
62
|
|
|
* @return $this |
63
|
|
|
*/ |
64
|
|
|
abstract public function refresh(); |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Make new instance. |
68
|
|
|
* |
69
|
|
|
* All provided arguments are forwarded to the constructor of the called class. |
70
|
|
|
* |
71
|
|
|
* @return static |
72
|
|
|
*/ |
73
|
|
|
public static function make() |
74
|
|
|
{ |
75
|
|
|
if ($arguments = func_get_args()) { |
76
|
|
|
return (new \ReflectionClass(static::class))->newInstanceArgs($arguments); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
return new static; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Fill the model with an array of attributes. |
84
|
|
|
* |
85
|
|
|
* @param array $attributes |
86
|
|
|
* |
87
|
|
|
* @return $this |
88
|
|
|
*/ |
89
|
|
|
public function fill(array $attributes) |
90
|
|
|
{ |
91
|
|
|
foreach ($attributes as $key => $value) { |
92
|
|
|
if ($this->expandAlias($key)) { |
93
|
|
|
$this->aliasSet($key, $value); |
94
|
|
|
continue; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
$this->object->$key = $value; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
return $this; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Create a new model of the model's type, and save it to the database. |
105
|
|
|
* |
106
|
|
|
* @param array $attributes |
107
|
|
|
* |
108
|
|
|
* @return static |
109
|
|
|
*/ |
110
|
|
|
public static function create($attributes = []) |
111
|
|
|
{ |
112
|
|
|
$model = new static($attributes); |
|
|
|
|
113
|
|
|
|
114
|
|
|
return $model->save(); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Create a new query builder instance for this model type. |
119
|
|
|
* |
120
|
|
|
* @return \Silk\Contracts\BuildsQueries |
121
|
|
|
*/ |
122
|
|
|
public static function query() |
123
|
|
|
{ |
124
|
|
|
return (new static)->newQuery(); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Meta API for this type |
129
|
|
|
* |
130
|
|
|
* @param string $key Meta key to retrieve or empty to retrieve all. |
131
|
|
|
* |
132
|
|
|
* @return ObjectMeta|\Silk\Meta\Meta |
133
|
|
|
*/ |
134
|
|
|
public function meta($key = '') |
135
|
|
|
{ |
136
|
|
|
$meta = new ObjectMeta(static::OBJECT_TYPE, $this->id); |
137
|
|
|
|
138
|
|
|
if ($key) { |
139
|
|
|
return $meta->get($key); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
return $meta; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Set the primary ID on the model. |
147
|
|
|
* |
148
|
|
|
* @param string|int $id The model's ID |
149
|
|
|
* |
150
|
|
|
* @return $this |
151
|
|
|
*/ |
152
|
|
|
protected function setId($id) |
153
|
|
|
{ |
154
|
|
|
$this->object->{static::ID_PROPERTY} = (int) $id; |
155
|
|
|
|
156
|
|
|
return $this; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* Set the object for the model. |
161
|
|
|
* |
162
|
|
|
* @param $object |
163
|
|
|
* |
164
|
|
|
* @return $this |
165
|
|
|
*/ |
166
|
|
|
protected function setObject($object) |
167
|
|
|
{ |
168
|
|
|
$this->object = $object; |
169
|
|
|
|
170
|
|
|
return $this; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* Set a property on the aliased object. |
175
|
|
|
* |
176
|
|
|
* @param string $key The alias name on the model |
177
|
|
|
* @param mixed $value The value to set on the aliased object |
178
|
|
|
* |
179
|
|
|
* @return bool True if the alias was resolved and set; otherwise false |
180
|
|
|
*/ |
181
|
|
|
protected function aliasSet($key, $value) |
182
|
|
|
{ |
183
|
|
|
$expanded = $this->expandAlias($key); |
184
|
|
|
|
185
|
|
|
if ($expanded && is_object($aliased = $this->getAliasedObject())) { |
|
|
|
|
186
|
|
|
$aliased->$expanded = $value; |
187
|
|
|
return true; |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
return false; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Get a property from the aliased object by the model's key. |
195
|
|
|
* |
196
|
|
|
* @param $key |
197
|
|
|
* |
198
|
|
|
* @return mixed|null |
199
|
|
|
*/ |
200
|
|
|
protected function aliasGet($key) |
201
|
|
|
{ |
202
|
|
|
if (! $expanded = $this->expandAlias($key)) { |
203
|
|
|
return null; |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
return data_get($this->getAliasedObject(), $expanded); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Get the aliased object instance. |
211
|
|
|
* |
212
|
|
|
* @return object |
213
|
|
|
*/ |
214
|
|
|
protected function getAliasedObject() |
215
|
|
|
{ |
216
|
|
|
return $this->object; |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* Expands an alias into its respective object property name. |
221
|
|
|
* |
222
|
|
|
* @param string $key Alias key |
223
|
|
|
* |
224
|
|
|
* @return string|false The expanded alias, or false no alias exists for the key. |
225
|
|
|
*/ |
226
|
|
|
protected function expandAlias($key) |
227
|
|
|
{ |
228
|
|
|
return data_get($this->objectAliases, $key, false); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* Magic getter. |
233
|
|
|
* |
234
|
|
|
* @param string $property |
235
|
|
|
* |
236
|
|
|
* @return mixed |
237
|
|
|
*/ |
238
|
|
|
public function __get($property) |
239
|
|
|
{ |
240
|
|
|
if ($property == 'id') { |
241
|
|
|
return $this->object->{static::ID_PROPERTY}; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
if (in_array($property, ['object', static::OBJECT_TYPE])) { |
245
|
|
|
return $this->object; |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
if (! is_null($aliased = $this->aliasGet($property))) { |
249
|
|
|
return $aliased; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Finally, hand-off the request to the wrapped object. |
254
|
|
|
* We don't check for existence as we leverage the magic __get |
255
|
|
|
* on the wrapped object as well. |
256
|
|
|
*/ |
257
|
|
|
return $this->object->$property; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* Magic Isset Checker. |
262
|
|
|
* |
263
|
|
|
* @return bool |
264
|
|
|
*/ |
265
|
|
|
public function __isset($property) |
266
|
|
|
{ |
267
|
|
|
return ! is_null($this->__get($property)); |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* Magic setter. |
272
|
|
|
* |
273
|
|
|
* @param string $property The property name |
274
|
|
|
* @param mixed $value The new property value |
275
|
|
|
*/ |
276
|
|
|
public function __set($property, $value) |
277
|
|
|
{ |
278
|
|
|
if ($this->aliasSet($property, $value)) { |
279
|
|
|
return; |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
$this->object->$property = $value; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* Handle dynamic method calls into the model. |
287
|
|
|
* |
288
|
|
|
* @param string $method |
289
|
|
|
* @param array $arguments |
290
|
|
|
* |
291
|
|
|
* @return mixed |
292
|
|
|
*/ |
293
|
|
|
public function __call($method, $arguments) |
294
|
|
|
{ |
295
|
|
|
$query = $this->newQuery(); |
296
|
|
|
|
297
|
|
|
return call_user_func_array([$query, $method], $arguments); |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
/** |
301
|
|
|
* Handle dynamic static method calls on the model class. |
302
|
|
|
* |
303
|
|
|
* Proxies calls to direct method calls on a new instance |
304
|
|
|
* |
305
|
|
|
* @param string $method |
306
|
|
|
* @param array $arguments |
307
|
|
|
* |
308
|
|
|
* @return mixed |
309
|
|
|
*/ |
310
|
|
|
public static function __callStatic($method, array $arguments) |
311
|
|
|
{ |
312
|
|
|
return call_user_func_array([new static, $method], $arguments); |
313
|
|
|
} |
314
|
|
|
} |
315
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.