Completed
Pull Request — master (#52)
by Jasper
04:02
created

Item::canBeIncluded()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 7
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 15
ccs 0
cts 8
cp 0
crap 30
rs 9.6111

1 Method

Rating   Name   Duplication   Size   Complexity  
A Item::hasAttributes() 0 3 1
1
<?php
2
3
namespace Swis\JsonApi\Client;
4
5
use Illuminate\Support\Str;
6
use Jenssegers\Model\Model;
7
use Swis\JsonApi\Client\Interfaces\DataInterface;
8
use Swis\JsonApi\Client\Interfaces\ItemInterface;
9
use Swis\JsonApi\Client\Interfaces\ManyRelationInterface;
10
use Swis\JsonApi\Client\Interfaces\OneRelationInterface;
11
use Swis\JsonApi\Client\Relations\HasManyRelation;
12
use Swis\JsonApi\Client\Relations\HasOneRelation;
13
use Swis\JsonApi\Client\Relations\MorphToManyRelation;
14
use Swis\JsonApi\Client\Relations\MorphToRelation;
15
use Swis\JsonApi\Client\Traits\HasLinks;
16
use Swis\JsonApi\Client\Traits\HasMeta;
17
use Swis\JsonApi\Client\Traits\HasType;
18
19
/**
20
 * @property string|null id
21
 */
22
class Item extends Model implements ItemInterface
23
{
24
    use HasLinks;
25
    use HasMeta;
26
    use HasType;
27
28
    /**
29
     * @var string|null
30
     */
31
    protected $id;
32
33
    /**
34
     * Contains the initial values.
35
     *
36
     * @var array
37
     */
38
    protected $initial = [];
39
40
    /**
41
     * @var \Swis\JsonApi\Client\Interfaces\OneRelationInterface[]|\Swis\JsonApi\Client\Interfaces\ManyRelationInterface[]
42
     */
43
    protected $relationships = [];
44
45
    /**
46
     * Available relations need to be explicitly set.
47
     *
48
     * @var array
49
     */
50
    protected $availableRelations = [];
51
52
    /**
53
     * @var array
54
     */
55
    protected $guarded = ['id'];
56
57
    /**
58
     * @return array
59
     */
60 115
    public function toJsonApiArray(): array
61
    {
62
        $data = [
63 115
            'type' => $this->getType(),
64
        ];
65
66 115
        if ($this->hasId()) {
67 70
            $data['id'] = $this->getId();
68
        }
69
70 115
        $attributes = $this->toArray();
71 115
        if (!empty($attributes)) {
72 10
            $data['attributes'] = $attributes;
73
        }
74
75 115
        $relationships = $this->getRelationships();
76 115
        if (!empty($relationships)) {
77 80
            $data['relationships'] = $relationships;
78
        }
79
80 115
        $links = $this->getLinks();
81 115
        if ($links !== null) {
82 5
            $data['links'] = $links->toArray();
83
        }
84
85 115
        $meta = $this->getMeta();
86 115
        if ($meta !== null) {
87 5
            $data['meta'] = $meta->toArray();
88
        }
89
90 115
        return $data;
91
    }
92
93
    /**
94
     * @return bool
95
     */
96 15
    public function isNew(): bool
97
    {
98 15
        return !$this->hasId();
99
    }
100
101
    /**
102
     * @return bool
103
     */
104 170
    public function hasId(): bool
105
    {
106 170
        return isset($this->id);
107
    }
108
109
    /**
110
     * @return string|null
111
     */
112 245
    public function getId(): ? string
113
    {
114 245
        return $this->id;
115
    }
116
117
    /**
118
     * @param string|null $id
119
     *
120
     * @return static
121
     */
122 295
    public function setId(? string $id)
123
    {
124 295
        $this->id = $id;
125
126 295
        return $this;
127
    }
128
129
    /**
130
     * @return array
131
     */
132 135
    public function getRelationships(): array
133
    {
134 135
        $relationships = [];
135
136 135
        foreach ($this->relationships as $name => $relationship) {
137 95
            if ($relationship instanceof OneRelationInterface) {
138 55
                $relationships[$name] = ['data' => null];
139
140 55
                if ($relationship->getIncluded() !== null) {
141 45
                    $relationships[$name] = [
142
                        'data' => [
143 45
                            'type' => $relationship->getIncluded()->getType(),
144 55
                            'id'   => $relationship->getIncluded()->getId(),
145
                        ],
146
                    ];
147
                }
148 40
            } elseif ($relationship instanceof ManyRelationInterface) {
149 40
                $relationships[$name]['data'] = [];
150
151 40
                foreach ($relationship->getIncluded() as $item) {
152 30
                    $relationships[$name]['data'][] =
153
                        [
154 30
                            'type' => $item->getType(),
155 43
                            'id'   => $item->getId(),
156
                        ];
157
                }
158
            }
159
        }
160
161 135
        return $relationships;
162
    }
163
164
    /**
165
     * @return bool
166
     */
167 15
    public function hasRelationships(): bool
168
    {
169 15
        return !empty($this->getRelationships());
170
    }
171
172
    /**
173
     * @param string $key
174
     *
175
     * @return mixed
176
     */
177 25
    public function __get($key)
178
    {
179 25
        if ($key === 'id') {
180 5
            return $this->getId();
181
        }
182
183 20
        return parent::__get($key);
184
    }
185
186
    /**
187
     * @param string $key
188
     *
189
     * @return \Swis\JsonApi\Client\Interfaces\DataInterface|mixed
190
     */
191 45
    public function getAttribute($key)
192
    {
193 45
        if ($this->hasAttribute($key) || $this->hasGetMutator($key)) {
194 25
            return parent::getAttribute($key);
195
        }
196
197 20
        return $this->getRelationValue($key);
198
    }
199
200
    /**
201
     * @param string $key
202
     *
203
     * @return bool
204
     */
205 45
    public function hasAttribute($key): bool
206
    {
207 45
        return array_key_exists($key, $this->attributes);
208
    }
209
210
    /**
211
     * @return bool
212
     */
213 30
    public function hasAttributes(): bool
214
    {
215 30
        return !empty($this->toArray());
216
    }
217
218
    /**
219
     * @param string $key
220
     * @param mixed  $value
221
     */
222 5
    public function __set($key, $value)
223
    {
224 5
        if ($key === 'id') {
225 5
            $this->setId($value);
226
227 5
            return;
228
        }
229
230
        parent::__set($key, $value);
231
    }
232
233
    /**
234
     * Get the relationship data.
235
     *
236
     * @param string $key
237
     *
238
     * @return \Swis\JsonApi\Client\Interfaces\DataInterface|null
239
     */
240 20
    public function getRelationValue($key)
241
    {
242
        // If the "attribute" exists as a method on the model, we will just assume
243
        // it is a relationship and will load and return the included items in the relationship
244 20
        $method = Str::camel($key);
245 20
        if (method_exists($this, $method)) {
246 10
            return $this->$method()->getIncluded();
247
        }
248
249
        // If the "attribute" exists as a relationship on the model, we will return
250
        // the included items in the relationship
251 10
        if ($this->hasRelationship($key)) {
252 10
            return $this->getRelationship($key)->getIncluded();
253
        }
254
255
        return null;
256
    }
257
258
    /**
259
     * Determine if an attribute exists on the model.
260
     *
261
     * @param string $key
262
     *
263
     * @return bool
264
     */
265 5
    public function __isset($key)
266
    {
267 5
        if ($key === 'id') {
268 5
            return $this->hasId();
269
        }
270
271
        return parent::__isset($key) || $this->hasRelationship($key) || $this->hasRelationship(Str::snake($key));
272
    }
273
274
    /**
275
     * @param string $name
276
     *
277
     * @return \Swis\JsonApi\Client\Interfaces\OneRelationInterface|\Swis\JsonApi\Client\Interfaces\ManyRelationInterface
278
     */
279 80
    public function getRelationship(string $name)
280
    {
281 80
        return $this->relationships[$name];
282
    }
283
284
    /**
285
     * @param string $name
286
     *
287
     * @return bool
288
     */
289 25
    public function hasRelationship(string $name): bool
290
    {
291 25
        return array_key_exists($name, $this->relationships);
292
    }
293
294
    /**
295
     * @param $name
296
     *
297
     * @return static
298
     */
299
    public function removeRelationship(string $name)
300
    {
301
        unset($this->relationships[$name]);
302
303
        return $this;
304
    }
305
306
    /**
307
     * Create a singular relation to another item.
308
     *
309
     * @param string      $class
310
     * @param string|null $relationName
311
     *
312
     * @return \Swis\JsonApi\Client\Relations\HasOneRelation
313
     */
314 45
    public function hasOne(string $class, string $relationName = null)
315
    {
316 45
        $relationName = $relationName ?: Str::snake(debug_backtrace()[1]['function']);
317
318 45
        if (!array_key_exists($relationName, $this->relationships)) {
319 45
            $this->relationships[$relationName] = new HasOneRelation((new $class())->getType());
320
        }
321
322 45
        return $this->relationships[$relationName];
323
    }
324
325
    /**
326
     * Create a plural relation to another item.
327
     *
328
     * @param string      $class
329
     * @param string|null $relationName
330
     *
331
     * @return \Swis\JsonApi\Client\Relations\HasManyRelation
332
     */
333 20
    public function hasMany(string $class, string $relationName = null)
334
    {
335 20
        $relationName = $relationName ?: Str::snake(debug_backtrace()[1]['function']);
336
337 20
        if (!array_key_exists($relationName, $this->relationships)) {
338 20
            $this->relationships[$relationName] = new HasManyRelation((new $class())->getType());
339
        }
340
341 20
        return $this->relationships[$relationName];
342
    }
343
344
    /**
345
     * Create a singular relation to another item.
346
     *
347
     * @param string|null $relationName
348
     *
349
     * @return \Swis\JsonApi\Client\Relations\MorphToRelation
350
     */
351 85
    public function morphTo(string $relationName = null)
352
    {
353 85
        $relationName = $relationName ?: Str::snake(debug_backtrace()[1]['function']);
354
355 85
        if (!array_key_exists($relationName, $this->relationships)) {
356 85
            $this->relationships[$relationName] = new MorphToRelation();
357
        }
358
359 85
        return $this->relationships[$relationName];
360
    }
361
362
    /**
363
     * Create a plural relation to another item.
364
     *
365
     * @param string|null $relationName
366
     *
367
     * @return \Swis\JsonApi\Client\Relations\MorphToManyRelation
368
     */
369 55
    public function morphToMany(string $relationName = null)
370
    {
371 55
        $relationName = $relationName ?: Str::snake(debug_backtrace()[1]['function']);
372
373 55
        if (!array_key_exists($relationName, $this->relationships)) {
374 55
            $this->relationships[$relationName] = new MorphToManyRelation();
375
        }
376
377 55
        return $this->relationships[$relationName];
378
    }
379
380
    /**
381
     * Sets the initial values of an Item.
382
     *
383
     * @param array $initial
384
     *
385
     * @return static
386
     */
387 10
    public function setInitial(array $initial)
388
    {
389 10
        $this->initial = $initial;
390
391 10
        return $this;
392
    }
393
394
    /**
395
     * Returns the initial values of an Item.
396
     *
397
     * @param string|null $key
398
     *
399
     * @return array|mixed
400
     */
401 5
    public function getInitial($key = null)
402
    {
403 5
        if (null === $key) {
404 5
            return $this->initial;
405
        }
406
407
        return $this->initial[$key];
408
    }
409
410
    /**
411
     * @param string $key
412
     *
413
     * @return bool
414
     */
415
    public function hasInitial($key): bool
416
    {
417
        return isset($this->getInitial()[$key]);
418
    }
419
420
    /**
421
     * Prefills the model with values from $initial, when adding new item.
422
     *
423
     * @return static
424
     */
425 5
    public function useInitial()
426
    {
427 5
        $this->fill($this->initial);
428
429 5
        return $this;
430
    }
431
432
    /**
433
     * @return array
434
     */
435 95
    public function getAvailableRelations(): array
436
    {
437 95
        return $this->availableRelations;
438
    }
439
440
    /**
441
     * Set the specific relationship on the model.
442
     *
443
     * @param string                                        $relation
444
     * @param \Swis\JsonApi\Client\Interfaces\DataInterface $value
445
     * @param \Swis\JsonApi\Client\Links|null               $links
446
     * @param \Swis\JsonApi\Client\Meta|null                $meta
447
     *
448
     * @return static
449
     */
450 65
    public function setRelation(string $relation, DataInterface $value, Links $links = null, Meta $meta = null)
451
    {
452 65
        if (method_exists($this, $relation)) {
453
            /** @var \Swis\JsonApi\Client\Interfaces\OneRelationInterface|\Swis\JsonApi\Client\Interfaces\ManyRelationInterface $relationObject */
454 15
            $relationObject = $this->$relation();
455 55
        } elseif ($value instanceof Collection) {
456 10
            $relationObject = $this->morphToMany(Str::snake($relation));
457
        } else {
458 50
            $relationObject = $this->morphTo(Str::snake($relation));
459
        }
460
461 65
        $relationObject->associate($value);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type Swis\JsonApi\Client\Collection; however, parameter $included of Swis\JsonApi\Client\Inte...nInterface::associate() does only seem to accept Swis\JsonApi\Client\Interfaces\ItemInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

461
        $relationObject->associate(/** @scrutinizer ignore-type */ $value);
Loading history...
Bug introduced by
It seems like $value can also be of type Swis\JsonApi\Client\Collection; however, parameter $included of Swis\JsonApi\Client\Rela...neRelation::associate() does only seem to accept Swis\JsonApi\Client\Interfaces\ItemInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

461
        $relationObject->associate(/** @scrutinizer ignore-type */ $value);
Loading history...
462 65
        $relationObject->setLinks($links);
463 65
        $relationObject->setMeta($meta);
464
465 65
        return $this;
466
    }
467
468
    /**
469
     * @return array
470
     */
471 45
    public function getRelations(): array
472
    {
473 45
        return $this->relationships;
474
    }
475
}
476