Collection::count()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of Cecil.
5
 *
6
 * (c) Arnaud Ligny <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Cecil\Collection;
15
16
/**
17
 * Class Collection.
18
 *
19
 * Represents a collection of items, providing methods to manage them.
20
 */
21
class Collection implements CollectionInterface
22
{
23
    /**
24
     * Collection's identifier.
25
     * @var string
26
     */
27
    protected $id;
28
    /**
29
     * Collection's items.
30
     * @var array
31
     */
32
    protected $items = [];
33
34 1
    public function __construct(string $id, array $items = [])
35
    {
36 1
        $this->setId($id);
37 1
        $this->items = $items;
38
    }
39
40
    /**
41
     * {@inheritdoc}
42
     */
43 1
    public function setId(string $id): BaseInterface
44
    {
45 1
        $this->id = $id;
46
47 1
        return $this;
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53 1
    public function getId(): string
54
    {
55 1
        return $this->id;
56
    }
57
58
    /**
59
     * Search an item by ID.
60
     */
61 1
    protected function searchItem(string $id): ?array
62
    {
63 1
        return array_filter($this->items, function (ItemInterface $item) use ($id) {
64 1
            return $item->getId() == $id;
65 1
        });
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     *
71
     * @throws \DomainException
72
     */
73 1
    public function getPosition(string $id): int
74
    {
75 1
        $result = $this->searchItem($id);
76 1
        $position = key($result);
77 1
        if (!\is_int($position)) {
78
            throw new \DomainException(\sprintf('"%s" does not exist in "%s" collection.', $id, $this->getId()));
79
        }
80
81 1
        return $position;
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87 1
    public function has(string $id): bool
88
    {
89 1
        $result = $this->searchItem($id);
90 1
        if (\is_array($result) && !empty($result)) {
91 1
            return true;
92
        }
93
94 1
        return false;
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     *
100
     * @throws \DomainException
101
     */
102 1
    public function add(ItemInterface $item): CollectionInterface
103
    {
104 1
        if ($this->has($item->getId())) {
105 1
            throw new \DomainException(\sprintf('Failed adding "%s" in "%s" collection: item already exists.', $item->getId(), $this->getId()));
106
        }
107 1
        $this->items[] = $item;
108
109 1
        return $this;
110
    }
111
112
    /**
113
     * {@inheritdoc}
114
     *
115
     * @throws \DomainException
116
     */
117 1
    public function replace(string $id, ItemInterface $item): CollectionInterface
118
    {
119
        try {
120 1
            $this->items[$this->getPosition($id)] = $item;
121
        } catch (\DomainException) {
122
            throw new \DomainException(\sprintf('Failed replacing "%s" in "%s" collection: item does not exist.', $id, $this->getId()));
123
        }
124
125 1
        return $this;
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     *
131
     * @throws \DomainException
132
     */
133 1
    public function remove(string $id): CollectionInterface
134
    {
135
        try {
136 1
            unset($this->items[$this->getPosition($id)]);
137
        } catch (\DomainException) {
138
            throw new \DomainException(\sprintf('Failed removing "%s" in "%s" collection: item does not exist.', $id, $this->getId()));
139
        }
140
141 1
        return $this;
142
    }
143
144
    /**
145
     * {@inheritdoc}
146
     *
147
     * @throws \DomainException
148
     */
149 1
    public function get(string $id): ItemInterface
150
    {
151
        try {
152 1
            return $this->items[$this->getPosition($id)];
153
        } catch (\DomainException) {
154
            throw new \DomainException(\sprintf('Failed getting "%s" in "%s" collection: item does not exist.', $id, $this->getId()));
155
        }
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161
    public function keys(): array
162
    {
163
        return array_keys($this->items);
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169 1
    public function first(): ?ItemInterface
170
    {
171 1
        if (\count($this->items) < 1) {
172
            return null;
173
        }
174 1
        $items = $this->items;
175
176 1
        return array_shift($items);
177
    }
178
179
    /**
180
     * {@inheritdoc}
181
     */
182
    public function last(): ?ItemInterface
183
    {
184
        if (\count($this->items) < 1) {
185
            return null;
186
        }
187
        $items = $this->items;
188
189
        return array_pop($items);
190
    }
191
192
    /**
193
     * {@inheritdoc}
194
     */
195 1
    public function count(): int
196
    {
197 1
        return \count($this->items);
198
    }
199
200
    /**
201
     * {@inheritdoc}
202
     */
203 1
    public function toArray(): array
204
    {
205 1
        return $this->items;
206
    }
207
208
    /**
209
     * {@inheritdoc}
210
     */
211
    public function toJson(): string
212
    {
213
        return \sprintf("%s\n", json_encode($this->items));
214
    }
215
216
    /**
217
     * {@inheritdoc}
218
     */
219 1
    public function getIterator(): \ArrayIterator
220
    {
221 1
        return new \ArrayIterator($this->items);
222
    }
223
224
    /**
225
     * {@inheritdoc}
226
     */
227 1
    public function usort(?\Closure $callback = null): CollectionInterface
228
    {
229 1
        $callback ? usort($this->items, $callback) : usort($this->items, function ($a, $b) {
230
            if ($a == $b) {
231
                return 0;
232
            }
233
234
            return ($a < $b) ? -1 : 1;
235 1
        });
236
237 1
        return new static($this->getId(), $this->items); /** @phpstan-ignore-line */
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     */
243
    public function reverse(): CollectionInterface
244
    {
245
        return new static($this->getId(), array_reverse($this->items)); /** @phpstan-ignore-line */
246
    }
247
248
    /**
249
     * {@inheritdoc}
250
     */
251 1
    public function filter(\Closure $callback): CollectionInterface
252
    {
253 1
        return new static($this->getId(), array_filter($this->items, $callback)); /** @phpstan-ignore-line */
254
    }
255
256
    /**
257
     * {@inheritdoc}
258
     */
259 1
    public function map(\Closure $callback): CollectionInterface
260
    {
261 1
        return new static($this->getId(), array_map($callback, $this->items)); /** @phpstan-ignore-line */
262
    }
263
264
    /**
265
     * Implements \ArrayAccess.
266
     *
267
     * @param string $offset
268
     *
269
     * @return bool
270
     */
271 1
    #[\ReturnTypeWillChange]
272
    public function offsetExists($offset): bool
273
    {
274 1
        return $this->has((string) $offset);
275
    }
276
277
    /**
278
     * Implements \ArrayAccess.
279
     *
280
     * @param string $offset
281
     *
282
     * @return CollectionInterface|ItemInterface|null
283
     */
284 1
    #[\ReturnTypeWillChange]
285
    public function offsetGet($offset)
286
    {
287 1
        return $this->get((string) $offset);
288
    }
289
290
    /**
291
     * Implements \ArrayAccess.
292
     *
293
     * @param mixed         $offset
294
     * @param ItemInterface $value
295
     *
296
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
297
     */
298
    #[\ReturnTypeWillChange]
299
    public function offsetSet($offset, $value): void
300
    {
301
        $this->add($value);
302
    }
303
304
    /**
305
     * Implements \ArrayAccess.
306
     *
307
     * @param string $offset
308
     *
309
     * @return void
310
     */
311
    #[\ReturnTypeWillChange]
312
    public function offsetUnset($offset): void
313
    {
314
        $this->remove($offset);
315
    }
316
317
    /**
318
     * Returns the collection ID.
319
     *
320
     * @return string
321
     */
322 1
    public function __toString()
323
    {
324 1
        return $this->getId();
325
    }
326
}
327