Collection   A
last analyzed

Complexity

Total Complexity 31

Size/Duplication

Total Lines 225
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 50
dl 0
loc 225
rs 9.92
c 0
b 0
f 0
wmc 31

22 Methods

Rating   Name   Duplication   Size   Complexity  
A type() 0 3 1
A __construct() 0 7 3
A jsonSerialize() 0 3 1
A getIterator() 0 3 1
A offsetSet() 0 3 1
A offsetExists() 0 3 1
A first() 0 5 1
A offsetGet() 0 3 1
A last() 0 5 1
A isCompatible() 0 11 3
A offsetUnset() 0 3 1
A append() 0 7 2
A __callStatic() 0 3 1
A sum() 0 9 2
A reverse() 0 10 2
A validate() 0 4 2
A count() 0 3 1
A chunk() 0 5 1
A current() 0 3 1
A map() 0 9 2
A pop() 0 3 1
A add() 0 4 1
1
<?php
2
3
namespace kartavik\Support;
4
5
/**
6
 * Class Collection
7
 * @package kartavik\Support\
8
 */
9
class Collection implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonSerializable
10
{
11
    /** @var StrictInterface */
12
    private $strict = null;
13
14
    /** @var array */
15
    protected $container = [];
16
17
    /**
18
     * Collection constructor.
19
     *
20
     * @param StrictInterface $type
21
     * @param iterable ...$iterables
22
     *
23
     * @throws Exception\Validation
24
     */
25
    public function __construct(StrictInterface $type, iterable ...$iterables)
26
    {
27
        $this->strict = $type;
28
29
        foreach ($iterables as $iterable) {
30
            foreach ($iterable as $index => $item) {
31
                $this->append($item);
32
            }
33
        }
34
    }
35
36
    final public function type(): StrictInterface
37
    {
38
        return $this->strict;
39
    }
40
41
    /**
42
     * @param string|int $offset
43
     *
44
     * @return bool
45
     */
46
    public function offsetExists($offset): bool
47
    {
48
        return isset($this->container[$offset]);
49
    }
50
51
    /**
52
     * @param string|int $offset
53
     *
54
     * @return mixed
55
     */
56
    public function offsetGet($offset)
57
    {
58
        return $this->container[$offset];
59
    }
60
61
    /**
62
     * @param string|int $offset
63
     */
64
    public function offsetUnset($offset): void
65
    {
66
        unset($this->container[$offset]);
67
    }
68
69
    public function getIterator(): \ArrayIterator
70
    {
71
        return new \ArrayIterator($this->container);
72
    }
73
74
    /**
75
     * @param string|int $index
76
     * @param mixed $value
77
     *
78
     * @throws Exception\Validation
79
     */
80
    public function offsetSet($index, $value): void
81
    {
82
        $this->add($value, $index);
83
    }
84
85
    public function jsonSerialize(): array
86
    {
87
        return $this->container;
88
    }
89
90
    /**
91
     * @param mixed ...$var
92
     *
93
     * @return Collection
94
     * @throws Exception\Validation
95
     */
96
    public function append(...$var): Collection
97
    {
98
        foreach ($var as $item) {
99
            $this->add($item);
100
        }
101
102
        return $this;
103
    }
104
105
    public function isCompatible(iterable $collection): bool
106
    {
107
        try {
108
            foreach ($collection as $item) {
109
                $this->validate($item);
110
            }
111
        } catch (Exception\Validation $exception) {
112
            return false;
113
        }
114
115
        return true;
116
    }
117
118
    public function first()
119
    {
120
        reset($this->container);
121
122
        return $this->current();
123
    }
124
125
    public function last()
126
    {
127
        end($this->container);
128
129
        return $this->current();
130
    }
131
132
    /**
133
     * @param mixed $item
134
     *
135
     * @throws Exception\Validation
136
     */
137
    public function validate($item): void
138
    {
139
        if (!$this->type()->validate($item)) {
140
            throw new Exception\Validation($item);
141
        }
142
    }
143
144
    public function chunk(int $size): Collection
145
    {
146
        return Collection::{Collection::class}(array_map(function ($chunk) {
147
            return new Collection($this->type(), $chunk);
148
        }, array_chunk($this->container, $size)));
149
    }
150
151
    /**
152
     * @param \Closure $callback
153
     *
154
     * @return Collection
155
     * @throws Exception\Validation
156
     */
157
    public function map(\Closure $callback): Collection
158
    {
159
        $fetched = [];
160
161
        foreach ($this->container as $item) {
162
            $fetched[] = call_user_func($callback, $item);
163
        }
164
165
        return new Collection(Strict::typeof(current($fetched)), $fetched);
166
    }
167
168
    /**
169
     * @param bool $preserveKeys
170
     *
171
     * @return Collection
172
     * @throws Exception\Validation
173
     */
174
    public function reverse(bool $preserveKeys = false): Collection
175
    {
176
        /** @var Collection $collection */
177
        $collection = static::{$this->strict->type()}();
178
179
        foreach (array_reverse($this->container, $preserveKeys) as $index => $item) {
180
            $collection->add($item, $index);
181
        }
182
183
        return $collection;
184
    }
185
186
    public function current()
187
    {
188
        return current($this->container);
189
    }
190
191
    public function pop()
192
    {
193
        return array_pop($this->container);
194
    }
195
196
    public function sum(\Closure $callback)
197
    {
198
        $sum = 0;
199
200
        foreach ($this as $element) {
201
            $sum += call_user_func($callback, $element);
202
        }
203
204
        return $sum;
205
    }
206
207
    public function count(): int
208
    {
209
        return count($this->container);
210
    }
211
212
    /**
213
     * @param mixed $item
214
     * @param string|int|null $index
215
     *
216
     * @throws Exception\Validation
217
     */
218
    public function add($item, $index = null): void
219
    {
220
        $this->validate($item);
221
        $this->container[$index ?? $this->count()] = $item;
222
    }
223
224
    /**
225
     * @param string $name
226
     * @param array $arguments
227
     *
228
     * @return Collection
229
     * @throws Exception\Validation
230
     */
231
    public static function __callStatic(string $name, array $arguments = [])
232
    {
233
        return new static(Strict::{$name}(), ...$arguments);
234
    }
235
}
236