Completed
Push — master ( d01fce...3c3d94 )
by Nate
02:38
created

ArrayList   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 235
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 2
dl 0
loc 235
ccs 56
cts 56
cp 1
rs 10
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A add() 0 6 1
A remove() 0 12 2
A clear() 0 4 1
A toArray() 0 4 1
A filter() 0 4 1
A getIterator() 0 4 1
A insert() 0 6 1
A insertAll() 0 9 1
A get() 0 8 2
A has() 0 4 1
A removeAt() 0 7 1
A set() 0 13 2
A subList() 0 10 3
A assertIndex() 0 6 3
1
<?php
2
/*
3
 * Copyright (c) Nate Brunette.
4
 * Distributed under the MIT License (http://opensource.org/licenses/MIT)
5
 */
6
7
namespace Tebru\Collection;
8
9
use ArrayIterator;
10
use OutOfBoundsException;
11
12
/**
13
 * Class ArrayList
14
 *
15
 * Implements [@see ListInterface] and maintains an array of elements
16
 *
17
 * @author Nate Brunette <[email protected]>
18
 */
19
class ArrayList extends AbstractList
20
{
21
    /**
22
     * An array of elements
23
     *
24
     * @var array
25
     */
26
    protected $elements = [];
27
28
    /**
29
     * Constructor
30
     *
31
     * @param array $elements
32
     */
33 67
    public function __construct(array $elements = [])
34
    {
35 67
        $this->elements = array_values($elements);
36 67
    }
37
38
    /**
39
     * Ensure the element exists in the collection
40
     *
41
     * Returns true if the collection can contain duplicates,
42
     * and false if it cannot.
43
     *
44
     * @param mixed $element
45
     * @return bool
46
     */
47 47
    public function add($element): bool
48
    {
49 47
        $this->elements[] = $element;
50
51 47
        return true;
52
    }
53
54
    /**
55
     * Removes object if it exists
56
     *
57
     * Returns true if the element was removed
58
     *
59
     * @param mixed $element
60
     * @return bool
61
     */
62 8
    public function remove($element): bool
63
    {
64 8
        $index = $this->indexOf($element);
65
66 8
        if (-1 === $index) {
67 2
            return false;
68
        }
69
70 7
        array_splice($this->elements, $index, 1);
71
72 7
        return true;
73
    }
74
75
    /**
76
     * Removes all elements from a collection
77
     *
78
     * @return void
79
     */
80 1
    public function clear()
81
    {
82 1
        $this->elements = [];
83 1
    }
84
85
    /**
86
     * Returns an array of all elements in the collection
87
     *
88
     * @return array
89
     */
90 91
    public function toArray(): array
91
    {
92 91
        return $this->elements;
93
    }
94
95
    /**
96
     * Filter the collection using closure
97
     *
98
     * The closure will get passed each element.  Returning true from the
99
     * closure will include that element in the new collection.
100
     *
101
     * @param callable $filter
102
     * @return CollectionInterface
103
     */
104 1
    public function filter(callable $filter): CollectionInterface
105
    {
106 1
        return new static(array_filter($this->toArray(), $filter));
107
    }
108
109
    /**
110
     * Retrieve an external iterator
111
     *
112
     * @return ArrayIterator
113
     */
114 8
    public function getIterator(): ArrayIterator
115
    {
116 8
        return new ArrayIterator($this->elements);
117
    }
118
119
    /**
120
     * Insert element at the specified index
121
     *
122
     * @param int $index
123
     * @param mixed $element
124
     * @return void
125
     * @throws \OutOfBoundsException if the index doesn't exist
126
     */
127 6
    public function insert(int $index, $element)
128
    {
129 6
        $this->assertIndex($index);
130
131 5
        array_splice($this->elements, $index, 0, [$element]);
132 5
    }
133
134
    /**
135
     * Inserts all elements of a collection at index
136
     *
137
     * @param int $index
138
     * @param CollectionInterface $collection
139
     * @return bool
140
     * @throws \OutOfBoundsException if the index doesn't exist
141
     */
142 4
    public function insertAll(int $index, CollectionInterface $collection): bool
143
    {
144 4
        $this->assertIndex($index);
145
146 3
        $size = $this->count();
147 3
        array_splice($this->elements, $index, 0, $collection->toArray());
148
149 3
        return $size !== $this->count();
150
    }
151
152
    /**
153
     * Returns the element at the index
154
     *
155
     * @param int $index
156
     * @return mixed
157
     * @throws \OutOfBoundsException if the index doesn't exist
158
     */
159 13
    public function get(int $index)
160
    {
161 13
        if (!$this->has($index)) {
162 2
            throw new OutOfBoundsException(sprintf('Tried to access element at index "%s"', $index));
163
        }
164
165 11
        return $this->elements[$index];
166
    }
167
168
    /**
169
     * Returns true if an element exists at the index
170
     *
171
     * @param int $index
172
     * @return bool
173
     */
174 19
    public function has(int $index): bool
175
    {
176 19
        return array_key_exists($index, $this->elements);
177
    }
178
179
    /**
180
     * Removes the element at the specified index
181
     *
182
     * This returns the element that was previously at this index
183
     *
184
     * @param int $index
185
     * @return mixed
186
     * @throws \OutOfBoundsException if the index doesn't exist
187
     */
188 2
    public function removeAt(int $index)
189
    {
190 2
        $oldElement = $this->get($index);
191 1
        array_splice($this->elements, $index, 1);
192
193 1
        return $oldElement;
194
    }
195
196
    /**
197
     * Replace the element at the specified index
198
     *
199
     * Returns the element that was previously at this index
200
     *
201
     * @param int $index
202
     * @param mixed $element
203
     * @return mixed
204
     * @throws \OutOfBoundsException if the index doesn't exist
205
     */
206 3
    public function set(int $index, $element)
207
    {
208 3
        $this->assertIndex($index);
209
210 2
        $oldElement = null;
211 2
        if ($this->has($index)) {
212 1
            $oldElement = $this->get($index);
213
        }
214
215 2
        $this->elements[$index] = $element;
216
217 2
        return $oldElement;
218
    }
219
220
    /**
221
     * Returns a new ListInterface ranging from $fromIndex inclusive to
222
     * $toIndex exclusive
223
     *
224
     * @param int $fromIndex
225
     * @param int $toIndex
226
     * @return ListInterface
227
     * @throws \OutOfBoundsException If to or from index does not exist
228
     */
229 4
    public function subList(int $fromIndex, int $toIndex): ListInterface
230
    {
231 4
        if (!$this->has($fromIndex) || !$this->has($toIndex - 1)) {
232 2
            throw new OutOfBoundsException('Unable to create sub list as $toIndex or $fromIndex do not exist in list');
233
        }
234
235 2
        $newList = array_slice($this->toArray(), $fromIndex, $toIndex - $fromIndex);
236
237 2
        return new static($newList);
238
    }
239
240
    /**
241
     * Assert the index is able to be inserted
242
     *
243
     * @param int $index
244
     * @return void
245
     * @throws \OutOfBoundsException If the index is less than 0 or greater than current size
246
     */
247 13
    protected function assertIndex(int $index)
248
    {
249 13
        if ($index < 0 || $index > $this->count()) {
250 3
            throw new OutOfBoundsException(sprintf('Element unable to be inserted at index "%s"', $index));
251
        }
252 10
    }
253
}
254