Completed
Push — master ( 6b2337...35aa85 )
by Jasper
14s queued 11s
created

Item::__get()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
ccs 0
cts 0
cp 0
crap 2
1
<?php
2
3
namespace Swis\JsonApi\Client;
4
5
use ArrayAccess;
6
use Illuminate\Contracts\Support\Arrayable;
7
use Illuminate\Contracts\Support\Jsonable;
8
use JsonSerializable;
9
use Swis\JsonApi\Client\Exceptions\MassAssignmentException;
10
use Swis\JsonApi\Client\Interfaces\ItemInterface;
11
use Swis\JsonApi\Client\Interfaces\ManyRelationInterface;
12
use Swis\JsonApi\Client\Interfaces\OneRelationInterface;
13
14
/**
15
 * @property string|null id
16
 */
17
class Item implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, ItemInterface
18
{
19
    use Concerns\GuardsAttributes;
20
    use Concerns\HasAttributes;
21
    use Concerns\HasId;
22
    use Concerns\HasInitial;
23
    use Concerns\HasLinks;
24
    use Concerns\HasMeta;
25
    use Concerns\HasRelations;
26
    use Concerns\HasType;
27
    use Concerns\HidesAttributes;
28
29
    /**
30
     * Available relations need to be explicitly set.
31
     *
32
     * @var array
33
     */
34
    protected $availableRelations = [];
35
36
    /**
37
     * Create a new Item instance.
38
     *
39
     * @param array $attributes
40
     *
41
     * @return void
42
     */
43
    public function __construct(array $attributes = [])
44 96
    {
45
        $this->fill($attributes);
46
    }
47 96
48
    /**
49
     * Fill the model with an array of attributes.
50 96
     *
51 54
     * @param array $attributes
52
     *
53
     * @throws \Illuminate\Database\Eloquent\MassAssignmentException
54 96
     *
55 96
     * @return $this
56 6
     */
57
    public function fill(array $attributes)
58
    {
59 96
        $totallyGuarded = $this->totallyGuarded();
60 96
61 63
        foreach ($this->fillableFromArray($attributes) as $key => $value) {
62
            // The developers may choose to place some attributes in the "fillable" array
63
            // which means only those attributes may be set through mass assignment to
64 96
            // the model, and all others will just get ignored for security reasons.
65 96
            if ($this->isFillable($key)) {
66 3
                $this->setAttribute($key, $value);
67
            } elseif ($totallyGuarded) {
68
                throw new MassAssignmentException(sprintf('Add [%s] to fillable property to allow mass assignment on [%s].', $key, get_class($this)));
69 96
            }
70 96
        }
71 3
72
        return $this;
73
    }
74 96
75
    /**
76
     * Fill the model with an array of attributes. Force mass assignment.
77
     *
78
     * @param array $attributes
79
     *
80 9
     * @return $this
81
     */
82 9
    public function forceFill(array $attributes)
83
    {
84
        return static::unguarded(function () use ($attributes) {
85
            return $this->fill($attributes);
86
        });
87
    }
88
89
    /**
90 27
     * Create a new instance of the given model.
91
     *
92 27
     * @param array $attributes
93 24
     *
94
     * @return static
95
     */
96 6
    public function newInstance(array $attributes = [])
97
    {
98
        $model = new static($attributes);
99
100
        $model->mergeCasts($this->casts);
101
102
        return $model;
103
    }
104 144
105
    /**
106 144
     * Create a list of models from plain arrays.
107
     *
108
     * @param array $items
109
     *
110
     * @return array
111
     */
112 24
    public static function hydrate(array $items): array
113
    {
114 24
        $instance = new static();
115
116
        return array_map(static function ($item) use ($instance) {
117
            return $instance->newInstance($item);
118
        }, $items);
119
    }
120 75
121
    /**
122 75
     * @return array
123
     */
124
    public function toJsonApiArray(): array
125
    {
126
        $data = [
127
            'type' => $this->getType(),
128 108
        ];
129
130 108
        if ($this->hasId()) {
131
            $data['id'] = $this->getId();
132 108
        }
133 84
134 12
        $attributes = $this->toArray();
135
        if (!empty($attributes)) {
136
            $data['attributes'] = $attributes;
137 72
        }
138 42
139
        $relationships = $this->getRelationships();
140 42
        if (!empty($relationships)) {
141 30
            $data['relationships'] = $relationships;
142 30
        }
143 42
144
        $links = $this->getLinks();
145
        if ($links !== null) {
146 30
            $data['links'] = $links->toArray();
147 30
        }
148
149 30
        $meta = $this->getMeta();
150 18
        if ($meta !== null) {
151 18
            $data['meta'] = $meta->toArray();
152 18
        }
153
154
        return $data;
155
    }
156
157 72
    /**
158 72
     * Convert the model instance to JSON.
159 12
     *
160
     * @param int $options
161
     *
162 72
     * @return string
163 72
     */
164 12
    public function toJson($options = 0)
165
    {
166
        return json_encode($this->jsonSerialize(), $options);
167
    }
168 108
169
    /**
170
     * Convert the object into something JSON serializable.
171
     *
172
     * @return array
173
     */
174 9
    public function jsonSerialize()
175
    {
176 9
        return $this->toArray();
177
    }
178
179
    /**
180
     * Convert the model instance to an array.
181
     *
182
     * @return array
183
     */
184 3
    public function toArray()
185
    {
186 3
        return $this->attributesToArray();
187
    }
188 3
189
    /**
190
     * Clone the model into a new, non-existing instance.
191
     *
192
     * @param array|null $except
193
     *
194
     * @return static
195
     */
196 6
    public function replicate(array $except = null)
197
    {
198 6
        $attributes = Util::arrayExcept($this->getAttributes(), $except ?? []);
199 3
200
        return new static($attributes);
201
    }
202 3
203
    /**
204
     * @return bool
205
     */
206
    public function isNew(): bool
207
    {
208
        return !$this->hasId();
209 9
    }
210
211 9
    /**
212 6
     * @return bool
213
     */
214 6
    public function hasAttributes(): bool
215
    {
216
        return !empty($this->toArray());
217 3
    }
218 3
219
    /**
220
     * @param string $key
221
     *
222
     * @return bool
223
     */
224
    public function hasAttribute($key): bool
225
    {
226
        return array_key_exists($key, $this->attributes);
227 6
    }
228
229 6
    /**
230 3
     * @return array
231
     */
232
    public function getAvailableRelations(): array
233 3
    {
234
        return $this->availableRelations;
235
    }
236
237
    /**
238
     * @return array
239
     */
240
    public function getRelationships(): array
241 6
    {
242
        $relationships = [];
243 6
244 3
        foreach ($this->getRelations() as $name => $relation) {
245
            if (!$relation->hasIncluded()) {
246
                continue;
247 6
            }
248 6
249
            if ($relation instanceof OneRelationInterface) {
250
                $relationships[$name]['data'] = null;
251
252
                if ($relation->getIncluded() !== null) {
253
                    $relationships[$name]['data'] = [
254
                        'type' => $relation->getIncluded()->getType(),
255
                        'id' => $relation->getIncluded()->getId(),
256
                    ];
257
                }
258
            } elseif ($relation instanceof ManyRelationInterface) {
259
                $relationships[$name]['data'] = [];
260
261
                foreach ($relation->getIncluded() as $item) {
262
                    $relationships[$name]['data'][] = [
263
                        'type' => $item->getType(),
264
                        'id' => $item->getId(),
265
                    ];
266
                }
267
            }
268
269
            $links = $relation->getLinks();
270
            if ($links !== null) {
271
                $relationships[$name]['links'] = $links->toArray();
272
            }
273
274
            $meta = $relation->getMeta();
275
            if ($meta !== null) {
276
                $relationships[$name]['meta'] = $meta->toArray();
277
            }
278
        }
279
280
        return $relationships;
281
    }
282
283
    /**
284
     * @return bool
285
     */
286
    public function hasRelationships(): bool
287
    {
288
        return !empty($this->getRelationships());
289
    }
290
291
    /**
292
     * Fills the model with the values from $initial. This is useful for setting defaults when creating a new item.
293
     *
294
     * @return static
295
     */
296
    public function useInitial()
297
    {
298
        $this->fill($this->initial);
299
300
        return $this;
301
    }
302
303
    /**
304
     * Dynamically retrieve attributes on the model.
305
     *
306
     * @param string $key
307
     *
308
     * @return mixed
309
     */
310
    public function __get(string $key)
311
    {
312
        return $this->offsetGet($key);
313
    }
314
315
    /**
316
     * Dynamically set attributes on the model.
317
     *
318
     * @param string $key
319
     * @param mixed  $value
320
     *
321
     * @return void
322
     */
323
    public function __set(string $key, $value)
324
    {
325
        $this->offsetSet($key, $value);
326
    }
327
328
    /**
329
     * Determine if the given attribute exists.
330
     *
331
     * @param mixed $offset
332
     *
333
     * @return bool
334
     */
335
    public function offsetExists($offset)
336
    {
337
        if ($offset === 'id') {
338
            return $this->hasId();
339
        }
340
341
        return !is_null($this->getAttribute($offset));
342
    }
343
344
    /**
345
     * Get the value for a given offset.
346
     *
347
     * @param mixed $offset
348
     *
349
     * @return mixed
350
     */
351
    public function offsetGet($offset)
352
    {
353
        if ($offset === 'id') {
354
            return $this->getId();
355
        }
356
357
        return $this->getAttribute($offset);
358
    }
359
360
    /**
361
     * Set the value for a given offset.
362
     *
363
     * @param mixed $offset
364
     * @param mixed $value
365
     *
366
     * @return void
367
     */
368
    public function offsetSet($offset, $value)
369
    {
370
        if ($offset === 'id') {
371
            $this->setId($value);
372
373
            return;
374
        }
375
376
        $this->setAttribute($offset, $value);
377
    }
378
379
    /**
380
     * Unset the value for a given offset.
381
     *
382
     * @param mixed $offset
383
     *
384
     * @return void
385
     */
386
    public function offsetUnset($offset)
387
    {
388
        if ($offset === 'id') {
389
            $this->id = null;
390
        }
391
392
        unset($this->attributes[$offset], $this->relations[$offset]);
393
    }
394
395
    /**
396
     * Determine if an attribute or relation exists on the model.
397
     *
398
     * @param string $key
399
     *
400
     * @return bool
401
     */
402
    public function __isset(string $key)
403
    {
404
        return $this->offsetExists($key);
405
    }
406
407
    /**
408
     * Unset an attribute on the model.
409
     *
410
     * @param string $key
411
     *
412
     * @return void
413
     */
414
    public function __unset(string $key)
415
    {
416
        $this->offsetUnset($key);
417
    }
418
419
    /**
420
     * Convert the model to its string representation.
421
     *
422
     * @return string
423
     */
424
    public function __toString()
425
    {
426
        return $this->toJson();
427
    }
428
}
429