Completed
Push — develop ( 07d619...391d38 )
by Evan
05:11 queued 02:23
created

Model::getAliasedObject()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
cc 1
eloc 2
nc 1
nop 0
rs 10
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'
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
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);
0 ignored issues
show
Unused Code introduced by
The call to Model::__construct() has too many arguments starting with $attributes.

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.

Loading history...
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
        if (! $expanded = $this->expandAlias($key)) {
184
            return false;
185
        }
186
187
        if (is_object($aliased = $this->getAliasedObject())) {
188
            $aliased->$expanded = $value;
189
            return true;
190
        }
191
192
        return false;
193
    }
194
195
    /**
196
     * Get a property from the aliased object by the model's key.
197
     *
198
     * @param $key
199
     *
200
     * @return mixed|null
201
     */
202
    protected function aliasGet($key)
203
    {
204
        if (! $expanded = $this->expandAlias($key)) {
205
            return null;
206
        }
207
208
        return data_get($this->getAliasedObject(), $expanded);
209
    }
210
211
    /**
212
     * Get the aliased object instance.
213
     *
214
     * @return object
215
     */
216
    protected function getAliasedObject()
217
    {
218
        return $this->object;
219
    }
220
221
    /**
222
     * Expands an alias into its respective object property name.
223
     *
224
     * @param string $key  Alias key
225
     *
226
     * @return string|false  The expanded alias, or false no alias exists for the key.
227
     */
228
    protected function expandAlias($key)
229
    {
230
        return data_get($this->objectAliases, $key, false);
231
    }
232
233
    /**
234
     * Magic getter.
235
     *
236
     * @param  string $property
237
     *
238
     * @return mixed
239
     */
240
    public function __get($property)
241
    {
242
        if ($property == 'id') {
243
            return $this->object->{static::ID_PROPERTY};
244
        }
245
246
        if (in_array($property, ['object', static::OBJECT_TYPE])) {
247
            return $this->object;
248
        }
249
250
        if (! is_null($aliased = $this->aliasGet($property))) {
251
            return $aliased;
252
        }
253
254
        /**
255
         * Finally, hand-off the request to the wrapped object.
256
         * We don't check for existence as we leverage the magic __get
257
         * on the wrapped object as well.
258
         */
259
        return $this->object->$property;
260
    }
261
262
    /**
263
     * Magic Isset Checker.
264
     *
265
     * @return bool
266
     */
267
    public function __isset($property)
268
    {
269
        return ! is_null($this->__get($property));
270
    }
271
272
    /**
273
     * Magic setter.
274
     *
275
     * @param string $property  The property name
276
     * @param mixed  $value     The new property value
277
     */
278
    public function __set($property, $value)
279
    {
280
        if ($this->aliasSet($property, $value)) {
281
            return;
282
        }
283
284
        $this->object->$property = $value;
285
    }
286
287
    /**
288
     * Handle dynamic method calls into the model.
289
     *
290
     * @param  string $method
291
     * @param  array $arguments
292
     *
293
     * @return mixed
294
     */
295
    public function __call($method, $arguments)
296
    {
297
        $query = $this->newQuery();
298
299
        return call_user_func_array([$query, $method], $arguments);
300
    }
301
302
    /**
303
     * Handle dynamic static method calls on the model class.
304
     *
305
     * Proxies calls to direct method calls on a new instance
306
     *
307
     * @param string $method
308
     * @param array $arguments
309
     *
310
     * @return mixed
311
     */
312
    public static function __callStatic($method, array $arguments)
313
    {
314
        return call_user_func_array([new static, $method], $arguments);
315
    }
316
}
317