Test Failed
Pull Request — 1.0.0-alpha (#26)
by Alex
09:34 queued 02:30
created

RelationshipIterator::iterate()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 20
rs 8.8571
cc 6
eloc 10
nc 4
nop 2
1
<?php
2
3
namespace Huntie\JsonApi\Support;
4
5
use InvalidArgumentException;
6
use Huntie\JsonApi\Exceptions\InvalidRelationPathException;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Support\Collection;
9
10
class RelationshipIterator
11
{
12
    /**
13
     * The primary record.
14
     */
15
    private $record;
16
17
    /**
18
     * The path to the relation.
19
     *
20
     * @var string
21
     */
22
    private $path;
23
24
    /**
25
     * Create a new RelationshipIterator instance.
26
     *
27
     * @param Model  $record The primary record
28
     * @param string $path   The path to the relation
29
     *
30
     * @throws InvalidArgumentException
31
     */
32
    public function __construct($record, string $path)
33
    {
34
        if (!preg_match('/^([A-Za-z]+.?)+[A-Za-z]+$/', $path)) {
35
            throw new InvalidArgumentException('The relationship path must be a valid string');
36
        }
37
38
        $this->record = $record;
39
        $this->path = $path;
40
    }
41
42
    /**
43
     * Resolve the relationship from the primary record.
44
     *
45
     * @return Collection|Model|null
46
     */
47
    public function resolve()
48
    {
49
        return $this->iterate($this->record, $this->path);
50
    }
51
52
    /**
53
     * Recursively iterate through a given relation path to return the resolved
54
     * relationship value.
55
     *
56
     * @param Collection|Model|null $resolved
57
     * @param string|null           $path
58
     *
59
     * @return Collection|Model|null
60
     */
61
    private function iterate($resolved, $path)
62
    {
63
        list($relation, $path) = array_pad(explode('.', $path, 2), 2, null);
64
65
        if (empty($relation) || is_null($resolved = $resolved->{$relation})) {
66
            return $resolved;
67
        }
68
69
        if ($resolved instanceof Collection) {
70
            return $resolved->map(function ($record) use ($path) {
71
                return $this->iterate($record, $path);
72
            });
73
        }
74
75
        if (!$resolved instanceof Model || in_array($relation, $resolved->getHidden())) {
76
            throw new InvalidRelationPathException($this->path);
77
        }
78
79
        return $this->iterate($resolved, $path);
80
    }
81
}
82