GenericList   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 16
eloc 24
c 1
b 0
f 0
dl 0
loc 97
ccs 34
cts 34
cp 1
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A only() 0 11 3
A isEmpty() 0 3 1
A map() 0 3 1
A filter() 0 3 1
A __construct() 0 12 4
A slice() 0 3 1
A walk() 0 3 1
A count() 0 3 1
A getIterator() 0 3 1
A merge() 0 3 1
A isNotEmpty() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cunningsoft\GenericList;
6
7
use ArrayIterator;
8
use InvalidArgumentException;
9
use IteratorAggregate;
10
use function array_filter;
11
use function array_map;
12
use function array_merge;
13
use function array_slice;
14
use function array_walk;
15
use function count;
16
use function get_class;
17
use function gettype;
18
use function is_object;
19
use function sprintf;
20
21
/**
22
 * @template T
23
 */
24
abstract class GenericList implements IteratorAggregate
25
{
26
    /**
27
     * @var string
28
     * @psalm-var class-string<T>
29
     */
30
    private $type;
31
32
    /**
33
     * @var mixed[]
34
     * @psalm-var array<int, T>
35
     */
36
    protected $elements = [];
37
38
    /**
39
     * @param mixed[] $elements
40
     *
41
     * @psalm-param class-string<T> $type
42
     * @psalm-param iterable<T> $elements
43
     */
44 56
    public function __construct(string $type, iterable $elements = [])
45
    {
46 56
        $this->type = $type;
47 56
        foreach ($elements as $element) {
48 42
            if (!$element instanceof $type) {
49 12
                throw new InvalidArgumentException(sprintf(
50 12
                    'Expected a %s, but got: %s.',
51 12
                    $type,
52 12
                    is_object($element) ? get_class($element) : gettype($element),
53
                ));
54
            }
55 42
            $this->elements[] = $element;
56
        }
57 44
    }
58
59 33
    public function count(): int
60
    {
61 33
        return count($this->elements);
62
    }
63
64 15
    public function isEmpty(): bool
65
    {
66 15
        return $this->count() === 0;
67
    }
68
69 3
    public function isNotEmpty(): bool
70
    {
71 3
        return !$this->isEmpty();
72
    }
73
74 6
    public function filter(callable $callback): self
75
    {
76 6
        return new static($this->type, array_filter($this->elements, $callback));
77
    }
78
79
    /** @return mixed[] */
80 2
    public function map(callable $callback): array
81
    {
82 2
        return array_map($callback, $this->elements);
83
    }
84
85 1
    public function walk(callable $callback): bool
86
    {
87 1
        return array_walk($this->elements, $callback);
88
    }
89
90 4
    public function merge(self $other): self
91
    {
92 4
        return new static($this->type, array_merge($this->elements, $other->elements));
93
    }
94
95 12
    public function slice(int $offset, ?int $length = null): self
96
    {
97 12
        return new static($this->type, array_slice($this->elements, $offset, $length));
98
    }
99
100
    /**
101
     * @return mixed
102
     *
103
     * @psalm-return T
104
     */
105 4
    public function only()
106
    {
107 4
        if ($this->isEmpty()) {
108 1
            throw new NoElements();
109
        }
110
111 3
        if ($this->count() > 1) {
112 1
            throw new ElementsAreNotUnique();
113
        }
114
115 2
        return $this->elements[0];
116
    }
117
118 4
    public function getIterator(): ArrayIterator
119
    {
120 4
        return new ArrayIterator($this->elements);
121
    }
122
}
123