Passed
Pull Request — master (#427)
by
unknown
01:47
created

Model::getFillable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 1
c 1
b 0
f 1
dl 0
loc 2
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Picqer\Financials\Exact;
4
5
/**
6
 * Class Model.
7
 */
8
abstract class Model implements \JsonSerializable
9
{
10
    /**
11
     * @var Connection
12
     */
13
    protected $connection;
14
15
    /**
16
     * @var array The model's attributes
17
     */
18
    protected $attributes = [];
19
20
    /**
21
     * @deferred array The model's collection values
22
     */
23
    protected $deferred = [];
24
25
    /**
26
     * @var array The model's fillable attributes
27
     */
28
    protected $fillable = [];
29
30
    /**
31
     * @var string The URL endpoint of this model
32
     */
33
    protected $url = '';
34
35
    /**
36
     * @var string Name of the primary key for this model
37
     */
38
    protected $primaryKey = 'ID';
39
40
    public function __construct(Connection $connection, array $attributes = [])
41
    {
42
        $this->connection = $connection;
43
        $this->fill($attributes);
44
    }
45
46
    /**
47
     * Get the connection instance.
48
     *
49
     * @return Connection
50
     */
51
    public function connection()
52
    {
53
        return $this->connection;
54
    }
55
56
    /**
57
     * Get the model's attributes.
58
     *
59
     * @return array
60
     */
61
    public function attributes()
62
    {
63
        return $this->attributes;
64
    }
65
66
    /**
67
     * Get the model's url.
68
     *
69
     * @return string
70
     */
71
    public function url()
72
    {
73
        return $this->url;
74
    }
75
76
    /**
77
     * Get the model's primary key.
78
     *
79
     * @return string
80
     */
81
    public function primaryKey()
82
    {
83
        return $this->primaryKey;
84
    }
85
86
    /**
87
     * Get the model's primary key value.
88
     *
89
     * @return mixed
90
     */
91
    public function primaryKeyContent()
92
    {
93
        return $this->__get($this->primaryKey);
94
    }
95
96
    /**
97
     * Fill the entity from an array.
98
     *
99
     * @param array $attributes
100
     */
101
    protected function fill(array $attributes)
102
    {
103
        foreach ($this->fillableFromArray($attributes) as $key => $value) {
104
            if ($this->isFillable($key)) {
105
                $this->setAttribute($key, $value);
106
            }
107
        }
108
    }
109
110
    /**
111
     * Get the fillable attributes of an array.
112
     *
113
     * @param array $attributes
114
     *
115
     * @return array
116
     */
117
    protected function fillableFromArray(array $attributes)
118
    {
119
        if (count($this->fillable) > 0) {
120
            return array_intersect_key($attributes, array_flip($this->fillable));
121
        }
122
123
        return $attributes;
124
    }
125
126
    protected function isFillable($key)
127
    {
128
        return in_array($key, $this->fillable);
129
    }
130
131
    public function getFillable(){
132
        return $this->fillable;
133
    }
134
135
    protected function setAttribute($key, $value)
136
    {
137
        $this->attributes[$key] = $value;
138
    }
139
140
    /**
141
     * Resolve deferred values.
142
     *
143
     * @param string $key
144
     *
145
     * @return bool Returns true when collection is found
146
     */
147
    protected function lazyLoad($key)
148
    {
149
        // Check previously resolved or manualy set.
150
        if (isset($this->deferred[$key])) {
151
            return true;
152
        }
153
154
        try {
155
            if (array_key_exists($key, $this->attributes) && is_array($this->attributes[$key]) && array_key_exists('__deferred', $this->attributes[$key])) {
156
                $class = preg_replace('/(.+?)s?$/', __NAMESPACE__ . '\\\$1', $key); // Filter plural 's' and add namespace
157
                $deferred = new $class($this->connection());
158
                $uri = $this->attributes[$key]['__deferred']['uri'];
159
                $deferred->connection()->nextUrl = $uri; // $uri is complete, by setting it to nextUrl Connection->formatUrl leaves it as is.
160
                $result = $deferred->connection()->get($uri);
161
                $this->deferred[$key] = $deferred->collectionFromResult($result);
162
163
                return true;
164
            }
165
        } catch (\Exception $e) {
166
            // We tried lets leave it as is.
167
        }
168
169
        return false;
170
    }
171
172
    public function __get($key)
173
    {
174
        if ($this->lazyLoad($key)) {
175
            return $this->deferred[$key];
176
        }
177
178
        if (isset($this->attributes[$key])) {
179
            return $this->attributes[$key];
180
        }
181
    }
182
183
    public function __set($key, $value)
184
    {
185
        if ($this->isFillable($key)) {
186
            if (is_array($value)) {
187
                $this->deferred[$key] = $value;
188
189
                return;
190
            }
191
192
            $this->setAttribute($key, $value);
193
        }
194
    }
195
196
    public function __isset($name)
197
    {
198
        return $this->__get($name) !== null;
199
    }
200
201
    public function __call($name, $arguments)
202
    {
203
        return $this->__get($name);
204
    }
205
206
    /**
207
     * Refresh deferred item by clearing and then lazy loading it.
208
     *
209
     * @param $key
210
     *
211
     * @return mixed
212
     */
213
    public function refresh($key)
214
    {
215
        unset($this->deferred[$key]);
216
217
        return $this->__get($key);
218
    }
219
220
    /**
221
     * Checks if primaryKey holds a value.
222
     *
223
     * @return bool
224
     */
225
    public function exists()
226
    {
227
        if (! array_key_exists($this->primaryKey, $this->attributes)) {
228
            return false;
229
        }
230
231
        return ! empty($this->attributes[$this->primaryKey]);
232
    }
233
234
    /**
235
     * Return the JSON representation of the data.
236
     *
237
     * @param int $options http://php.net/manual/en/json.constants.php
238
     *
239
     * @return string
240
     */
241
    public function json($options = 0, $withDeferred = false)
242
    {
243
        $attributes = $this->attributes;
244
        if ($withDeferred) {
245
            foreach ($this->deferred as $attribute => $collection) {
246
                if (empty($collection)) {
247
                    continue; // Leave orriginal array with __deferred key
248
                }
249
250
                $attributes[$attribute] = [];
251
                foreach ($collection as $value) {
252
                    if (! empty($value->deferred)) {
253
                        $value->attributes = array_merge($value->attributes, $value->deferred);
254
                    }
255
256
                    if (is_a($value, 'Picqer\Financials\Exact\Model')) {
257
                        array_push($attributes[$attribute], $value->attributes);
258
                    } else {
259
                        array_push($attributes[$attribute], $value);
260
                    }
261
                }
262
            }
263
        }
264
265
        return json_encode($attributes, $options);
266
    }
267
268
    /**
269
     * Return serializable data.
270
     *
271
     * @return array
272
     */
273
    public function jsonSerialize()
274
    {
275
        return $this->attributes;
276
    }
277
278
    /**
279
     * Check whether the current user has rights for an action on this endpoint
280
     * https://start.exactonline.nl/docs/HlpRestAPIResources.aspx?SourceAction=10.
281
     *
282
     * @param string $action
283
     *
284
     * @return bool
285
     */
286
    public function userHasRights($action = 'GET')
287
    {
288
        $action = preg_match('/^GET|POST|PUT|DELETE$/i', $action) ? strtoupper($action) : 'GET';
289
        $result = $this->connection()->get('users/UserHasRights', [
290
            'endpoint' => "'{$this->url}'",
291
            'action'   => "'{$action}'",
292
        ]);
293
294
        return isset($result['UserHasRights']) ? $result['UserHasRights'] : null;
295
    }
296
}
297