Passed
Push — develop ( a803f3...78e549 )
by nguereza
03:14
created

ArrayList   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 219
Duplicated Lines 0 %

Importance

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