Includeset   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 96
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 39
dl 0
loc 96
rs 10
c 0
b 0
f 0
wmc 16

9 Methods

Rating   Name   Duplication   Size   Complexity  
A offsetExists() 0 3 1
A withRelation() 0 10 2
A offsetGet() 0 3 2
A count() 0 3 1
A offsetUnset() 0 3 1
A offsetSet() 0 3 1
A fromString() 0 27 4
A withInclude() 0 17 3
A getIterator() 0 3 1
1
<?php namespace JSONAPI\Resource;
2
3
/**
4
 * Class helper for working with `include` JSON:API parameter.
5
 *
6
 * @link https://jsonapi.org/format/#fetching-includes
7
 *
8
 * @implements \ArrayAccess<string, Includeset>
9
 * @implements \IteratorAggregate<string, Includeset>
10
 */
11
final class Includeset implements \ArrayAccess, \IteratorAggregate, \Countable
12
{
13
    const ITEM_SEPARATOR = ',';
14
    const RELATION_SEPARATOR = '.';
15
16
    /** @var array<string, Includeset> */
17
    protected array $relations = [];
18
19
    public static function fromString(string $raw): Includeset
20
    {
21
        $include = new Includeset();
22
        $items = array_unique(explode(Includeset::ITEM_SEPARATOR, $raw));
23
24
        foreach ($items as $item) {
25
            $parserInclude = explode(Includeset::RELATION_SEPARATOR, $item, 2);
26
            $relation = array_shift($parserInclude);
27
28
            if (empty($relation)) {
29
                continue;
30
            }
31
32
            $rawChildren = array_shift($parserInclude) ?? '';
33
34
            if (isset($include->relations[$relation])) {
35
                $include->relations[$relation] = $include
36
                    ->relations[$relation]
37
                    ->withInclude(Includeset::fromString($rawChildren));
38
39
                continue;
40
            }
41
42
            $include->relations[$relation] = Includeset::fromString($rawChildren);
43
        }
44
45
        return $include;
46
    }
47
48
    public function withRelation(string $relation): self
49
    {
50
        if (isset($this[$relation])) {
51
            return $this;
52
        }
53
54
        $new = clone $this;
55
        $new->relations[$relation] = new Includeset();
56
57
        return $new;
58
    }
59
60
    public function withInclude(self $includeset): self
61
    {
62
        $new = clone $this;
63
64
        foreach ($includeset as $relation => $item) {
65
            if (isset($new->relations[$relation])) {
66
                $new->relations[$relation] = $new
67
                    ->relations[$relation]
68
                    ->withInclude($item);
69
70
                continue;
71
            }
72
73
            $new->relations[$relation] = $item;
74
        }
75
76
        return $new;
77
    }
78
79
    public function count() : int
80
    {
81
        return count($this->relations);
82
    }
83
84
    public function offsetExists($key): bool
85
    {
86
        return isset($this->relations[$key]);
87
    }
88
89
    public function offsetGet($key): ?Includeset
90
    {
91
        return isset($this->relations[$key]) ? $this->relations[$key] : null;
92
    }
93
94
    public function offsetSet($key, $value)
95
    {
96
        throw new \LogicException('Modifying includeset is not permitted');
97
    }
98
99
    public function offsetUnset($key)
100
    {
101
        throw new \LogicException('Modifying includeset is not permitted');
102
    }
103
104
    public function getIterator()
105
    {
106
        return new \ArrayIterator($this->relations);
107
    }
108
}