ArrayList   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 232
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 0%

Importance

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

15 Methods

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