ArrayList::keyBy()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 9
ccs 6
cts 6
cp 1
crap 2
rs 9.6666
c 0
b 0
f 0
1
<?php
2
namespace Wandu\Collection;
3
4
use InvalidArgumentException;
5
use Traversable;
6
use Wandu\Collection\Contracts\ListInterface;
7
8
class ArrayList implements ListInterface
9
{
10
    /** @var array */
11
    protected $items;
12
13
    /**
14
     * @param array|\Traversable $items
15
     */
16 53
    public function __construct($items = [])
17
    {
18 53
        if ($items instanceof Traversable) {
19 4
            $this->items = iterator_to_array($items); // for lazy iterate
20
        } else {
21 52
            $this->items = array_values($items);
22
        }
23 53
    }
24
25
    /**
26
     * {@inheritdoc}
27
     */
28 1
    public function __toString()
29
    {
30 1
        $string = static::class . " [\n";
31 1
        foreach ($this as $item) {
32 1
            $string .= "    ";
33 1
            if (is_string($item)) {
34 1
                $string .= "\"{$item}\",\n";
35 1
            } elseif (is_scalar($item)) {
36 1
                $string .= "{$item},\n";
37 1
            } elseif (is_null($item)) {
38 1
                $string .= "null,\n";
39 1
            } elseif (is_array($item)) {
40 1
                $string .= "[array],\n";
41 1
            } elseif (is_object($item)) {
42 1
                $string .= "[" . get_class($item) . "],\n";
43
            } else {
44 1
                $string .= "[unknown],\n";
45
            }
46
        }
47 1
        return $string . ']';
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53 43
    public function toArray()
54
    {
55 43
        $arr = [];
56 43
        foreach ($this as $item) {
57 43
            if (method_exists($item, 'toArray')) {
58 1
                $arr[] = $item->toArray();
59
            } else {
60 43
                $arr[] = $item;
61
            }
62
        }
63 43
        return $arr;
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69 22
    public function all()
70
    {
71 22
        return $this->items;
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77 7
    public function count()
78
    {
79 7
        return count($this->items);
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     */
85 1
    function jsonSerialize()
86
    {
87 1
        return $this->all(); // safe
88
    }
89
    
90
    /**
91
     * {@inheritdoc}
92
     */
93 49
    public function getIterator()
94
    {
95 49
        foreach ($this->items as $item) {
96 49
            yield $item;
97
        }
98 49
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103 1
    public function offsetExists($offset)
104
    {
105 1
        return isset($this->items[$offset]);
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111 4
    public function offsetGet($offset)
112
    {
113 4
        return $this->get($offset);
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119 4
    public function offsetSet($offset, $value)
120
    {
121 4
        $this->assertIsNullOrIntegerLessSize($offset, __METHOD__);
122 4
        $this->set($offset, $value);
123 4
    }
124
125
    /**
126
     * {@inheritdoc}
127
     */
128 1
    public function offsetUnset($offset)
129
    {
130 1
        $this->remove($offset);
131 1
    }
132
133
    /**
134
     * {@inheritdoc}
135
     */
136 1
    public function serialize()
137
    {
138 1
        return serialize($this->items);
139
    }
140
141
    /**
142
     * {@inheritdoc}
143
     */
144 1
    public function unserialize($serialized)
145
    {
146 1
        $this->items = unserialize($serialized);
147 1
    }
148
149
    /**
150
     * {@inheritdoc}
151
     */
152
    public function clear()
153
    {
154
        $this->items = [];
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160 3
    public function contains(...$values)
161
    {
162 3
        foreach ($values as $value) {
163 3
            if (!in_array($value, $this->items, true)) {
164 3
                return false;
165
            }
166
        }
167 3
        return true;
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173 5
    public function get($key, $default = null)
174
    {
175 5
        return array_key_exists($key, $this->items) ? $this->items[$key] : $default;
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181 6
    public function set($key, $value)
182
    {
183 6
        if (isset($key)) {
184 3
            $this->items[(int) $key] = $value;
185
        } else {
186 4
            $this->items[] = $value;
187
        }
188 6
    }
189
190
    /**
191
     * {@inheritdoc}
192
     */
193 2
    public function remove(...$keys)
194
    {
195 2
        foreach ($keys as $key) {
196 2
            unset($this->items[$key]);
197
        }
198 2
        $this->items = array_values($this->items);
199 2
    }
200
201
    /**
202
     * {@inheritdoc}
203
     */
204 1
    public function has(...$keys)
205
    {
206 1
        foreach ($keys as $key) {
207 1
            if (!array_key_exists($key, $this->items)) {
208 1
                return false;
209
            }
210
        }
211 1
        return true;
212
    }
213
214
    /**
215
     * {@inheritdoc}
216
     */
217 1
    public function filter(callable $handler = null)
218
    {
219 1
        if ($handler) {
220 1
            if (defined("ARRAY_FILTER_USE_BOTH")) {
221 1
                return new ArrayList(array_values(array_filter($this->items, $handler, ARRAY_FILTER_USE_BOTH)));
222
            } else {
223
                return new ArrayList(array_values(array_filter($this->items, $handler)));
224
            }
225
        }
226 1
        return new ArrayList(array_values(array_filter($this->items)));
227
    }
228
229
    /**
230
     * {@inheritdoc}
231
     */
232 3
    public function map(callable $handler)
233
    {
234 3
        return new ArrayList(array_map($handler, $this->items, array_keys($this->items)));
235
    }
236
237
    /**
238
     * {@inheritdoc}
239
     */
240 1
    public function reduce(callable $handler, $initial = null)
241
    {
242 1
        foreach ($this as $key => $item) {
243 1
            $initial = $handler($initial, $item, $key);
244
        }
245 1
        return $initial;
246
    }
247
248
    /**
249
     * {@inheritdoc}
250
     */
251 2
    public function groupBy(callable $handler)
252
    {
253 2
        $new = [];
254 2
        foreach ($this as $key => $item) {
255 2
            $groupName = call_user_func($handler, $item, $key);
256 2
            if (!isset($new[$groupName])) {
257 2
                $new[$groupName] = new ArrayList();
258
            }
259 2
            $new[$groupName][] = $item;
260
        }
261 2
        return new ArrayMap($new);
262
    }
263
264
    /**
265
     * {@inheritdoc}
266
     */
267 2
    public function keyBy(callable $handler)
268
    {
269 2
        $new = [];
270 2
        foreach ($this as $key => $item) {
271 2
            $keyName = call_user_func($handler, $item, $key);
272 2
            $new[$keyName] = $item;
273
        }
274 2
        return new ArrayMap($new);
275
    }
276
277
    /**
278
     * {@inheritdoc}
279
     */
280 4
    public function combine(ListInterface $list)
281
    {
282 4
        return new ArrayMap(array_combine($this->items, $list->all()));
283
    }
284
285
    /**
286
     * {@inheritdoc}
287
     */
288 2
    public function first(callable $handler = null, $default = null)
289
    {
290 2
        if ($handler) {
291 2
            foreach ($this->items as $key => $item) {
292 2
                if (call_user_func($handler, $item, $key)) {
293 2
                    return $item;
294
                }
295
            }
296 2
            return $default;
297
        }
298 2
        return isset($this->items[0]) ? $this->items[0] : $default;
299
    }
300
301
    /**
302
     * {@inheritdoc}
303
     */
304 2
    public function last(callable $handler = null, $default = null)
305
    {
306 2
        if ($handler) {
307 2
            $length = count($this->items);
308 2
            for ($i = 0; $i < $length; $i++) {
309 2
                $key = $length - $i - 1;
310 2
                $item = $this->items[$key];
311 2
                if (call_user_func($handler, $item, $key)) {
312 2
                    return $item;
313
                }
314
            }
315 2
            return $default;
316
        }
317 2
        return ($length = count($this->items)) ? $this->items[$length - 1] : $default;
318
    }
319
320
    /**
321
     * {@inheritdoc}
322
     */
323 8
    public function intersect(ListInterface $list)
324
    {
325 8
        return new ArrayList(array_intersect($this->items, $list->all()));
326
    }
327
328
    /**
329
     * {@inheritdoc}
330
     */
331 4
    public function union(ListInterface $list)
332
    {
333 4
        return new ArrayList(array_unique_union($this->items, $list->all()));
334
    }
335
336
    /**
337
     * {@inheritdoc}
338
     */
339 4
    public function merge(ListInterface $list)
340
    {
341 4
        return new ArrayList(array_merge($this->items, $list->all()));
342
    }
343
344
    /**
345
     * {@inheritdoc}
346
     */
347 2
    public function implode($glue = null)
348
    {
349 2
        return implode($glue, $this->items);
350
    }
351
352
    /**
353
     * {@inheritdoc}
354
     */
355 2
    public function isEmpty()
356
    {
357 2
        return $this->count() === 0;
358
    }
359
360
    /**
361
     * {@inheritdoc}
362
     */
363 3
    public function pop()
364
    {
365 3
        return array_pop($this->items);
366
    }
367
368
    /**
369
     * {@inheritdoc}
370
     */
371 1
    public function push(...$values)
372
    {
373 1
        $this->items = array_merge($this->items, $values);
374 1
        return $this;
375
    }
376
377
    /**
378
     * {@inheritdoc}
379
     */
380 1
    public function shift()
381
    {
382 1
        return array_shift($this->items);
383
    }
384
385
    /**
386
     * {@inheritdoc}
387
     */
388 1
    public function unshift(...$values)
389
    {
390 1
        $this->items = array_merge(array_reverse($values), $this->items);
391 1
        return $this;
392
    }
393
394
    /**
395
     * {@inheritdoc}
396
     */
397 2
    public function reverse()
398
    {
399 2
        return new ArrayList(array_reverse($this->items));
400
    }
401
402
    /**
403
     * {@inheritdoc}
404
     */
405 2
    public function shuffle()
406
    {
407 2
        $items = $this->items;
408 2
        shuffle($items);
409 2
        return new ArrayList($items);
410
    }
411
412
    /**
413
     * {@inheritdoc}
414
     */
415 1
    public function sort(callable $callback = null)
416
    {
417 1
        $items = $this->items;
418 1
        if ($callback) {
419 1
            usort($items, $callback);
420
        } else {
421 1
            sort($items);
422
        }
423 1
        return new ArrayList($items);
424
    }
425
    
426
    /**
427
     * {@inheritdoc}
428
     */
429 2
    public function slice($offset, $length = null)
430
    {
431 2
        return new ArrayList(array_slice($this->items, $offset, $length));
432
    }
433
434
    /**
435
     * {@inheritdoc}
436
     */
437 4
    public function splice($offset, $length = null, $replacement = null)
438
    {
439 4
        if ($length) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $length of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
440 2
            return new ArrayList(array_splice($this->items, $offset, $length, $replacement));
441
        }
442 2
        return new ArrayList(array_splice($this->items, $offset));
443
    }
444
    
445
    /**
446
     * {@inheritdoc}
447
     */
448 1
    public function unique()
449
    {
450 1
        return new ArrayList(array_unique($this->items));
451
    }
452
    
453
    /**
454
     * @param mixed $value
455
     * @param string $method
456
     * @param int $order
457
     */
458 4
    private function assertIsNullOrIntegerLessSize($value, $method, $order = 1)
459
    {
460 4
        if (!isset($value)) {
461 4
            return;
462
        }
463 1
        if (is_int($value) && $value <= $this->count()) {
464 1
            return;
465
        }
466 1
        if (is_string($value)) {
467 1
            if ($value == (((int) $value) . '') && $value <= $this->count()) {
468
                return;
469
            }
470
        }
471 1
        throw new InvalidArgumentException("Argument {$order} passed to {$method} must be null or an integer less than the size of the list");
472
    }
473
}
474