These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Silk\Type; |
||
4 | |||
5 | use Silk\Meta\ObjectMeta; |
||
6 | |||
7 | /** |
||
8 | * @property-read int $id |
||
9 | * @property-read object $object |
||
10 | */ |
||
11 | abstract class Model |
||
12 | { |
||
13 | use ObjectAliases; |
||
14 | |||
15 | /** |
||
16 | * The core model object |
||
17 | * @var object |
||
18 | */ |
||
19 | protected $object; |
||
20 | |||
21 | /** |
||
22 | * The object type in WordPress |
||
23 | */ |
||
24 | const OBJECT_TYPE = ''; |
||
25 | |||
26 | /** |
||
27 | * The name of the primary ID property on the object |
||
28 | */ |
||
29 | const ID_PROPERTY = ''; |
||
30 | |||
31 | /** |
||
32 | * Get a new query builder for the model. |
||
33 | * |
||
34 | * @return \Silk\Contracts\Query\BuildsQueries |
||
35 | */ |
||
36 | abstract public function newQuery(); |
||
37 | |||
38 | /** |
||
39 | * Save the changes to the database. |
||
40 | * |
||
41 | * @return $this |
||
42 | */ |
||
43 | abstract public function save(); |
||
44 | |||
45 | /** |
||
46 | * Delete the modeled record from the database. |
||
47 | * |
||
48 | * @return $this |
||
49 | */ |
||
50 | abstract public function delete(); |
||
51 | |||
52 | /** |
||
53 | * Reload the object from the database. |
||
54 | * |
||
55 | * @return $this |
||
56 | */ |
||
57 | abstract public function refresh(); |
||
58 | |||
59 | /** |
||
60 | * Make new instance. |
||
61 | * |
||
62 | * All provided arguments are forwarded to the constructor of the called class. |
||
63 | * |
||
64 | * @throws \ReflectionException |
||
65 | * |
||
66 | * @return object|Model |
||
67 | */ |
||
68 | public static function make() |
||
69 | { |
||
70 | if ($arguments = func_get_args()) { |
||
71 | return (new \ReflectionClass(static::class))->newInstanceArgs($arguments); |
||
72 | } |
||
73 | |||
74 | return new static; |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * Fill the model with an array of attributes. |
||
79 | * |
||
80 | * @param array $attributes |
||
81 | * |
||
82 | * @return $this |
||
83 | */ |
||
84 | public function fill(array $attributes) |
||
85 | { |
||
86 | foreach ($attributes as $key => $value) { |
||
87 | if ($this->expandAlias($key)) { |
||
88 | $this->aliasSet($key, $value); |
||
89 | continue; |
||
90 | } |
||
91 | |||
92 | $this->object->$key = $value; |
||
93 | } |
||
94 | |||
95 | return $this; |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * Create a new model of the model's type, and save it to the database. |
||
100 | * |
||
101 | * @param array $attributes |
||
102 | * |
||
103 | * @return static |
||
104 | */ |
||
105 | public static function create($attributes = []) |
||
106 | { |
||
107 | $model = new static($attributes); |
||
0 ignored issues
–
show
|
|||
108 | |||
109 | return $model->save(); |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * Create a new query builder instance for this model type. |
||
114 | * |
||
115 | * @return \Silk\Contracts\Query\BuildsQueries |
||
116 | */ |
||
117 | public static function query() |
||
118 | { |
||
119 | return (new static)->newQuery(); |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Meta API for this type |
||
124 | * |
||
125 | * @param string $key Meta key to retrieve or empty to retrieve all. |
||
126 | * |
||
127 | * @return ObjectMeta|\Silk\Meta\Meta |
||
128 | */ |
||
129 | public function meta($key = '') |
||
130 | { |
||
131 | $meta = new ObjectMeta(static::OBJECT_TYPE, $this->id); |
||
132 | |||
133 | if ($key) { |
||
134 | return $meta->get($key); |
||
135 | } |
||
136 | |||
137 | return $meta; |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * Set the primary ID on the model. |
||
142 | * |
||
143 | * @param string|int $id The model's ID |
||
144 | * |
||
145 | * @return $this |
||
146 | */ |
||
147 | protected function setId($id) |
||
148 | { |
||
149 | $this->object->{static::ID_PROPERTY} = (int) $id; |
||
150 | |||
151 | return $this; |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * Set the object for the model. |
||
156 | * |
||
157 | * @param $object |
||
158 | * |
||
159 | * @return $this |
||
160 | */ |
||
161 | protected function setObject($object) |
||
162 | { |
||
163 | $this->object = $object; |
||
164 | |||
165 | return $this; |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * @return array |
||
170 | */ |
||
171 | protected function objectAliases() |
||
172 | { |
||
173 | return []; |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * @return object |
||
178 | */ |
||
179 | protected function getAliasedObject() |
||
180 | { |
||
181 | return $this->object; |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * Magic getter. |
||
186 | * |
||
187 | * @param string $property |
||
188 | * |
||
189 | * @return mixed |
||
190 | */ |
||
191 | public function __get($property) |
||
192 | { |
||
193 | if ($property == 'id') { |
||
194 | return $this->object->{static::ID_PROPERTY}; |
||
195 | } |
||
196 | |||
197 | if (in_array($property, ['object', static::OBJECT_TYPE])) { |
||
198 | return $this->object; |
||
199 | } |
||
200 | |||
201 | if (! is_null($aliased = $this->aliasGet($property))) { |
||
202 | return $aliased; |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * Finally, hand-off the request to the wrapped object. |
||
207 | * We don't check for existence as we leverage the magic __get |
||
208 | * on the wrapped object as well. |
||
209 | */ |
||
210 | return $this->object->$property; |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * Magic Isset Checker. |
||
215 | * |
||
216 | * @param $property |
||
217 | * |
||
218 | * @return bool |
||
219 | */ |
||
220 | public function __isset($property) |
||
221 | { |
||
222 | return ! is_null($this->__get($property)); |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * Magic setter. |
||
227 | * |
||
228 | * @param string $property The property name |
||
229 | * @param mixed $value The new property value |
||
230 | */ |
||
231 | public function __set($property, $value) |
||
232 | { |
||
233 | if ($this->aliasSet($property, $value)) { |
||
234 | return; |
||
235 | } |
||
236 | |||
237 | $this->object->$property = $value; |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * Handle dynamic method calls into the model. |
||
242 | * |
||
243 | * @param string $method |
||
244 | * @param array $arguments |
||
245 | * |
||
246 | * @return mixed |
||
247 | */ |
||
248 | public function __call($method, $arguments) |
||
249 | { |
||
250 | $query = $this->newQuery(); |
||
251 | |||
252 | return call_user_func_array([$query, $method], $arguments); |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * Handle dynamic static method calls on the model class. |
||
257 | * |
||
258 | * Proxies calls to direct method calls on a new instance |
||
259 | * |
||
260 | * @param string $method |
||
261 | * @param array $arguments |
||
262 | * |
||
263 | * @return mixed |
||
264 | */ |
||
265 | public static function __callStatic($method, array $arguments) |
||
266 | { |
||
267 | return call_user_func_array([new static, $method], $arguments); |
||
268 | } |
||
269 | } |
||
270 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.