Completed
Push — master ( 07ff5e...48ef71 )
by Colin
01:15
created

Model::delete()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
cc 4
nc 6
nop 1
1
<?php
2
3
namespace MacsiDigital\Xero\Support;
4
5
use Exception;
6
use Illuminate\Support\Collection;
7
use MacsiDigital\Xero\Facades\Xero;
8
9
abstract class Model
10
{
11
    protected $attributes = [];
12
    protected $query_attributes = [];
13
    protected $relationships = [];
14
    protected $queries = [];
15
    protected $methods = [];
16
17
    public $response;
18
19
    const ENDPOINT = '';
20
    const NODE_NAME = '';
21
    const KEY_FIELD = '';
22
23
    protected $client;
24
25
    public function __construct()
26
    {
27
        $this->client = Xero::getClient();
28
    }
29
30
    /**
31
     * Get the resource uri of the class (Contacts) etc.
32
     *
33
     * @return string
34
     */
35
    public static function getEndpoint()
36
    {
37
        return static::ENDPOINT;
38
    }
39
40
    /**
41
     * Get the root node name.  Just the unqualified classname.
42
     *
43
     * @return string
44
     */
45
    public static function getRootNodeName()
46
    {
47
        return static::NODE_NAME;
48
    }
49
50
    /**
51
     * Get the unique key field.
52
     *
53
     * @return string
54
     */
55
    public static function getKey()
56
    {
57
        return static::KEY_FIELD;
58
    }
59
60
    /**
61
     * Get the response model
62
     *
63
     * @return response object
64
     */
65
    public function getResponse()
66
    {
67
        return $this->response;
68
    }
69
70
    /**
71
     * Get the object unique ID.
72
     *
73
     * @return string
74
     */
75
    public function getID()
76
    {
77
        $index = $this->getKey();
78
79
        return $this->$index;
80
    }
81
82
    public function hasID()
83
    {
84
        $index = $this->getKey();
85
        if ($this->$index != '') {
86
            return true;
87
        }
88
89
        return false;
90
    }
91
92
    public function getAttributes()
93
    {
94
        return $this->attributes;
95
    }
96
97
    /**
98
     * Get an attribute from the model.
99
     *
100
     * @param  string  $key
101
     * @return mixed
102
     */
103
    public function getAttribute($key)
104
    {
105
        if (! $key) {
106
            return;
107
        }
108
        if ($this->attributeExists($key)) {
109
            return $this->getAttributeValue($key);
110
        }
111
    }
112
113
    /**
114
     * Get a plain attribute (not a relationship).
115
     *
116
     * @param  string  $key
117
     * @return mixed
118
     */
119
    public function getAttributeValue($key)
120
    {
121
        return $this->getAttributeFromArray($key);
122
    }
123
124
    /**
125
     * Get an attribute from the $attributes array.
126
     *
127
     * @param  string  $key
128
     * @return mixed
129
     */
130
    protected function getAttributeFromArray($key)
131
    {
132
        if (isset($this->attributes[$key])) {
133
            return $this->attributes[$key];
134
        }
135
    }
136
137
    /**
138
     * Set a given attribute on the model.
139
     *
140
     * @param  string  $key
141
     * @param  mixed  $value
142
     * @return mixed
143
     */
144
    public function setAttribute($key, $value)
145
    {
146
        if ($this->attributeExists($key)) {
147
            if ($this->isRelationshipAttribute($key)) {
148
                $class = new $this->relationships[$key];
149
                if (is_array($value) && in_array($class->getKey(), $value)) {
150
                    $class->fill($value);
151
                    $this->attributes[$key] = $class;
152
                } else {
153
                    foreach ($value as $index => $class) {
0 ignored issues
show
Bug introduced by
The expression $value of type object|integer|double|string|null|boolean|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
154
                        $new_class = new $this->relationships[$key];
155
                        $new_class->fill($class);
156
                        $this->attributes[$key][$index] = $new_class;
157
                    }
158
                }
159
            } else {
160
                $this->attributes[$key] = $value;
161
            }
162
        }
163
164
        return $this;
165
    }
166
167
    public function processRelationships()
168
    {
169
        foreach ($this->relationships as $key => $class) {
170
            if (is_array($this->$key) && in_array($this->getKey(), $this->$key)) {
171
                if (! is_object($this->$key)) {
172
                    $this->attributes[$key] = ($class)::make($this->$key);
173
                }
174
            } else {
175
                foreach ($this->$key as $index => $item) {
176
                    if (! is_object($item)) {
177
                        $this->attributes[$key][$index] = ($class)::make($item);
178
                    }
179
                }
180
            }
181
        }
182
183
        return $this;
184
    }
185
186
    public function attributeExists($key)
187
    {
188
        return array_key_exists($key, $this->attributes);
189
    }
190
191
    public function isRelationshipAttribute($key)
192
    {
193
        return array_key_exists($key, $this->relationships);
194
    }
195
196
    public function unsetAttribute($key)
197
    {
198
        $this->setAttribute($key, '');
199
    }
200
201
    /**
202
     * Dynamically retrieve attributes on the model.
203
     *
204
     * @param  string  $key
205
     * @return mixed
206
     */
207
    public function __get($key)
208
    {
209
        return $this->getAttribute($key);
210
    }
211
212
    /**
213
     * Dynamically set attributes on the model.
214
     *
215
     * @param  string  $key
216
     * @param  mixed  $value
217
     * @return void
218
     */
219
    public function __set($key, $value)
220
    {
221
        $this->setAttribute($key, $value);
222
    }
223
224
    /**
225
     * Determine if an attribute or relation exists on the model.
226
     *
227
     * @param  string  $key
228
     * @return bool
229
     */
230
    public function __isset($key)
231
    {
232
        return $this->attributeExists($key);
233
    }
234
235
    /**
236
     * Unset an attribute on the model.
237
     *
238
     * @param  string  $key
239
     * @return void
240
     */
241
    public function __unset($key)
242
    {
243
        $this->unsetAttribute($key);
244
    }
245
246
    public function make($attributes)
247
    {
248
        $model = new static;
249
        $model->fill($attributes);
250
251
        return $model;
252
    }
253
254
    public function create($attributes)
255
    {
256
        $model = static::make($attributes);
257
        $model->save();
258
259
        return $model;
260
    }
261
262
    public function fill($attributes)
263
    {
264
        foreach ($attributes as $attribute => $value) {
265
            $this->$attribute = $value;
266
        }
267
268
        return $this;
269
    }
270
271
    public function update($attributes)
272
    {
273
        $this->fill($attributes)->save();
274
275
        return $this;
276
    }
277
278
    public function save()
279
    {
280
        if ($this->hasID()) {
281
            if (in_array('put', $this->methods)) {
282
                $this->response = $this->client->post($this->getEndpoint().'/'.$this->getID(), $this->attributes);
283
                if ($this->response->getStatusCode() == '200') {
284
                    return $this;
285
                } else {
286
                    throw new Exception('Status Code '.$this->response->getStatusCode());
287
                }
288
            }
289
        } else {
290
            if (in_array('post', $this->methods)) {
291
                $this->response = $this->client->post($this->getEndpoint(), $this->attributes);
292
                if ($this->response->getStatusCode() == '200') {
293
                    $this->fill($this->response->getBody());
294
295
                    return $this;
296
                } else {
297
                    throw new Exception('Status Code '.$this->response->getStatusCode());
298
                }
299
            }
300
        }
301
    }
302
303
    public function where($key, $operator, $value = '')
304
    {
305
        if (in_array($key, $this->query_attributes)) {
306
            if ($value == '') {
307
                $value = $operator;
308
                $operator = '=';
309
            }
310
            $this->queries[$key] = ['key' => $key, 'operator' => $operator, 'value' => $value];
311
        }
312
313
        return $this;
314
    }
315
316
    public function getQueryString()
317
    {
318
        $query_string = '';
319
        if ($this->queries != []) {
320
            $query_string .= '?';
321
            $i = 1;
322
            foreach ($this->queries as $query) {
323
                if ($i > 1) {
324
                    $query_string .= '&';
325
                }
326
                $query_string .= $query['key'].$query['operator'].$query['value'];
327
                $i++;
328
            }
329
        }
330
331
        return $query_string;
332
    }
333
334
    public function first()
335
    {
336
        return $this->get()->first();
337
    }
338
339 View Code Duplication
    public function get()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
340
    {
341
        if (in_array('get', $this->methods)) {
342
            $this->response = $this->client->get($this->getEndpoint().$this->getQueryString());
343
            if ($this->response->getStatusCode() == '200') {
344
                return $this->collect($this->response->getBody());
345
            } else {
346
                throw new Exception('Status Code '.$this->response->getStatusCode());
347
            }
348
        }
349
    }
350
351 View Code Duplication
    public function all()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
352
    {
353
        if (in_array('get', $this->methods)) {
354
            $this->response = $this->client->get($this->getEndpoint());
355
            if ($this->response->getStatusCode() == '200') {
356
                return $this->collect($this->response->getBody());
357
            } else {
358
                throw new Exception('Status Code '.$this->response->getStatusCode());
359
            }
360
        }
361
    }
362
363 View Code Duplication
    public function find($id)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
364
    {
365
        if (in_array('get', $this->methods)) {
366
            $this->response = $this->client->get($this->getEndpoint().'/'.$id);
367
            if ($this->response->getStatusCode() == '200') {
368
                return $this->collect($this->response->getBody())->first();
369
            } else {
370
                throw new Exception('Status Code '.$this->response->getStatusCode());
371
            }
372
        }
373
    }
374
375
    public function delete($id = '')
376
    {
377
        if ($id == '') {
378
            $id = $this->getID();
379
        }
380
        if (in_array('delete', $this->methods)) {
381
            $this->response = $this->client->delete($this->getEndpoint().'/'.$id);
382
            if ($this->response->getStatusCode() == '200') {
383
                return $this->response->getStatusCode();
384
            } else {
385
                throw new Exception('Status Code '.$this->response->getStatusCode());
386
            }
387
        }
388
    }
389
390
    protected function collect($response)
391
    {
392
        $items = [];
393
        foreach ($response[$this->getEndpoint()] as $item) {
394
            $items[] = static::make($item);
395
        }
396
397
        return new Collection($items);
398
    }
399
}
400