Passed
Push — master ( 81ef5c...53e963 )
by Stephan
03:03
created

Model::url()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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