Model::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 2
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
    protected function setAttribute($key, $value)
132
    {
133
        $this->attributes[$key] = $value;
134
    }
135
136
    /**
137
     * Resolve deferred values.
138
     *
139
     * @param string $key
140
     *
141
     * @return bool Returns true when collection is found
142
     */
143
    protected function lazyLoad($key)
144
    {
145
        // Check previously resolved or manualy set.
146
        if (isset($this->deferred[$key])) {
147
            return true;
148
        }
149
150
        try {
151
            if (array_key_exists($key, $this->attributes) && is_array($this->attributes[$key]) && array_key_exists('__deferred', $this->attributes[$key])) {
152
                $class = preg_replace('/(.+?)s?$/', __NAMESPACE__ . '\\\$1', $key); // Filter plural 's' and add namespace
153
                $deferred = new $class($this->connection());
154
                $uri = $this->attributes[$key]['__deferred']['uri'];
155
                $deferred->connection()->nextUrl = $uri; // $uri is complete, by setting it to nextUrl Connection->formatUrl leaves it as is.
156
                $result = $deferred->connection()->get($uri);
157
                $this->deferred[$key] = $deferred->collectionFromResult($result);
158
159
                return true;
160
            }
161
        } catch (\Exception $e) {
162
            // We tried lets leave it as is.
163
        }
164
165
        return false;
166
    }
167
168
    public function __get($key)
169
    {
170
        if ($this->lazyLoad($key)) {
171
            return $this->deferred[$key];
172
        }
173
174
        if (isset($this->attributes[$key])) {
175
            return $this->attributes[$key];
176
        }
177
    }
178
179
    public function __set($key, $value)
180
    {
181
        if ($this->isFillable($key)) {
182
            if (is_array($value)) {
183
                $this->deferred[$key] = $value;
184
185
                return;
186
            }
187
188
            $this->setAttribute($key, $value);
189
        }
190
    }
191
192
    public function __isset($name)
193
    {
194
        return $this->__get($name) !== null;
195
    }
196
197
    public function __call($name, $arguments)
198
    {
199
        return $this->__get($name);
200
    }
201
202
    /**
203
     * Refresh deferred item by clearing and then lazy loading it.
204
     *
205
     * @param $key
206
     *
207
     * @return mixed
208
     */
209
    public function refresh($key)
210
    {
211
        unset($this->deferred[$key]);
212
213
        return $this->__get($key);
214
    }
215
216
    /**
217
     * Checks if primaryKey holds a value.
218
     *
219
     * @return bool
220
     */
221
    public function exists()
222
    {
223
        if (! array_key_exists($this->primaryKey, $this->attributes)) {
224
            return false;
225
        }
226
227
        return ! empty($this->attributes[$this->primaryKey]);
228
    }
229
230
    /**
231
     * Return the JSON representation of the data.
232
     *
233
     * @param int $options http://php.net/manual/en/json.constants.php
234
     *
235
     * @return string
236
     */
237
    public function json($options = 0, $withDeferred = false)
238
    {
239
        $attributes = $this->attributes;
240
        if ($withDeferred) {
241
            foreach ($this->deferred as $attribute => $collection) {
242
                if (empty($collection)) {
243
                    continue; // Leave orriginal array with __deferred key
244
                }
245
246
                $attributes[$attribute] = [];
247
                foreach ($collection as $value) {
248
                    if (! empty($value->deferred)) {
249
                        $value->attributes = array_merge($value->attributes, $value->deferred);
250
                    }
251
252
                    if (is_a($value, 'Picqer\Financials\Exact\Model')) {
253
                        array_push($attributes[$attribute], $value->attributes);
254
                    } else {
255
                        array_push($attributes[$attribute], $value);
256
                    }
257
                }
258
            }
259
        }
260
261
        return json_encode($attributes, $options);
262
    }
263
264
    /**
265
     * Return serializable data.
266
     *
267
     * @return array
268
     */
269
    public function jsonSerialize()
270
    {
271
        return $this->attributes;
272
    }
273
274
    /**
275
     * Check whether the current user has rights for an action on this endpoint
276
     * https://start.exactonline.nl/docs/HlpRestAPIResources.aspx?SourceAction=10.
277
     *
278
     * @param string $action
279
     *
280
     * @return bool
281
     */
282
    public function userHasRights($action = 'GET')
283
    {
284
        $action = preg_match('/^GET|POST|PUT|DELETE$/i', $action) ? strtoupper($action) : 'GET';
285
        $result = $this->connection()->get('users/UserHasRights', [
286
            'endpoint' => "'{$this->url}'",
287
            'action'   => "'{$action}'",
288
        ]);
289
290
        return isset($result['UserHasRights']) ? $result['UserHasRights'] : null;
291
    }
292
}
293