Passed
Push — version-4 ( afc63d...db79e6 )
by Sebastian
02:18
created

ArrayListTrait::add()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
declare(strict_types=1);
3
/*
4
 * Copyright (C) 2018 Sebastian Böttger <[email protected]>
5
 * You may use, distribute and modify this code under the
6
 * terms of the MIT license.
7
 *
8
 * You should have received a copy of the MIT license with
9
 * this file. If not, please visit: https://opensource.org/licenses/mit-license.php
10
 */
11
12
namespace Seboettg\Collection\Lists;
13
14
use Seboettg\Collection\Lists\ListFeatures\ListAccessTrait;
15
use Seboettg\Collection\Lists\MapFeatures\MapFeaturesTrait;
16
use Seboettg\Collection\Map\MapInterface;
17
use Seboettg\Collection\NativePhp\IteratorTrait;
18
use function Seboettg\Collection\Assert\assertStringable;
19
use function Seboettg\Collection\Map\mapOf;
20
use function Seboettg\Collection\Map\pair;
21
22
/**
23
 * @property array $array Base array of this data structure
24
 */
25
trait ArrayListTrait
26
{
27
    use ListAccessTrait;
28
    use IteratorTrait;
29
    use MapFeaturesTrait;
30
31
    /**
32
     * flush array list
33
     *
34
     * @return ListInterface|ArrayListTrait
35
     */
36 1
    public function clear(): void
37
    {
38 1
        unset($this->array);
39 1
        $this->array = [];
40 1
    }
41
42
    /**
43
     * Adds the specified element to the end of this list.
44
     *
45
     * @param mixed $element
46
     */
47 14
    public function add($element): void
48
    {
49 14
        end($this->array);
50 14
        $this->array[] = $element;
51 14
    }
52
53
    /**
54
     * @inheritDoc
55
     */
56 1
    public function addAll(iterable $elements): void
57
    {
58 1
        foreach ($elements as $element) {
59 1
            $this->add($element);
60
        }
61 1
    }
62
63
    /**
64
     * @param $key
65
     * @return ListInterface|ArrayListTrait
66
     */
67 1
    public function remove($key): ListInterface
68
    {
69 1
        unset($this->array[$key]);
70 1
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Seboettg\Collection\Lists\ArrayListTrait which is incompatible with the type-hinted return Seboettg\Collection\Lists\ListInterface.
Loading history...
71
    }
72
73
    /**
74
     * {@inheritdoc}
75
     */
76 3
    public function contains($value): bool
77
    {
78 3
        $result = in_array($value, $this->array, true);
79 3
        return ($result !== false);
80
    }
81
82
    /**
83
     * @inheritDoc
84
     * @see http://php.net/manual/en/function.shuffle.php
85
     * @return ListInterface
86
     */
87 1
    public function shuffle(): ListInterface
88
    {
89 1
        shuffle($this->array);
90 1
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Seboettg\Collection\Lists\ArrayListTrait which is incompatible with the type-hinted return Seboettg\Collection\Lists\ListInterface.
Loading history...
91
    }
92
93
    /**
94
     * @inheritDoc
95
     */
96 8
    public function filter(?callable $predicate = null, bool $preserveKeys = false): ListInterface
97
    {
98 8
        $list = emptyList();
99 8
        $filtered = $predicate == null ? array_filter($this->array) : array_filter($this->array, $predicate);
100 8
        $list->setArray(
101 8
            $preserveKeys ? $filtered : array_values($filtered)
102
        );
103 8
        return $list;
104
    }
105
106
    /**
107
     * @param array $array
108
     */
109 27
    public function setArray(array $array): void
110
    {
111 27
        $this->replace($array);
112 27
    }
113
114
    /**
115
     * @param array $data
116
     */
117 29
    public function replace(array $data): void
118
    {
119 29
        $this->array = $data;
120 29
    }
121
122
    /**
123
     * returns a new ArrayList containing all the elements of this ArrayList after applying the callback function to each one.
124
     * @param callable $mapFunction
125
     * @return ListInterface|ArrayListTrait
126
     */
127 7
    public function map(callable $mapFunction): ListInterface
128
    {
129 7
        $list = emptyList();
130 7
        foreach ($this as $value) {
131 7
            $list->add($mapFunction($value));
132
        }
133 6
        return $list;
134
    }
135
136
    /**
137
     * @inheritDoc
138
     * @param callable $mapFunction
139
     * @return ListInterface
140
     */
141 1
    public function mapNotNull(callable $mapFunction): ListInterface
142
    {
143 1
        $list = $this->map($mapFunction);
144 1
        return $list->filter();
145
    }
146
147
    /**
148
     * Returns a new ArrayList containing a one-dimensional array of all elements of this ArrayList. Keys are going lost.
149
     * @return ListInterface
150
     */
151 1
    public function flatten(): ListInterface
152
    {
153 1
        $flattenedArray = [];
154
        array_walk_recursive($this->array, function ($item) use (&$flattenedArray) {
155 1
            $flattenedArray[] = $item;
156 1
        });
157 1
        return listOf(...$flattenedArray);
158
    }
159
160
    /**
161
     * @inheritDoc
162
     * @param callable $collectFunction
163
     * @return mixed
164
     */
165 1
    public function collect(callable $collectFunction)
166
    {
167 1
        return $collectFunction($this->array);
168
    }
169
170
    /**
171
     * @inheritDoc
172
     */
173 4
    public function joinToString(string $delimiter, string $prefix = null, string $suffix = null): string
174
    {
175
        $result = implode($delimiter, $this->map(function ($item) {
176 4
            assertStringable($item, "Elements in list must be convertible to string in order to use joinToString.");
177 3
            return strval($item);
178 4
        })->toArray());
179 3
        if ($prefix !== null) {
180
            $result = $prefix . $result;
181
        }
182 3
        if ($suffix !== null) {
183
            $result = $result . $suffix;
184
        }
185 3
        return $result;
186
    }
187
188
    /**
189
     * @inheritDoc
190
     * @deprecated use joinToString instead
191
     */
192 1
    public function collectToString(string $delimiter): string
193
    {
194 1
        return $this->joinToString($delimiter);
195
    }
196
197
    /**
198
     * @inheritDoc
199
     * @return int
200
     */
201 13
    public function count(): int
202
    {
203 13
        return count($this->array);
204
    }
205
206
    /**
207
     * @inheritDoc
208
     */
209
    public function size(): int
210
    {
211
        return $this->count();
212
    }
213
214
    /**
215
     * @inheritDoc
216
     */
217 1
    public function minus(iterable $values): ListInterface
218
    {
219 1
        if (!$values instanceof ListInterface) {
220
            $valuesList = emptyList();
221
            $valuesList->setArray(is_array($values) ?? $values->toArray());
0 ignored issues
show
Bug introduced by
It seems like is_array($values) ?? $values->toArray() can also be of type boolean; however, parameter $array of anonymous//src/Lists/Functions.php$0::setArray() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

221
            $valuesList->setArray(/** @scrutinizer ignore-type */ is_array($values) ?? $values->toArray());
Loading history...
222
        } else {
223 1
            $valuesList = $values;
224
        }
225 1
        $newInstance = emptyList();
226 1
        foreach ($this->array as $value) {
227 1
            if (!$valuesList->contains($value)) {
228 1
                $newInstance->add($value);
229
            }
230
        }
231 1
        return $newInstance;
232
    }
233
234
    /**
235
     * @inheritDoc
236
     */
237
    public function intersect(ListInterface $list): ListInterface
238
    {
239
        $newInstance = emptyList();
240
        $newInstance->setArray(array_intersect($this->array, $list->array));
0 ignored issues
show
Bug introduced by
Accessing array on the interface Seboettg\Collection\Lists\ListInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
241
        return $newInstance;
242
    }
243
244
    /**
245
     * @inheritDoc
246
     * @param callable $predicate - f(item: mixed) -> bool
247
     * @return MapInterface<string, ListInterface>
248
     */
249 1
    public function partition(callable $predicate): MapInterface
250
    {
251 1
        $first = listOf(...array_filter($this->array, $predicate));
252 1
        return mapOf(
253 1
            pair("first", $first),
254 1
            pair("second", $this->minus($first))
255
        );
256
    }
257
258
259
    public function plus(iterable $other): ListInterface
260
    {
261
        $list = listOf(...$this->array);
262
        $list->addAll($other);
263
        return $list;
264
    }
265
266
    public function union(ListInterface $other): ListInterface
267
    {
268
        return $this->plus($other);
269
    }
270
271
    public function subtract(ListInterface $other): ListInterface
272
    {
273
        $list = emptyList();
274
        foreach ($this->array as $element) {
275
            if (!$other->contains($element)) {
276
                $list->add($element);
277
            }
278
        }
279
        return $list;
280
    }
281
282 2
    public function any(callable $predicate): bool
283
    {
284 2
        return $this->filter($predicate)->count() > 0;
285
    }
286
287 2
    public function all(callable $predicate): bool
288
    {
289 2
        return $this->count() === $this->filter($predicate)->count();
290
    }
291
292
    /**
293
     * @inheritDoc
294
     */
295
    public function chunk(int $size): ListInterface
296
    {
297
        $listOfChunks = emptyList();
298
        $arrayChunks = array_chunk($this->array, $size);
299
        foreach ($arrayChunks as $arrayChunk) {
300
            $listOfChunks->add(listOf(...$arrayChunk));
301
        }
302
        return $listOfChunks;
303
    }
304
305
    public function distinct(): ListInterface
306
    {
307
        return listOf(...array_unique($this->array));
308
    }
309
310
    /**
311
     * @inheritDoc
312
     */
313 4
    public function forEach(callable $action): void
314
    {
315 4
        foreach ($this->array as $element) {
316 4
            $action($element);
317
        }
318 4
    }
319
320
    /**
321
     * @inheritDoc
322
     */
323
    public function getOrElse(int $index, callable $defaultValue)
324
    {
325
        if ($this->array[$index] !== null) {
326
            return $this->array[$index];
327
        }
328
        return $defaultValue();
329
    }
330
331
    /**
332
     * @inheritDoc
333
     * @param int $fromIndex
334
     * @param int $toIndex
335
     * @return ListInterface
336
     */
337
    public function subList(int $fromIndex, int $toIndex): ListInterface
338
    {
339
        $list = emptyList();
340
        for ($i = $fromIndex; $i < $toIndex; ++$i) {
341
            if (isset($this->array[$i])) {
342
                $list->add($this->array[$i]);
343
            }
344
        }
345
        return $list;
346
    }
347
348
    /**
349
     * Return first element of this list that matches the matchingCondition
350
     *
351
     * @param callable $matchingCondition
352
     * @return mixed|null
353
     */
354
    public function searchBy(callable $matchingCondition)
355
    {
356
        $list = listOf(...array_filter($this->array));
357
        return $list->filter($matchingCondition)->first();
358
    }
359
360
    public function isEmpty(): bool
361
    {
362
        return $this->count() === 0;
363
    }
364
365
    /**
366
     * {@inheritDoc}
367
     */
368 9
    public function toArray(): array
369
    {
370 9
        return $this->array;
371
    }
372
}
373