ArrayList   A
last analyzed

Complexity

Total Complexity 30

Size/Duplication

Total Lines 241
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 30
eloc 72
c 1
b 0
f 0
dl 0
loc 241
rs 10

15 Methods

Rating   Name   Duplication   Size   Complexity  
A equals() 0 9 2
A forEach() 0 6 1
A fill() 0 4 2
A slice() 0 7 2
A rand() 0 10 2
A filter() 0 14 4
A reverse() 0 7 2
A merge() 0 3 1
A add() 0 6 1
A get() 0 3 1
A sort() 0 7 2
A map() 0 7 2
A remove() 0 15 3
A diff() 0 21 3
A update() 0 12 2
1
<?php
2
3
/**
4
 * Platine Collection
5
 *
6
 * Platine Collection provides a flexible and simple PHP collection implementation.
7
 *
8
 * This content is released under the MIT License (MIT)
9
 *
10
 * Copyright (c) 2020 Platine Collection
11
 *
12
 * Permission is hereby granted, free of charge, to any person obtaining a copy
13
 * of this software and associated documentation files (the "Software"), to deal
14
 * in the Software without restriction, including without limitation the rights
15
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
 * copies of the Software, and to permit persons to whom the Software is
17
 * furnished to do so, subject to the following conditions:
18
 *
19
 * The above copyright notice and this permission notice shall be included in all
20
 * copies or substantial portions of the Software.
21
 *
22
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
 * SOFTWARE.
29
 */
30
31
/**
32
 *  @file ArrayList.php
33
 *
34
 *  The Array List class is like a PHP native array
35
 *
36
 *  @package    Platine\Collection\Generic
37
 *  @author Platine Developers Team
38
 *  @copyright  Copyright (c) 2020
39
 *  @license    http://opensource.org/licenses/MIT  MIT License
40
 *  @link   https://www.platine-php.com
41
 *  @version 1.0.0
42
 *  @filesource
43
 */
44
45
declare(strict_types=1);
46
47
namespace Platine\Collection\Generic;
48
49
use OutOfRangeException;
50
use Platine\Collection\BaseCollection;
51
use Platine\Collection\CollectionInterface;
52
use Platine\Collection\Exception\InvalidOperationException;
53
use Platine\Collection\IterableInterface;
54
use Platine\Collection\MergeableInterface;
55
use Platine\Collection\SortableInterface;
56
57
/**
58
 * @class ArrayList
59
 * @package Platine\Collection\Generic
60
 * @template T
61
 * @extends BaseCollection<T>
62
 * @implements MergeableInterface<T>
63
 * @implements SortableInterface<T>
64
 */
65
class ArrayList extends BaseCollection implements
66
    CollectionInterface,
67
    IterableInterface,
68
    MergeableInterface,
69
    SortableInterface
70
{
71
    /**
72
     *
73
     * @param T $value
0 ignored issues
show
Bug introduced by
The type Platine\Collection\Generic\T was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
74
     * @return void
75
     */
76
    public function add(mixed $value): void
77
    {
78
        $data = $this->all();
79
80
        array_push($data, $value);
81
        $this->data->setData($data);
82
    }
83
84
    /**
85
     * Fill the collection
86
     * @param array<int, T> $data
87
     * @return void
88
     */
89
    public function fill(array $data): void
90
    {
91
        foreach ($data as $value) {
92
            $this->add($value);
93
        }
94
    }
95
96
    /**
97
     *
98
     * @param BaseCollection<T> $collection
99
     * @return ArrayList<T>
100
     * @throws InvalidOperationException
101
     */
102
    public function diff(BaseCollection $collection): BaseCollection
103
    {
104
        if (!$collection instanceof self) {
105
            throw new InvalidOperationException(
106
                'You should only compare an ArrayList against another ArrayList'
107
            );
108
        }
109
110
        $diffValues = array_udiff(
111
            $this->all(),
112
            $collection->all(),
113
            function ($a, $b) {
114
                if (gettype($a) !== gettype($b)) {
115
                    return -1;
116
                }
117
118
                return $a <=> $b;
119
            }
120
        );
121
122
        return new $this(array_values($diffValues));
123
    }
124
125
    /**
126
     *
127
     * @param BaseCollection<T> $collection
128
     * @return bool
129
     * @throws InvalidOperationException
130
     */
131
    public function equals(BaseCollection $collection): bool
132
    {
133
        if (!$collection instanceof self) {
134
            throw new InvalidOperationException(
135
                'You should only compare an ArrayList against another ArrayList'
136
            );
137
        }
138
139
        return $this->all() == $collection->all();
140
    }
141
142
    /**
143
     *
144
     * @param callable $callback
145
     * @return $this|null
146
     */
147
    public function filter(callable $callback): ?self
148
    {
149
        $matches = [];
150
151
        foreach ($this->data as $value) {
152
            $val = call_user_func($callback, $value);
153
            if ($val === true) {
154
                $matches[] = $value;
155
            }
156
        }
157
158
        return count($matches) > 0
159
                ? new $this($matches)
160
                : null;
161
    }
162
163
    /**
164
     * {@inheritedoc}
165
     */
166
    public function forEach(callable $callback): void
167
    {
168
        $data = $this->all();
169
        array_walk($data, $callback);
170
171
        $this->data->setData($data);
172
    }
173
174
    /**
175
     *
176
     * @param int $offset
177
     * @return T|null
178
     */
179
    public function get(int $offset): mixed
180
    {
181
        return $this->data->offsetGet($offset);
182
    }
183
184
    /**
185
     *
186
     * @param callable $callback
187
     * @return $this|null
188
     */
189
    public function map(callable $callback): ?self
190
    {
191
        $matches = array_map($callback, $this->all());
192
193
        return count($matches) > 0
194
                ? new $this(array_values($matches))
195
                : null;
196
    }
197
198
    /**
199
     *
200
     * @param ArrayList<T> $collection
201
     * @return ArrayList<T>
202
     */
203
    public function merge(BaseCollection $collection): BaseCollection
204
    {
205
        return new $this(array_merge($this->all(), $collection->all()));
206
    }
207
208
    /**
209
     * Return a random element of the collection
210
     * @return T|null
211
     * @throws InvalidOperationException
212
     */
213
    public function rand(): mixed
214
    {
215
        if ($this->isEmpty()) {
216
            throw new InvalidOperationException('The collection is empty');
217
        }
218
219
        /** @var int $offset */
220
        $offset = array_rand($this->all());
221
222
        return $this->get($offset);
223
    }
224
225
    /**
226
     * {@inheritedoc}
227
     */
228
    public function remove(int $offset): void
229
    {
230
        if ($this->isEmpty()) {
231
            throw new OutOfRangeException('The collection is empty');
232
        }
233
234
        if (!$this->data->offsetExists($offset)) {
235
            throw new OutOfRangeException(sprintf(
236
                'The collection index [%d] does not exists',
237
                $offset
238
            ));
239
        }
240
241
        $this->data->offsetUnset($offset);
242
        $this->repopulate();
243
    }
244
245
    /**
246
     *
247
     * @return $this
248
     */
249
    public function reverse(): self
250
    {
251
        if ($this->isEmpty()) {
252
            throw new InvalidOperationException('The collection is empty');
253
        }
254
255
        return new $this(array_reverse($this->all()));
256
    }
257
258
    /**
259
     *
260
     * @param int $offset
261
     * @param int|null $length
262
     * @return ArrayList<T>|null
263
     */
264
    public function slice(int $offset, ?int $length = null): ?BaseCollection
265
    {
266
        $newData = array_slice($this->all(), $offset, $length);
267
268
        return count($newData) > 0
269
                ? new $this($newData)
270
                : null;
271
    }
272
273
    /**
274
     *
275
     * @param callable $callback
276
     * @return ArrayList<T>|null
277
     */
278
    public function sort(callable $callback): ?BaseCollection
279
    {
280
        $data = $this->all();
281
282
        return usort($data, $callback)
283
                ? new $this($data)
284
                : null;
285
    }
286
287
    /**
288
     *
289
     * @param int $offset
290
     * @param T $value
291
     * @return bool
292
     * @throws InvalidOperationException
293
     */
294
    public function update(int $offset, mixed $value): bool
295
    {
296
        if (!$this->exists($offset)) {
297
            throw new InvalidOperationException(sprintf(
298
                'The collection index [%d] does not exists',
299
                $offset
300
            ));
301
        }
302
303
        $this->data->offsetSet($offset, $value);
304
305
        return $this->data->offsetGet($offset) === $value;
306
    }
307
}
308