1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
// Copyright (c) Lellys Informática. All rights reserved. See License.txt in the project root for license information. |
4
|
|
|
namespace Collections; |
5
|
|
|
|
6
|
|
|
use Collections\Iterator\VectorIterator; |
7
|
|
|
use Collections\Traits\GuardTrait; |
8
|
|
|
use Collections\Traits\StrictIterableTrait; |
9
|
|
|
use InvalidArgumentException; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Represents a strongly typed list of objects that can be accessed by index. Provides methods to search, sort, |
13
|
|
|
* and manipulate lists. |
14
|
|
|
*/ |
15
|
|
|
class ArrayList extends AbstractConstCollectionArray implements VectorInterface, \ArrayAccess |
16
|
|
|
{ |
17
|
|
|
use StrictIterableTrait, |
18
|
|
|
GuardTrait; |
19
|
|
|
|
20
|
|
|
public function at($key) |
21
|
1 |
|
{ |
22
|
|
|
$this->validateKeyType($key); |
23
|
1 |
|
$this->validateKeyBounds($key); |
24
|
1 |
|
|
25
|
|
|
return $this->container[$key]; |
26
|
1 |
|
} |
27
|
|
|
|
28
|
|
|
public function set($key, $value) |
29
|
17 |
|
{ |
30
|
|
|
$this->validateKeyType($key); |
31
|
17 |
|
$this->container[$key] = $value; |
32
|
16 |
|
|
33
|
|
|
return $this; |
34
|
16 |
|
} |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* {@inheritdoc} |
38
|
|
|
*/ |
39
|
|
|
public function get($index) |
40
|
1 |
|
{ |
41
|
|
|
$this->validateKeyType($index); |
42
|
1 |
|
|
43
|
|
|
return $this->container[$index]; |
44
|
1 |
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* {@inheritdoc} |
48
|
|
|
*/ |
49
|
|
|
public function tryGet($index, $default = null) |
50
|
22 |
|
{ |
51
|
|
|
if ($this->containsKey($index) === false) { |
52
|
22 |
|
return $default; |
53
|
|
|
} |
54
|
22 |
|
|
55
|
|
|
return $this->get($index); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* {@inheritdoc} |
60
|
3 |
|
*/ |
61
|
|
|
public function add($item) |
62
|
3 |
|
{ |
63
|
1 |
|
$this->container[] = $item; |
64
|
|
|
|
65
|
|
|
return $this; |
66
|
2 |
|
} |
67
|
2 |
|
|
68
|
|
|
/** |
69
|
|
|
* {@inheritdoc} |
70
|
2 |
|
*/ |
71
|
2 |
View Code Duplication |
public function addAll($items) |
|
|
|
|
72
|
|
|
{ |
73
|
2 |
|
$this->validateTraversable($items); |
74
|
|
|
|
75
|
|
|
foreach ($items as $item) { |
76
|
|
|
if (is_array($item)) { |
77
|
|
|
$item = new static($item); |
78
|
|
|
} |
79
|
4 |
|
$this->add($item); |
80
|
|
|
} |
81
|
4 |
|
|
82
|
|
|
return $this; |
83
|
3 |
|
} |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* {@inheritdoc} |
87
|
|
|
*/ |
88
|
|
View Code Duplication |
public function setAll($items) |
|
|
|
|
89
|
|
|
{ |
90
|
3 |
|
$this->validateTraversable($items); |
91
|
|
|
|
92
|
3 |
|
foreach ($items as $key => $item) { |
93
|
2 |
|
if (is_array($item)) { |
94
|
|
|
$item = new static($item); |
95
|
1 |
|
} |
96
|
|
|
$this->set($key, $item); |
97
|
1 |
|
} |
98
|
|
|
|
99
|
|
|
return $this; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
|
103
|
3 |
|
/** |
104
|
|
|
* {@inheritdoc} |
105
|
3 |
|
*/ |
106
|
|
|
public function containsKey($key) |
107
|
|
|
{ |
108
|
|
|
$this->validateKeyType($key); |
109
|
|
|
|
110
|
|
|
return $key >= 0 && $key < $this->count(); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* {@inheritdoc} |
116
|
|
|
*/ |
117
|
|
|
public function removeKey($key) |
118
|
|
|
{ |
119
|
|
|
$this->validateKeyType($key); |
120
|
|
|
$this->validateKeyBounds($key); |
121
|
|
|
|
122
|
|
|
array_splice($this->container, $key, 1); |
123
|
|
|
|
124
|
|
|
return $this; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* {@inheritdoc} |
129
|
|
|
*/ |
130
|
|
|
public function indexOf($item) |
131
|
|
|
{ |
132
|
2 |
|
return array_search($item, $this->container, true); |
133
|
|
|
} |
134
|
2 |
|
|
135
|
|
|
/** |
136
|
1 |
|
* {@inheritdoc} |
137
|
|
|
*/ |
138
|
|
|
public function insert($index, $item) |
139
|
|
|
{ |
140
|
|
|
if (!is_numeric($index)) { |
141
|
|
|
throw new InvalidArgumentException('The index must be numeric'); |
142
|
1 |
|
} |
143
|
|
|
if ($index < 0 || $index >= $this->count()) { |
144
|
1 |
|
throw new InvalidArgumentException('The index is out of bounds (must be >=0 and <= size of te array)'); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
$current = $this->count() - 1; |
148
|
|
|
for (; $current >= $index; $current--) { |
149
|
|
|
$this->container[$current + 1] = $this->container[$current]; |
150
|
19 |
|
} |
151
|
|
|
$this->container[$index] = $item; |
152
|
19 |
|
|
153
|
4 |
|
return $this; |
154
|
4 |
|
} |
155
|
17 |
|
|
156
|
|
|
/** |
157
|
18 |
|
* {@inheritdoc} |
158
|
|
|
*/ |
159
|
|
|
public function offsetExists($offset) |
160
|
|
|
{ |
161
|
|
|
$this->validateKeyType($offset); |
162
|
1 |
|
|
163
|
|
|
return $this->containsKey($offset) && $this->at($offset) !== null; |
164
|
1 |
|
} |
165
|
1 |
|
|
166
|
|
|
/** |
167
|
|
|
* {@inheritdoc} |
168
|
|
|
*/ |
169
|
|
|
public function offsetGet($offset) |
170
|
|
|
{ |
171
|
1 |
|
return $this->get($offset); |
172
|
|
|
} |
173
|
1 |
|
|
174
|
|
|
/** |
175
|
|
|
* {@inheritdoc} |
176
|
|
|
*/ |
177
|
|
|
public function offsetSet($offset, $value) |
178
|
|
|
{ |
179
|
|
|
if (is_null($offset)) { |
180
|
|
|
$this->add($value); |
181
|
|
|
} else { |
182
|
|
|
$this->set($offset, $value); |
183
|
|
|
} |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* {@inheritdoc} |
188
|
|
|
*/ |
189
|
|
|
public function offsetUnset($offset) |
190
|
|
|
{ |
191
|
|
|
throw new \RuntimeException( |
192
|
|
|
'Cannot unset an element of a ' . get_class($this)); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* {@inheritdoc} |
197
|
|
|
*/ |
198
|
|
|
public function toMap() |
199
|
|
|
{ |
200
|
|
|
return new Dictionary($this->getIterator()); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
/** |
204
|
|
|
* {@inheritdoc} |
205
|
|
|
*/ |
206
|
|
|
public function reverse() |
207
|
|
|
{ |
208
|
|
|
return static::fromArray(array_reverse($this->container)); |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* {@inheritdoc} |
213
|
18 |
|
*/ |
214
|
|
|
public function splice($offset, $length = null) |
215
|
18 |
|
{ |
216
|
|
|
return static::fromArray(array_splice($this->container, $offset, $length)); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* {@inheritdoc} |
221
|
|
|
*/ |
222
|
|
|
public static function fromArray(array $arr) |
223
|
|
|
{ |
224
|
|
|
$map = new ArrayList(); |
225
|
|
|
foreach ($arr as $v) { |
226
|
|
|
if (is_array($v)) { |
227
|
|
|
$map->add(new ArrayList($v)); |
228
|
|
|
} else { |
229
|
|
|
$map->add($v); |
230
|
|
|
} |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
return $map; |
|
|
|
|
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* Gets the collection's iterator |
238
|
|
|
* @return VectorIterator |
239
|
|
|
*/ |
240
|
|
|
public function getIterator() |
241
|
|
|
{ |
242
|
|
|
return new VectorIterator($this->container); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* {@inheritDoc} |
247
|
|
|
* @return $this |
248
|
|
|
*/ |
249
|
|
|
public function concat($iterable) |
250
|
|
|
{ |
251
|
|
|
$this->validateTraversable($iterable); |
252
|
|
|
|
253
|
|
|
$this->setAll($this->concatRecurse($this, $iterable)); |
254
|
|
|
|
255
|
|
|
return $this; |
256
|
|
|
} |
257
|
|
|
} |
258
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.