Completed
Pull Request — master (#23)
by Evan
05:41 queued 02:40
created

Model::make()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 2
eloc 4
c 2
b 0
f 1
nc 2
nop 0
dl 0
loc 8
rs 9.4285
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
            $expanded = $this->expandAlias($key);
93
            $this->object->$expanded = $value;
94
        }
95
96
        return $this;
97
    }
98
99
    /**
100
     * Create a new model of the model's type, and save it to the database.
101
     *
102
     * @param  array $attributes
103
     *
104
     * @return static
105
     */
106
    public static function create($attributes = [])
107
    {
108
        $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...
109
110
        return $model->save();
111
    }
112
113
    /**
114
     * Create a new query builder instance for this model type.
115
     *
116
     * @return \Silk\Contracts\BuildsQueries
117
     */
118
    public static function query()
119
    {
120
        return (new static)->newQuery();
121
    }
122
123
    /**
124
     * Meta API for this type
125
     *
126
     * @param  string $key  Meta key to retrieve or empty to retrieve all.
127
     *
128
     * @return ObjectMeta|\Silk\Meta\Meta
129
     */
130
    public function meta($key = '')
131
    {
132
        $meta = new ObjectMeta(static::OBJECT_TYPE, $this->id);
133
134
        if ($key) {
135
            return $meta->get($key);
136
        }
137
138
        return $meta;
139
    }
140
141
    /**
142
     * Set the primary ID on the model.
143
     *
144
     * @param string|int $id  The model's ID
145
     *
146
     * @return $this
147
     */
148
    protected function setId($id)
149
    {
150
        $this->object->{static::ID_PROPERTY} = (int) $id;
151
152
        return $this;
153
    }
154
155
    /**
156
     * Expands an alias into its respective object property name.
157
     *
158
     * @param string $key  Alias key
159
     *
160
     * @return mixed|string
161
     */
162
    protected function expandAlias($key)
163
    {
164
        if (isset($this->objectAliases[$key])) {
165
            return $this->objectAliases[$key];
166
        }
167
168
        return $key;
169
    }
170
171
    /**
172
     * Magic getter.
173
     *
174
     * @param  string $property
175
     *
176
     * @return mixed
177
     */
178
    public function __get($property)
179
    {
180
        if ($property == 'id') {
181
            return $this->object->{static::ID_PROPERTY};
182
        }
183
184
        if (in_array($property, ['object', static::OBJECT_TYPE])) {
185
            return $this->object;
186
        }
187
188
        $property = $this->expandAlias($property);
189
190
        /**
191
         * Finally, hand-off the request to the wrapped object.
192
         * We don't check for existence as we leverage the magic __get
193
         * on the wrapped object as well.
194
         */
195
        return $this->object->$property;
196
    }
197
198
    /**
199
     * Magic Isset Checker.
200
     *
201
     * @return bool
202
     */
203
    public function __isset($property)
204
    {
205
        return ! is_null($this->__get($property));
206
    }
207
208
    /**
209
     * Magic setter.
210
     *
211
     * @param string $property  The property name
212
     * @param mixed  $value     The new property value
213
     */
214
    public function __set($property, $value)
215
    {
216
        $property = $this->expandAlias($property);
217
218
        $this->object->$property = $value;
219
    }
220
221
    /**
222
     * Handle dynamic method calls into the model.
223
     *
224
     * @param  string $method
225
     * @param  array $arguments
226
     *
227
     * @return mixed
228
     */
229
    public function __call($method, $arguments)
230
    {
231
        $query = $this->newQuery();
232
233
        return call_user_func_array([$query, $method], $arguments);
234
    }
235
236
    /**
237
     * Handle dynamic static method calls on the model class.
238
     *
239
     * Proxies calls to direct method calls on a new instance
240
     *
241
     * @param string $method
242
     * @param array $arguments
243
     *
244
     * @return mixed
245
     */
246
    public static function __callStatic($method, array $arguments)
247
    {
248
        return call_user_func_array([new static, $method], $arguments);
249
    }
250
}
251