Completed
Push — master ( 92a23c...ca331a )
by Lars
02:20
created

Arrayy::filter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.1481

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 2
dl 0
loc 10
ccs 4
cts 6
cp 0.6667
crap 2.1481
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arrayy;
6
7
use voku\helper\UTF8;
8
9
/** @noinspection ClassReImplementsParentInterfaceInspection */
10
11
/**
12
 * Methods to manage arrays.
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
class Arrayy extends \ArrayObject implements \IteratorAggregate, \ArrayAccess, \Serializable, \Countable
18
{
19
  /**
20
   * @var array
21
   */
22
  protected $array = [];
23
24
  /**
25
   * @var string
26
   */
27
  protected $iteratorClass;
28
29
  /**
30
   * @var string
31
   */
32
  protected $pathSeparator = '.';
33
34
  /** @noinspection MagicMethodsValidityInspection */
35
  /**
36
   * Initializes
37
   *
38
   * @param array  $array
39
   * @param string $iteratorClass
40 815
   */
41
  public function __construct($array = [], $iteratorClass = ArrayyIterator::class)
42 815
  {
43 813
    $array = $this->fallbackForArray($array);
44
    $this->array = $array;
45 813
46 813
    $this->setIteratorClass($iteratorClass);
47
  }
48
49
  /**
50
   * Get a value by key.
51
   *
52
   * @param mixed $key
53
   *
54
   * @return mixed <p>Get a Value from the current array.</p>
55 2
   */
56
  public function &__get($key)
57 2
  {
58
    $return = $this->get($key);
59 2
60
    if (\is_array($return)) {
61
      return static::create($return);
62
    }
63 2
64
    return $return;
65
  }
66
67
  /**
68
   * Call object as function.
69
   *
70
   * @param mixed $key
71
   *
72
   * @return mixed
73 1
   */
74
  public function __invoke($key = null)
75 1
  {
76 1
    if ($key !== null) {
77 1
      if (isset($this->array[$key])) {
78
        return $this->array[$key];
79
      }
80
81
      return false;
82
    }
83
84
    return (array)$this->array;
85
  }
86
87
  /**
88
   * Whether or not an element exists by key.
89
   *
90
   * @param mixed $key
91
   *
92
   * @return bool <p>True is the key/index exists, otherwise false.</p>
93
   */
94
  public function __isset($key)
95
  {
96
    return $this->offsetExists($key);
97
  }
98
99
  /**
100
   * Assigns a value to the specified element.
101
   *
102
   * @param mixed $key
103
   * @param mixed $value
104 2
   */
105
  public function __set($key, $value)
106 2
  {
107 2
    $this->internalSet($key, $value);
108
  }
109
110
  /**
111
   * magic to string
112
   *
113
   * @return string
114 16
   */
115
  public function __toString()
116 16
  {
117
    return $this->toString();
118
  }
119
120
  /**
121
   * Unset element by key.
122
   *
123
   * @param mixed $key
124
   */
125
  public function __unset($key)
126
  {
127
    $this->internalRemove($key);
128
  }
129
130
  /**
131
   * alias: for "Arrayy->append()"
132
   *
133
   * @see Arrayy::append()
134
   *
135
   * @param mixed $value
136
   *
137
   * @return static <p>(Mutable) Return this Arrayy object, with the appended values.</p>
138 1
   */
139
  public function add($value)
140 1
  {
141
    return $this->append($value);
142
  }
143
144
  /**
145
   * Append a (key) + value to the current array.
146
   *
147
   * @param mixed $value
148
   * @param mixed $key
149
   *
150
   * @return static <p>(Mutable) Return this Arrayy object, with the appended values.</p>
151 9
   */
152
  public function append($value, $key = null)
153 9
  {
154
    if ($key !== null) {
155
      $this->array[$key] = $value;
156 9
    } else {
157
      $this->array[] = $value;
158
    }
159 9
160
    return $this;
161
  }
162
163
  /**
164
   * Sort the entries by value.
165
   *
166
   * @param int $sort_flags [optional] <p>
167
   *                        You may modify the behavior of the sort using the optional
168
   *                        parameter sort_flags, for details
169
   *                        see sort.
170
   *                        </p>
171
   *
172
   * @return static <p>(Mutable) Return this Arrayy object.</p>
173 4
   */
174
  public function asort(int $sort_flags = 0)
175 4
  {
176
    \asort($this->array, $sort_flags);
177 4
178
    return $this;
179
  }
180
181
  /**
182
   * Count the values from the current array.
183
   *
184
   * alias: for "Arrayy->size()"
185
   *
186
   * @see Arrayy::size()
187
   *
188
   * @param int $mode
189 93
   *
190
   * @return int
191 93
   */
192
  public function count(int $mode = COUNT_NORMAL): int
193
  {
194
    return $this->size($mode);
195
  }
196
197
  /**
198
   * Exchange the array for another one.
199
   *
200
   * @param array|static $data
201 1
   *
202
   * @return array
203 1
   */
204
  public function exchangeArray($data): array
205 1
  {
206
    $this->array = $this->fallbackForArray($data);
207
208
    return $this->array;
209
  }
210
211
  /**
212
   * Creates a copy of the ArrayyObject.
213 1
   *
214
   * @return array
215 1
   */
216
  public function getArrayCopy(): array
217
  {
218
    return $this->array;
219
  }
220
221
  /**
222
   * Returns a new ArrayyIterator, thus implementing the IteratorAggregate interface.
223 20
   *
224
   * @return ArrayyIterator <p>An iterator for the values in the array.</p>
225 20
   */
226
  public function getIterator(): ArrayyIterator
227 20
  {
228
    $iterator = $this->getIteratorClass();
229
230
    return new $iterator($this->array);
231
  }
232
233
  /**
234
   * Gets the iterator classname for the ArrayObject.
235 20
   *
236
   * @return string
237 20
   */
238
  public function getIteratorClass(): string
239
  {
240
    return $this->iteratorClass;
241
  }
242
243
  /**
244
   * Sort the entries by key
245
   *
246
   * @param int $sort_flags [optional] <p>
247
   *                        You may modify the behavior of the sort using the optional
248
   *                        parameter sort_flags, for details
249
   *                        see sort.
250
   *                        </p>
251 4
   *
252
   * @return static <p>(Mutable) Return this Arrayy object.</p>
253 4
   */
254
  public function ksort(int $sort_flags = 0)
255 4
  {
256
    \ksort($this->array, $sort_flags);
257
258
    return $this;
259
  }
260
261
  /**
262
   * Sort an array using a case insensitive "natural order" algorithm
263
   *
264
   * @return static <p>(Mutable) Return this Arrayy object.</p>
265
   */
266
  public function natcasesort()
267
  {
268
    \natcasesort($this->array);
269
270
    return $this;
271
  }
272
273
  /**
274
   * Sort entries using a "natural order" algorithm
275 1
   *
276
   * @return static <p>(Mutable) Return this Arrayy object.</p>
277 1
   */
278
  public function natsort()
279 1
  {
280
    \natsort($this->array);
281
282
    return $this;
283
  }
284
285
  /**
286
   * Whether or not an offset exists.
287
   *
288
   * @param int|float|string $offset
289 40
   *
290
   * @return bool
291 40
   */
292 4
  public function offsetExists($offset): bool
293
  {
294
    if ($this->isEmpty()) {
295
      return false;
296 36
    }
297 1
298 1
    // php cast "bool"-index into "int"-index
299
    if ((bool)$offset === $offset) {
300 36
      $offset = (int)$offset;
301
    }
302
303
    $tmpReturn = \array_key_exists($offset, $this->array);
304 36
305
    if (
306
        $tmpReturn === true
307 12
        ||
308 12
        (
309 12
            $tmpReturn === false
310 36
            &&
311 34
            \strpos((string)$offset, $this->pathSeparator) === false
312
        )
313
    ) {
314 3
      return $tmpReturn;
315
    }
316 3
317
    $offsetExists = false;
318 3
319 3
    if (\strpos((string)$offset, $this->pathSeparator) !== false) {
320 3
321 3
      $offsetExists = false;
322
      $explodedPath = \explode($this->pathSeparator, (string)$offset);
323 3
      $lastOffset = \array_pop($explodedPath);
324 3
      $containerPath = \implode($this->pathSeparator, $explodedPath);
325
326 3
      $this->callAtPath(
327 3
          $containerPath,
328 3
          function ($container) use ($lastOffset, &$offsetExists) {
0 ignored issues
show
Documentation introduced by
function ($container) us...tOffset, $container); } is of type object<Closure>, but the function expects a object<callable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
329 3
            $offsetExists = \array_key_exists($lastOffset, $container);
330
          }
331 3
      );
332
    }
333
334
    return $offsetExists;
335
  }
336
337
  /**
338
   * Returns the value at specified offset.
339
   *
340
   * @param int|float|string $offset
341 26
   *
342
   * @return mixed <p>Will return null if the offset did not exists.</p>
343 26
   */
344
  public function offsetGet($offset)
345
  {
346
    return $this->offsetExists($offset) ? $this->get($offset) : null;
347
  }
348
349
  /**
350
   * Assigns a value to the specified offset.
351
   *
352 17
   * @param int|float|string $offset
353
   * @param mixed            $value
354 17
   */
355 4
  public function offsetSet($offset, $value)
356 4
  {
357 13
    if ($offset === null) {
358
      $this->array[] = $value;
359 17
    } else {
360
      $this->internalSet($offset, $value);
361
    }
362
  }
363
364
  /**
365
   * Unset an offset.
366 7
   *
367
   * @param int|float|string $offset
368 7
   */
369 1
  public function offsetUnset($offset)
370
  {
371
    if ($this->isEmpty()) {
372 6
      return;
373 4
    }
374
375 4
    if (\array_key_exists($offset, $this->array)) {
376
      unset($this->array[$offset]);
377
378 3
      return;
379
    }
380 2
381 2
    if (\strpos((string)$offset, $this->pathSeparator) !== false) {
382
383 2
      $path = \explode($this->pathSeparator, (string)$offset);
384 2
      $pathToUnset = \array_pop($path);
385
386 2
      $this->callAtPath(
387 2
          \implode($this->pathSeparator, $path),
388 2
          function (&$offset) use ($pathToUnset) {
0 ignored issues
show
Documentation introduced by
function (&$offset) use(...ffset[$pathToUnset]); } is of type object<Closure>, but the function expects a object<callable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
389
            unset($offset[$pathToUnset]);
390 2
          }
391 3
      );
392
393
    }
394
  }
395
396
  /**
397
   * Serialize the current "Arrayy"-object.
398 1
   *
399
   * @return string
400 1
   */
401
  public function serialize()
402
  {
403
    return parent::serialize();
404
  }
405
406
  /**
407
   * Sets the iterator classname for the current "Arrayy"-object.
408
   *
409
   * @param string $class
410
   *
411
   * @return void
412 813
   *
413
   * @throws \InvalidArgumentException
414 813
   */
415 813
  public function setIteratorClass($class)
416
  {
417 813
    if (\class_exists($class)) {
418
      $this->iteratorClass = $class;
419
420
      return;
421
    }
422
423
    if (\strpos($class, '\\') === 0) {
424
      $class = '\\' . $class;
425
      if (\class_exists($class)) {
426
        $this->iteratorClass = $class;
427
428
        return;
429
      }
430
    }
431
432
    throw new \InvalidArgumentException('The iterator class does not exist: ' . $class);
433
  }
434
435
  /**
436
   * Sort the entries with a user-defined comparison function and maintain key association.
437
   *
438
   * @param \callable $function
439
   *
440
   * @return static <p>(Mutable) Return this Arrayy object.</p>
441
   *
442
   * @throws \InvalidArgumentException
443
   */
444 View Code Duplication
  public function uasort($function)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
445
  {
446
    if (!\is_callable($function)) {
447
      throw new \InvalidArgumentException(
448
          'Passed function must be callable'
449
      );
450
    }
451
452
    \uasort($this->array, $function);
453
454
    return $this;
455
  }
456
457
  /**
458
   * Sort the entries by keys using a user-defined comparison function.
459
   *
460
   * @param \callable $function
461
   *
462
   * @return static <p>(Mutable) Return this Arrayy object.</p>
463 5
   *
464
   * @throws \InvalidArgumentException
465 5
   */
466
  public function uksort($function)
467
  {
468
    return $this->customSortKeys($function);
469
  }
470
471
  /**
472
   * Unserialize an string and return this object.
473
   *
474
   * @param string $string
475 1
   *
476
   * @return static <p>(Mutable)</p>
477 1
   */
478
  public function unserialize($string)
479 1
  {
480
    parent::unserialize($string);
481
482
    return $this;
483
  }
484
485
  /**
486
   * Add a suffix to each key.
487
   *
488
   * @param mixed $prefix
489 10
   *
490
   * @return static <p>(Immutable) Return an Arrayy object, with the prefixed keys.</p>
491 10
   */
492 10 View Code Duplication
  public function appendToEachKey($prefix)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
493 9
  {
494
    $result = [];
495 9
    foreach ($this->array as $key => $item) {
496
      if ($item instanceof self) {
497
        $result[$prefix . $key] = $item->appendToEachKey($prefix);
498 9
      } elseif (\is_array($item)) {
499
        $result[$prefix . $key] = self::create($item)->appendToEachKey($prefix)->toArray();
500 10
      } else {
501
        $result[$prefix . $key] = $item;
502 10
      }
503
    }
504
505
    return self::create($result);
506
  }
507
508
  /**
509
   * Add a prefix to each value.
510
   *
511
   * @param mixed $prefix
512 10
   *
513
   * @return static <p>(Immutable) Return an Arrayy object, with the prefixed values.</p>
514 10
   */
515 10 View Code Duplication
  public function appendToEachValue($prefix)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
516 9
  {
517
    $result = [];
518 9
    foreach ($this->array as $key => $item) {
519
      if ($item instanceof self) {
520 9
        $result[$key] = $item->appendToEachValue($prefix);
521 1
      } elseif (\is_array($item)) {
522 1
        $result[$key] = self::create($item)->appendToEachValue($prefix)->toArray();
523 8
      } elseif (\is_object($item)) {
524
        $result[$key] = $item;
525 10
      } else {
526
        $result[$key] = $prefix . $item;
527 10
      }
528
    }
529
530
    return self::create($result);
531
  }
532
533
  /**
534
   * Convert an array into a object.
535
   *
536
   * @param array $array PHP array
537 4
   *
538
   * @return \stdClass (object)
539 4
   */
540
  protected static function arrayToObject(array $array = []): \stdClass
541 4
  {
542 1
    $object = new \stdClass();
543
544
    if (!\is_array($array) || \count($array) <= 0) {
545 3
      return $object;
546 3
    }
547 1
548 1
    foreach ($array as $name => $value) {
549
      if (\is_array($value)) {
550 3
        $object->{$name} = self::arrayToObject($value);
551 3
        continue;
552
      }
553 3
      $object->{$name} = $value;
554
    }
555
556
    return $object;
557
  }
558
559
  /**
560
   * Sort an array in reverse order and maintain index association.
561 4
   *
562
   * @return static <p>(Mutable) Return this Arrayy object.</p>
563 4
   */
564
  public function arsort()
565 4
  {
566
    \arsort($this->array);
567
568
    return $this;
569
  }
570
571
  /**
572
   * Iterate over the current array and execute a callback for each loop.
573
   *
574
   * @param \Closure $closure
575 2
   *
576
   * @return static <p>(Immutable)</p>
577 2
   */
578 View Code Duplication
  public function at(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
579 2
  {
580 2
    $array = $this->array;
581 2
582
    foreach ($array as $key => $value) {
583 2
      $closure($value, $key);
584
    }
585
586
    return static::create($array);
587
  }
588
589
  /**
590
   * Returns the average value of the current array.
591
   *
592
   * @param int $decimals <p>The number of decimal-numbers to return.</p>
593 10
   *
594
   * @return int|double <p>The average value.</p>
595 10
   */
596
  public function average($decimals = 0)
597 10
  {
598 2
    $count = $this->count();
599
600
    if (!$count) {
601 8
      return 0;
602 3
    }
603 3
604
    if (!\is_int($decimals)) {
605 8
      $decimals = 0;
606
    }
607
608
    return \round(\array_sum($this->array) / $count, $decimals);
609
  }
610
611
  /**
612
   * @param mixed      $path
613 4
   * @param \callable  $callable
614
   * @param null|array $currentOffset
615 4
   */
616 4
  protected function callAtPath($path, $callable, &$currentOffset = null)
617 4
  {
618
    if ($currentOffset === null) {
619 4
      $currentOffset = &$this->array;
620 4
    }
621
622 4
    $explodedPath = \explode($this->pathSeparator, $path);
623
    $nextPath = \array_shift($explodedPath);
624
625
    if (!isset($currentOffset[$nextPath])) {
626 4
      return;
627 1
    }
628 1
629 1
    if (!empty($explodedPath)) {
630 1
      $this->callAtPath(
631 1
          \implode($this->pathSeparator, $explodedPath),
632 1
          $callable,
633 4
          $currentOffset[$nextPath]
634
      );
635 4
    } else {
636
      $callable($currentOffset[$nextPath]);
637
    }
638
  }
639
640
  /**
641
   * Changes all keys in an array.
642
   *
643
   * @param int $case [optional] <p> Either <strong>CASE_UPPER</strong><br />
644
   *                  or <strong>CASE_LOWER</strong> (default)</p>
645 1
   *
646
   * @return static <p>(Immutable)</p>
647 1
   */
648
  public function changeKeyCase(int $case = CASE_LOWER)
649
  {
650
    return static::create(UTF8::array_change_key_case($this->array, $case));
0 ignored issues
show
Security Bug introduced by
It seems like \voku\helper\UTF8::array...se($this->array, $case) targeting voku\helper\UTF8::array_change_key_case() can also be of type false; however, Arrayy\Arrayy::create() does only seem to accept array, did you maybe forget to handle an error condition?
Loading history...
651
  }
652
653
  /**
654
   * Change the path separator of the array wrapper.
655
   *
656
   * By default, the separator is: "."
657
   *
658
   * @param string $separator <p>Separator to set.</p>
659 1
   *
660
   * @return static <p>Mutable</p>
661 1
   */
662
  public function changeSeparator($separator)
663 1
  {
664
    $this->pathSeparator = $separator;
665
666
    return $this;
667
  }
668
669
  /**
670
   * Create a chunked version of the current array.
671
   *
672
   * @param int  $size         <p>Size of each chunk.</p>
673
   * @param bool $preserveKeys <p>Whether array keys are preserved or no.</p>
674 4
   *
675
   * @return static <p>(Immutable) A new array of chunks from the original array.</p>
676 4
   */
677
  public function chunk($size, $preserveKeys = false)
678 4
  {
679
    $result = \array_chunk($this->array, $size, $preserveKeys);
680
681
    return static::create($result);
682
  }
683
684
  /**
685
   * Clean all falsy values from the current array.
686 8
   *
687
   * @return static <p>(Immutable)</p>
688 8
   */
689
  public function clean()
690 7
  {
691
    return $this->filter(
692 8
        function ($value) {
693
          return (bool)$value;
694
        }
695
    );
696
  }
697
698
  /**
699
   * WARNING!!! -> Clear the current array.
700 4
   *
701
   * @return static <p>(Mutable) Return this Arrayy object, with an empty array.</p>
702 4
   */
703
  public function clear()
704 4
  {
705
    $this->array = [];
706
707
    return $this;
708
  }
709
710
  /**
711
   * Check if an item is in the current array.
712
   *
713
   * @param string|int|float $value
714 13
   * @param bool             $recursive
715
   * @param bool             $strict
716 13
   *
717
   * @return bool
718
   */
719
  public function contains($value, $recursive = false, $strict = true): bool
720
  {
721
    if ($recursive === true) {
722
      return $this->in_array_recursive($value, $this->array, $strict);
723
    }
724
725
    return \in_array($value, $this->array, $strict);
726 13
  }
727
728 13
  /**
729 13
   * @param mixed $needle   <p>
730 13
   *                        The searched value.
731
   *                        </p>
732 13
   *                        <p>
733 13
   *                        If needle is a string, the comparison is done
734 13
   *                        in a case-sensitive manner.
735 13
   *                        </p>
736 13
   * @param array $haystack <p>
737
   *                        The array.
738 13
   *                        </p>
739
   * @param bool  $strict   [optional] <p>
740
   *                        If the third parameter strict is set to true
741
   *                        then the in_array function will also check the
742
   *                        types of the
743
   *                        needle in the haystack.
744
   *                        </p>
745
   *
746
   * @return bool true if needle is found in the array, false otherwise.
747
   */
748 4
  protected function in_array_recursive($needle, array $haystack = null, $strict = true): bool
749
  {
750 4
    if ($haystack === null) {
751
      $haystack = $this->array;
752
    }
753
754
    foreach ($haystack as $item) {
755
756
      if (\is_array($item) === true) {
757
        $returnTmp = $this->in_array_recursive($needle, $item, $strict);
758
      } else {
759
        $returnTmp = ($strict === true ? $item === $needle : $item == $needle);
760 1
      }
761
762 1
      if ($returnTmp === true) {
763
        return true;
764
      }
765
    }
766
767
    return false;
768
  }
769
770
  /**
771
   * Check if an (case-insensitive) string is in the current array.
772
   *
773
   * @param string $value
774 9
   * @param bool   $recursive
775
   *
776 9
   * @return bool
777
   */
778
  public function containsCaseInsensitive($value, $recursive = false): bool
779
  {
780
    if ($recursive === true) {
781
      return $this->in_array_recursive(
782
          UTF8::strtoupper($value),
783
          $this->walk(
784
              function (&$val) {
0 ignored issues
show
Documentation introduced by
function (&$val) { $...F8::strtoupper($val); } is of type object<Closure>, but the function expects a object<callable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
785
                $val = UTF8::strtoupper($val);
786 1
              },
787
              true
788 1
          )->getArray(),
789
          true
790
      );
791
    }
792
793
    return \in_array(
794
        UTF8::strtoupper($value),
795
        $this->walk(
796
            function (&$val) {
0 ignored issues
show
Documentation introduced by
function (&$val) { $...F8::strtoupper($val); } is of type object<Closure>, but the function expects a object<callable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
797
              $val = UTF8::strtoupper($val);
798
            },
799
            false
800
        )->getArray(),
801
        true
802 1
    );
803
  }
804 1
805
  /**
806
   * Check if the given key/index exists in the array.
807
   *
808
   * @param string|int|float $key <p>key/index to search for</p>
809
   *
810
   * @return bool <p>Returns true if the given key/index exists in the array, false otherwise.</p>
811
   */
812
  public function containsKey($key): bool
813
  {
814 522
    return $this->offsetExists($key);
815
  }
816 522
817
  /**
818
   * Check if all given needles are present in the array as key/index.
819
   *
820
   * @param array $needles <p>The keys you are searching for.</p>
821
   * @param bool  $recursive
822
   *
823
   * @return bool <p>Returns true if all the given keys/indexes exists in the array, false otherwise.</p>
824
   */
825
  public function containsKeys(array $needles, $recursive = false): bool
826 1
  {
827
    if ($recursive === true) {
828 1
      return \count(\array_intersect($needles, $this->keys(true)->getArray())) === \count($needles, COUNT_RECURSIVE);
829
    }
830 1
831
    return \count(\array_intersect($needles, $this->keys()->getArray())) === \count($needles);
832 1
  }
833
834
  /**
835
   * Check if all given needles are present in the array as key/index.
836
   *
837
   * @param array $needles <p>The keys you are searching for.</p>
838
   *
839
   * @return bool <p>Returns true if all the given keys/indexes exists in the array, false otherwise.</p>
840
   */
841
  public function containsKeysRecursive(array $needles): bool
842 5
  {
843
    return $this->containsKeys($needles, true);
844 5
  }
845
846 5
  /**
847
   * alias: for "Arrayy->contains()"
848
   *
849
   * @see Arrayy::contains()
850
   *
851
   * @param string|int|float $value
852
   *
853
   * @return bool
854
   */
855
  public function containsValue($value): bool
856 4
  {
857
    return $this->contains($value);
858 4
  }
859 4
860
  /**
861 3
   * alias: for "Arrayy->contains($value, true)"
862 4
   *
863
   * @see Arrayy::contains()
864 4
   *
865
   * @param string|int|float $value
866
   *
867
   * @return bool
868
   */
869
  public function containsValueRecursive($value): bool
870
  {
871
    return $this->contains($value, true);
872
  }
873
874 5
  /**
875
   * Check if all given needles are present in the array.
876 5
   *
877
   * @param array $needles
878
   *
879
   * @return bool <p>Returns true if all the given values exists in the array, false otherwise.</p>
880
   */
881
  public function containsValues(array $needles): bool
882
  {
883
    return \count(\array_intersect($needles, $this->array)) === \count($needles);
884
  }
885
886
  /**
887
   * Counts all the values of an array
888
   *
889 8
   * @link http://php.net/manual/en/function.array-count-values.php
890
   *
891 8
   * @return static <p>
892 1
   *                (Immutable)
893
   *                An associative Arrayy-object of values from input as
894 1
   *                keys and their count as value.
895 1
   *                </p>
896 1
   */
897
  public function countValues()
898 1
  {
899 7
    return new static(\array_count_values($this->array));
900
  }
901
902
  /**
903 8
   * Creates an Arrayy object.
904
   *
905
   * @param array $array
906
   *
907 8
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
908 8
   */
909 8
  public static function create($array = [])
910 8
  {
911 8
    return new static($array);
912
  }
913 8
914
  /**
915
   * WARNING: Creates an Arrayy object by reference.
916
   *
917
   * @param array $array
918
   *
919
   * @return static <p>(Mutable) Return this Arrayy object.</p>
920
   */
921
  public function createByReference(&$array = [])
922
  {
923
    $array = $this->fallbackForArray($array);
924
925 1
    $this->array = &$array;
926
927 1
    return $this;
928
  }
929
930
  /**
931
   * Create an new Arrayy object via JSON.
932
   *
933
   * @param string $json
934
   *
935
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
936
   */
937
  public static function createFromJson(string $json)
938
  {
939
    $array = UTF8::json_decode($json, true);
940
941 5
    return static::create($array);
942
  }
943 5
944
  /**
945
   * Create an new instance filled with values from an object that have implemented ArrayAccess.
946
   *
947
   * @param \ArrayAccess $object <p>Object that implements ArrayAccess</p>
948
   *
949 5
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
950
   */
951 5
  public static function createFromObject(\ArrayAccess $object)
952
  {
953
    $array = new static();
954
    foreach ($object as $key => $value) {
955
      /** @noinspection OffsetOperationsInspection */
956
      $array[$key] = $value;
957
    }
958
959
    return $array;
960
  }
961
962
  /**
963
   * Create an new instance filled with values from an object.
964
   *
965 5
   * @param object $object
966
   *
967 5
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
968
   */
969
  public static function createFromObjectVars($object)
970
  {
971
    return new static(self::objectToArray($object));
972
  }
973 5
974
  /**
975 5
   * Create an new Arrayy object via string.
976
   *
977
   * @param string      $str       <p>The input string.</p>
978
   * @param string|null $delimiter <p>The boundary string.</p>
979
   * @param string|null $regEx     <p>Use the $delimiter or the $regEx, so if $pattern is null, $delimiter will be
980
   *                               used.</p>
981
   *
982
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
983
   */
984
  public static function createFromString(string $str, string $delimiter = null, string $regEx = null)
985 12
  {
986
    if ($regEx) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $regEx of type null|string is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
987 12
      \preg_match_all($regEx, $str, $array);
988
989 12
      if (!empty($array)) {
990
        $array = $array[0];
991
      }
992
993
    } else {
994
      $array = \explode($delimiter, $str);
995
    }
996
997
    // trim all string in the array
998
    \array_walk(
999
        $array,
1000 1
        function (&$val) {
1001
          /** @noinspection ReferenceMismatchInspection */
1002 1
          if (\is_string($val)) {
1003
            $val = \trim($val);
1004
          }
1005
        }
1006 1
    );
1007 1
1008 1
    return static::create($array);
1009 1
  }
1010 1
1011 1
  /**
1012
   * Create an new instance containing a range of elements.
1013
   *
1014 1
   * @param mixed $low  <p>First value of the sequence.</p>
1015 1
   * @param mixed $high <p>The sequence is ended upon reaching the end value.</p>
1016 1
   * @param int   $step <p>Used as the increment between elements in the sequence.</p>
1017 1
   *
1018 1
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
1019 1
   */
1020 1
  public static function createWithRange($low, $high, int $step = 1)
1021 1
  {
1022 1
    return static::create(\range($low, $high, $step));
1023 1
  }
1024 1
1025
  /**
1026 1
   * Custom sort by index via "uksort".
1027 1
   *
1028
   * @link http://php.net/manual/en/function.uksort.php
1029 1
   *
1030
   * @param \callable $function
1031 1
   *
1032
   * @return static <p>(Mutable) Return this Arrayy object.</p>
1033
   *
1034
   * @throws \InvalidArgumentException
1035
   */
1036 View Code Duplication
  public function customSortKeys($function)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
1037
  {
1038
    if (!\is_callable($function)) {
1039
      throw new \InvalidArgumentException(
1040
          'Passed function must be callable'
1041 8
      );
1042
    }
1043 8
1044
    \uksort($this->array, $function);
1045 8
1046
    return $this;
1047
  }
1048
1049
  /**
1050
   * Custom sort by value via "usort".
1051
   *
1052
   * @link http://php.net/manual/en/function.usort.php
1053 1
   *
1054
   * @param \callable $function
1055 1
   *
1056
   * @return static <p>(Mutable) Return this Arrayy object.</p>
1057 1
   *
1058 1
   * @throws \InvalidArgumentException
1059
   */
1060 1 View Code Duplication
  public function customSortValues($function)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
1061
  {
1062
    if (!\is_callable($function)) {
1063
      throw new \InvalidArgumentException(
1064
          'Passed function must be callable'
1065
      );
1066
    }
1067
1068
    \usort($this->array, $function);
1069
1070 4
    return $this;
1071
  }
1072 4
1073
  /**
1074 4
   * Return values that are only in the current array.
1075 4
   *
1076 4
   * @param array $array
1077
   *
1078 4
   * @return static <p>(Immutable)</p>
1079
   */
1080
  public function diff(array $array = [])
1081
  {
1082
    $result = \array_diff($this->array, $array);
1083
1084
    return static::create($result);
1085
  }
1086
1087
  /**
1088 4
   * Return values that are only in the current multi-dimensional array.
1089
   *
1090 4
   * @param array      $array
1091 4
   * @param null|array $helperVariableForRecursion <p>(only for internal usage)</p>
1092 3
   *
1093 1
   * @return static <p>(Immutable)</p>
1094 1
   */
1095
  public function diffRecursive(array $array = [], $helperVariableForRecursion = null)
1096 4
  {
1097
    $result = [];
1098 4
1099
    if (
1100
        $helperVariableForRecursion !== null
1101
        &&
1102
        \is_array($helperVariableForRecursion)
1103
    ) {
1104
      $arrayForTheLoop = $helperVariableForRecursion;
1105
    } else {
1106
      $arrayForTheLoop = $this->array;
1107
    }
1108
1109
    foreach ($arrayForTheLoop as $key => $value) {
1110
      if (\array_key_exists($key, $array)) {
1111
        if (\is_array($value)) {
1112
          $recursiveDiff = $this->diffRecursive($array[$key], $value);
1113
          if (!empty($recursiveDiff)) {
1114
            $result[$key] = $recursiveDiff;
1115
          }
1116
        } else {
1117
          if ($value != $array[$key]) {
1118 815
            $result[$key] = $value;
1119
          }
1120 815
        }
1121 812
      } else {
1122
        $result[$key] = $value;
1123
      }
1124 11
    }
1125 1
1126
    return static::create($result);
1127
  }
1128 10
1129 6
  /**
1130
   * Return values that are only in the new $array.
1131
   *
1132 9
   * @param array $array
1133
   *
1134 9
   * @return static <p>(Immutable)</p>
1135
   */
1136
  public function diffReverse(array $array = [])
1137
  {
1138
    $result = \array_diff($array, $this->array);
1139 9
1140
    return static::create($result);
1141
  }
1142
1143 9
  /**
1144
   * Divide an array into two arrays. One with keys and the other with values.
1145
   *
1146
   * @return static <p>(Immutable)</p>
1147
   */
1148
  public function divide()
1149 9
  {
1150
    return static::create(
1151 2
        [
1152 9
            $this->keys(),
1153 7
            $this->values(),
1154
        ]
1155
    );
1156 2
  }
1157
1158 2
  /**
1159
   * Iterate over the current array and modify the array's value.
1160
   *
1161
   * @param \Closure $closure
1162
   *
1163
   * @return static <p>(Immutable)</p>
1164
   */
1165 View Code Duplication
  public function each(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
1166
  {
1167
    $array = $this->array;
1168
1169
    foreach ($array as $key => $value) {
1170
      $array[$key] = $closure($value, $key);
1171
    }
1172
1173
    return static::create($array);
1174
  }
1175
1176
  /**
1177
   * Check if a value is in the current array using a closure.
1178
   *
1179
   * @param \Closure $closure
1180
   *
1181
   * @return bool <p>Returns true if the given value is found, false otherwise.</p>
1182
   */
1183
  public function exists(\Closure $closure): bool
1184
  {
1185
    $isExists = false;
1186
    foreach ($this->array as $key => $value) {
1187
      if ($closure($value, $key)) {
1188
        $isExists = true;
1189 9
        break;
1190
      }
1191 9
    }
1192 1
1193
    return $isExists;
1194
  }
1195 9
1196
  /**
1197
   * create a fallback for array
1198
   *
1199 9
   * 1. use the current array, if it's a array
1200
   * 2. call "getArray()" on object, if there is a "Arrayy"-object
1201 9
   * 3. fallback to empty array, if there is nothing
1202
   * 4. call "createFromObject()" on object, if there is a "\ArrayAccess"-object
1203
   * 5. call "__toArray()" on object, if the method exists
1204
   * 6. cast a string or object with "__toString()" into an array
1205
   * 7. throw a "InvalidArgumentException"-Exception
1206
   *
1207
   * @param $array
1208
   *
1209
   * @return array
1210
   *
1211 1
   * @throws \InvalidArgumentException
1212
   */
1213 1
  protected function fallbackForArray(&$array): array
1214 1
  {
1215 1
    if (\is_array($array)) {
1216 1
      return $array;
1217 1
    }
1218 1
1219 1
    if ($array instanceof self) {
1220 1
      return $array->getArray();
1221 1
    }
1222 1
1223 1
    if (!$array) {
1224 1
      return [];
1225 1
    }
1226
1227
    $isObject = \is_object($array);
1228 9
1229
    if ($isObject && $array instanceof \ArrayAccess) {
1230
      /** @noinspection ReferenceMismatchInspection */
1231
      return static::createFromObject($array)->getArray();
1232
    }
1233
1234
    if ($isObject && $array instanceof \ArrayObject) {
1235
      return $array->getArrayCopy();
1236
    }
1237
1238
    if ($isObject && \method_exists($array, '__toArray')) {
1239
      return (array)$array->__toArray();
1240
    }
1241
1242
    /** @noinspection ReferenceMismatchInspection */
1243
    if (
1244
        \is_string($array)
1245
        ||
1246
        ($isObject && \method_exists($array, '__toString'))
1247
    ) {
1248
      return [(string)$array];
1249
    }
1250
1251
    throw new \InvalidArgumentException(
1252
        'Passed value should be a array'
1253 1
    );
1254
  }
1255 1
1256 1
  /**
1257 1
   * Find all items in an array that pass the truth test.
1258
   *
1259
   * @param \Closure|null $closure [optional] <p>
1260
   *                               The callback function to use
1261 1
   *                               </p>
1262 1
   *                               <p>
1263
   *                               If no callback is supplied, all entries of
1264
   *                               input equal to false (see
1265 1
   *                               converting to
1266
   *                               boolean) will be removed.
1267
   *                               </p>
1268 1
   *
1269
   *  * @param int $flag [optional] <p>
1270
   *                               Flag determining what arguments are sent to <i>callback</i>:
1271 1
   *                               </p><ul>
1272
   *                               <li>
1273 1
   *                               <b>ARRAY_FILTER_USE_KEY</b> [1] - pass key as the only argument
1274 1
   *                               to <i>callback</i> instead of the value</span>
1275
   *                               </li>
1276
   *                               <li>
1277 1
   *                               <b>ARRAY_FILTER_USE_BOTH</b> [2] - pass both value and key as
1278
   *                               arguments to <i>callback</i> instead of the value</span>
1279
   *                               </li>
1280 1
   *                               </ul>
1281
   *
1282
   * @return static <p>(Immutable)</p>
1283 1
   */
1284
  public function filter($closure = null, int $flag = 0)
1285 1
  {
1286 1
    if (!$closure) {
1287
      return $this->clean();
1288
    }
1289 1
1290
    $array = \array_filter($this->array, $closure, $flag);
1291
1292 1
    return static::create($array);
1293
  }
1294
1295 1
  /**
1296 1
   * Filters an array of objects (or a numeric array of associative arrays) based on the value of a particular property
1297
   * within that.
1298 1
   *
1299 1
   * @param string          $property
1300 1
   * @param string|string[] $value
1301
   * @param string          $comparisonOp
1302 1
   *                            <p>
1303 1
   *                            'eq' (equals),<br />
1304 1
   *                            'gt' (greater),<br />
1305 1
   *                            'gte' || 'ge' (greater or equals),<br />
1306
   *                            'lt' (less),<br />
1307 1
   *                            'lte' || 'le' (less or equals),<br />
1308 1
   *                            'ne' (not equals),<br />
1309 1
   *                            'contains',<br />
1310
   *                            'notContains',<br />
1311 1
   *                            'newer' (via strtotime),<br />
1312
   *                            'older' (via strtotime),<br />
1313 1
   *                            </p>
1314 1
   *
1315
   * @return static <p>(Immutable)</p>
1316 1
   */
1317
  public function filterBy(string $property, $value, string $comparisonOp = null)
1318
  {
1319
    if (!$comparisonOp) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $comparisonOp of type null|string is loosely compared to false; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1320
      $comparisonOp = \is_array($value) ? 'contains' : 'eq';
1321
    }
1322
1323
    $ops = [
1324
        'eq'          => function ($item, $prop, $value) {
1325
          return $item[$prop] === $value;
1326
        },
1327 8
        'gt'          => function ($item, $prop, $value) {
1328
          return $item[$prop] > $value;
1329 8
        },
1330 6
        'ge'          => function ($item, $prop, $value) {
1331 5
          return $item[$prop] >= $value;
1332
        },
1333 5
        'gte'         => function ($item, $prop, $value) {
1334
          return $item[$prop] >= $value;
1335 3
        },
1336
        'lt'          => function ($item, $prop, $value) {
1337
          return $item[$prop] < $value;
1338
        },
1339
        'le'          => function ($item, $prop, $value) {
1340
          return $item[$prop] <= $value;
1341
        },
1342
        'lte'         => function ($item, $prop, $value) {
1343
          return $item[$prop] <= $value;
1344
        },
1345
        'ne'          => function ($item, $prop, $value) {
1346
          return $item[$prop] !== $value;
1347
        },
1348
        'contains'    => function ($item, $prop, $value) {
1349
          return \in_array($item[$prop], (array)$value, true);
1350
        },
1351
        'notContains' => function ($item, $prop, $value) {
1352
          return !\in_array($item[$prop], (array)$value, true);
1353
        },
1354
        'newer'       => function ($item, $prop, $value) {
1355
          return \strtotime($item[$prop]) > \strtotime($value);
1356
        },
1357 13
        'older'       => function ($item, $prop, $value) {
1358
          return \strtotime($item[$prop]) < \strtotime($value);
1359 13
        },
1360 13
    ];
1361
1362 13
    $result = \array_values(
1363 3
        \array_filter(
1364
            (array)$this->array,
1365
            function ($item) use (
1366 10
                $property,
1367
                $value,
1368
                $ops,
1369
                $comparisonOp
1370
            ) {
1371
              $item = (array)$item;
1372
              $itemArrayy = new Arrayy($item);
1373
              $item[$property] = $itemArrayy->get($property, []);
1374
1375
              return $ops[$comparisonOp]($item, $property, $value);
1376 28
            }
1377
        )
1378 28
    );
1379 7
1380 7
    return static::create($result);
1381 7
  }
1382 21
1383 21
  /**
1384 21
   * Find the first item in an array that passes the truth test,
1385
   *  otherwise return false
1386
   *
1387 28
   * @param \Closure $closure
1388
   *
1389
   * @return mixed|false <p>Return false if we did not find the value.</p>
1390
   */
1391
  public function find(\Closure $closure)
1392
  {
1393
    foreach ($this->array as $key => $value) {
1394
      if ($closure($value, $key)) {
1395
        return $value;
1396
      }
1397 26
    }
1398
1399 26
    return false;
1400 11
  }
1401 11
1402 15
  /**
1403 15
   * find by ...
1404
   *
1405
   * @param string          $property
1406 26
   * @param string|string[] $value
1407
   * @param string          $comparisonOp
1408
   *
1409
   * @return static <p>(Immutable)</p>
1410
   */
1411
  public function findBy(string $property, $value, string $comparisonOp = 'eq')
1412
  {
1413
    return $this->filterBy($property, $value, $comparisonOp);
1414 1
  }
1415
1416 1
  /**
1417
   * Get the first value from the current array.
1418 1
   *
1419
   * @return mixed <p>Return null if there wasn't a element.</p>
1420
   */
1421
  public function first()
1422
  {
1423
    $tmpArray = $this->array;
1424
    $result = \array_shift($tmpArray);
1425
1426
    if ($result === null) {
1427
      return null;
1428
    }
1429
1430
    return $result;
1431 61
  }
1432
1433
  /**
1434
   * Get the first value(s) from the current array.
1435 61
   *
1436 3
   * @param int|null $number <p>How many values you will take?</p>
1437 61
   *
1438 3
   * @return static <p>(Immutable)</p>
1439 3
   */
1440 59
  public function firstsImmutable(int $number = null)
1441
  {
1442
    if ($number === null) {
1443 61
      $arrayTmp = $this->array;
1444 1
      $array = (array)\array_shift($arrayTmp);
1445
    } else {
1446
      $number = (int)$number;
1447
      $arrayTmp = $this->array;
1448 61
      $array = \array_splice($arrayTmp, 0, $number, true);
1449 2
    }
1450 2
1451
    return static::create($array);
1452 61
  }
1453 51
1454 6
  /**
1455
   * Get the first value(s) from the current array.
1456
   *
1457 47
   * @param int|null $number <p>How many values you will take?</p>
1458
   *
1459
   * @return static <p>(Mutable)</p>
1460
   */
1461 20
  public function firstsMutable(int $number = null)
1462 20
  {
1463 19
    if ($number === null) {
1464
      $this->array = (array)\array_shift($this->array);
1465
    } else {
1466 5
      $number = (int)$number;
1467 5
      $this->array = \array_splice($this->array, 0, $number, true);
1468
    }
1469 5
1470
    return $this;
1471
  }
1472
1473 5
  /**
1474
   * Exchanges all keys with their associated values in an array.
1475
   *
1476
   * @return static <p>(Immutable)</p>
1477
   */
1478
  public function flip()
1479
  {
1480
    $result = \array_flip($this->array);
1481 536
1482
    return static::create($result);
1483 536
  }
1484
1485 536
  /**
1486
   * Get a value from an array (optional using dot-notation).
1487
   *
1488
   * @param mixed $key       <p>The key to look for.</p>
1489
   * @param mixed $fallback  <p>Value to fallback to.</p>
1490
   * @param array $array     <p>The array to get from, if it's set to "null" we use the current array from the
1491
   *                         class.</p>
1492
   *
1493
   * @return mixed
1494
   */
1495
  public function get($key, $fallback = null, array $array = null)
1496
  {
1497
    if ($array !== null) {
1498
      $usedArray = $array;
1499
    } else {
1500 1
      $usedArray = $this->array;
1501
    }
1502 1
1503
    if ($key === null) {
1504 1
      return static::create($usedArray);
1505
    }
1506
1507
    // php cast "bool"-index into "int"-index
1508
    if ((bool)$key === $key) {
1509
      $key = (int)$key;
1510
    }
1511
1512
    if (\array_key_exists($key, $usedArray) === true) {
1513
      if (\is_array($usedArray[$key])) {
1514 38
        return static::create($usedArray[$key]);
1515
      }
1516 38
1517 10
      return $usedArray[$key];
1518
    }
1519 10
1520 2
    // Crawl through array, get key according to object or not
1521 2
    foreach (\explode($this->pathSeparator, (string)$key) as $segment) {
1522 8
      if (!isset($usedArray[$segment])) {
1523
        return $fallback instanceof \Closure ? $fallback() : $fallback;
1524 10
      }
1525
1526
      $usedArray = $usedArray[$segment];
1527
    }
1528 38
1529
    if (\is_array($usedArray)) {
1530 38
      return static::create($usedArray);
1531
    }
1532
1533
    return $usedArray;
1534 38
  }
1535
1536
  /**
1537
   * Get the current array from the "Arrayy"-object.
1538
   *
1539
   * @return array
1540
   */
1541
  public function getArray(): array
1542
  {
1543
    \array_map(['self', 'internalGetArray'], $this->array);
1544 1
1545
    return $this->array;
1546 1
  }
1547
1548
  /**
1549
   * Returns the values from a single column of the input array, identified by
1550
   * the $columnKey, can be used to extract data-columns from multi-arrays.
1551
   *
1552
   * Info: Optionally, you may provide an $indexKey to index the values in the returned
1553
   * array by the values from the $indexKey column in the input array.
1554 4
   *
1555
   * @param mixed $columnKey
1556 4
   * @param mixed $indexKey
1557
   *
1558
   * @return static <p>(Immutable)</p>
1559
   */
1560
  public function getColumn($columnKey = null, $indexKey = null)
1561
  {
1562
    $result = \array_column($this->array, $columnKey, $indexKey);
1563
1564
    return static::create($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by \array_column($this->arr... $columnKey, $indexKey) on line 1562 can also be of type false or null; however, Arrayy\Arrayy::create() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1565
  }
1566 3
1567
  /**
1568 3
   * Get correct PHP constant for direction.
1569
   *
1570
   * @param int|string $direction
1571
   *
1572
   * @return int
1573
   */
1574
  protected function getDirection($direction): int
1575
  {
1576
    if (\is_string($direction)) {
1577
      $direction = \strtolower($direction);
1578 3
1579
      if ($direction === 'desc') {
1580 3
        $direction = SORT_DESC;
1581
      } else {
1582
        $direction = SORT_ASC;
1583
      }
1584
    }
1585
1586
    if (
1587
        $direction !== SORT_DESC
1588
        &&
1589
        $direction !== SORT_ASC
1590
    ) {
1591
      $direction = SORT_ASC;
1592 9
    }
1593
1594 9
    return $direction;
1595
  }
1596
1597
  /**
1598
   * alias: for "Arrayy->keys()"
1599
   *
1600
   * @see Arrayy::keys()
1601
   *
1602
   * @return static <p>(Immutable)</p>
1603
   */
1604 3
  public function getKeys()
1605
  {
1606 3
    return $this->keys();
1607
  }
1608
1609
  /**
1610
   * Get the current array from the "Arrayy"-object as object.
1611
   *
1612
   * @return \stdClass (object)
1613
   */
1614
  public function getObject(): \stdClass
1615
  {
1616
    return self::arrayToObject($this->getArray());
1617
  }
1618 6
1619
  /**
1620 6
   * alias: for "Arrayy->randomImmutable()"
1621
   *
1622
   * @see Arrayy::randomImmutable()
1623
   *
1624
   * @return static <p>(Immutable)</p>
1625
   */
1626
  public function getRandom()
1627
  {
1628
    return $this->randomImmutable();
1629
  }
1630
1631 3
  /**
1632
   * alias: for "Arrayy->randomKey()"
1633 3
   *
1634 3
   * @see Arrayy::randomKey()
1635
   *
1636
   * @return mixed <p>Get a key/index or null if there wasn't a key/index.</p>
1637 3
   */
1638
  public function getRandomKey()
1639 3
  {
1640 3
    return $this->randomKey();
1641
  }
1642 3
1643
  /**
1644
   * alias: for "Arrayy->randomKeys()"
1645
   *
1646 3
   * @see Arrayy::randomKeys()
1647 3
   *
1648 3
   * @param int $number
1649
   *
1650
   * @return static <p>(Immutable)</p>
1651 3
   */
1652 2
  public function getRandomKeys(int $number)
1653 1
  {
1654 1
    return $this->randomKeys($number);
1655 1
  }
1656 1
1657 1
  /**
1658
   * alias: for "Arrayy->randomValue()"
1659 2
   *
1660
   * @see Arrayy::randomValue()
1661 3
   *
1662
   * @return mixed <p>get a random value or null if there wasn't a value.</p>
1663 3
   */
1664
  public function getRandomValue()
1665
  {
1666
    return $this->randomValue();
1667
  }
1668
1669
  /**
1670
   * alias: for "Arrayy->randomValues()"
1671
   *
1672
   * @see Arrayy::randomValues()
1673 22
   *
1674
   * @param int $number
1675
   *
1676 22
   * @return static <p>(Immutable)</p>
1677
   */
1678 22
  public function getRandomValues(int $number)
1679
  {
1680
    return $this->randomValues($number);
1681
  }
1682
1683
  /**
1684
   * Group values from a array according to the results of a closure.
1685
   *
1686
   * @param \callable $grouper <p>A callable function name.</p>
1687
   * @param bool      $saveKeys
1688 28
   *
1689
   * @return static <p>(Immutable)</p>
1690 28
   */
1691
  public function group($grouper, bool $saveKeys = false)
1692
  {
1693
    $array = (array)$this->array;
1694
    $result = [];
1695
1696
    // Iterate over values, group by property/results from closure
1697
    foreach ($array as $key => $value) {
1698
1699 28
      $groupKey = \is_callable($grouper) ? $grouper($value, $key) : $this->get($grouper, null, $array);
1700
      $newValue = $this->get($groupKey, null, $result);
1701 28
1702 28
      if ($groupKey instanceof self) {
1703
        $groupKey = $groupKey->getArray();
1704 28
      }
1705 28
1706 28
      if ($newValue instanceof self) {
1707 28
        $newValue = $newValue->getArray();
1708 28
      }
1709
1710 28
      // Add to results
1711 28
      if ($groupKey !== null) {
1712
        if ($saveKeys) {
1713
          $result[$groupKey] = $newValue;
1714 28
          $result[$groupKey][$key] = $value;
1715
        } else {
1716
          $result[$groupKey] = $newValue;
1717
          $result[$groupKey][] = $value;
1718
        }
1719
      }
1720
1721
    }
1722
1723
    return static::create($result);
1724
  }
1725
1726
  /**
1727
   * Check if an array has a given key.
1728 3
   *
1729
   * @param mixed $key
1730 3
   *
1731
   * @return bool
1732 3
   */
1733 3
  public function has($key): bool
1734 2
  {
1735 2
    // Generate unique string to use as marker.
1736 3
    $unFound = \uniqid('arrayy', true);
1737
1738 3
    return $this->get($key, $unFound) !== $unFound;
1739
  }
1740
1741
  /**
1742
   * Implodes the keys of this array.
1743
   *
1744
   * @param string $glue
1745
   *
1746
   * @return string
1747
   */
1748
  public function implodeKeys(string $glue = ''): string
1749
  {
1750 4
    return $this->implode_recursive($glue, $this->array, true);
1751
  }
1752 4
1753
  /**
1754
   * Implodes the values of this array.
1755
   *
1756
   * @param string $glue
1757
   *
1758
   * @return string
1759
   */
1760
  public function implode(string $glue = ''): string
1761
  {
1762 12
    return $this->implode_recursive($glue, $this->array, false);
1763
  }
1764 12
1765
  /**
1766 12
   * @param mixed               $glue
1767
   * @param string|array|static $pieces
1768
   * @param bool                $useKeys
1769
   *
1770
   * @return string
1771
   */
1772 446
  protected function implode_recursive($glue = '', $pieces, bool $useKeys = false): string
1773
  {
1774 446
    if ($pieces instanceof self) {
1775
      $pieces = $pieces->getArray();
1776
    }
1777
1778
    if (\is_array($pieces)) {
1779
      $pieces_count = \count($pieces);
1780
      $pieces_count_not_zero = $pieces_count > 0;
1781
1782
      return \implode(
1783
          $glue,
1784 446
          \array_map(
1785
              [$this, 'implode_recursive'],
1786
              \array_fill(0, ($pieces_count_not_zero ? $pieces_count : 1), $glue),
1787
              ($useKeys === true && $pieces_count_not_zero ? $this->array_keys_recursive($pieces) : $pieces)
1788 446
          )
1789
      );
1790
    }
1791
1792
    return (string)$pieces;
1793
  }
1794
1795
  /**
1796
   * Given a list and an iterate-function that returns
1797 18
   * a key for each element in the list (or a property name),
1798
   * returns an object with an index of each item.
1799 18
   *
1800
   * Just like groupBy, but for when you know your keys are unique.
1801
   *
1802 18
   * @param mixed $key
1803
   *
1804
   * @return static <p>(Immutable)</p>
1805
   */
1806
  public function indexBy($key)
1807
  {
1808
    $results = [];
1809
1810
    foreach ($this->array as $a) {
1811
      if (\array_key_exists($key, $a) === true) {
1812 18
        $results[$a[$key]] = $a;
1813
      }
1814 18
    }
1815
1816 18
    return static::create($results);
1817
  }
1818
1819
  /**
1820
   * alias: for "Arrayy->searchIndex()"
1821
   *
1822
   * @see Arrayy::searchIndex()
1823
   *
1824
   * @param mixed $value <p>The value to search for.</p>
1825
   *
1826
   * @return mixed
1827 30
   */
1828
  public function indexOf($value)
1829 30
  {
1830
    return $this->searchIndex($value);
1831
  }
1832
1833
  /**
1834 30
   * Get everything but the last..$to items.
1835 30
   *
1836
   * @param int $to
1837
   *
1838 30
   * @return static <p>(Immutable)</p>
1839 3
   */
1840
  public function initial(int $to = 1)
1841
  {
1842
    $slice = \count($this->array) - $to;
1843
1844 3
    return $this->firstsImmutable($slice);
1845
  }
1846
1847
  /**
1848 3
   * @param mixed $value
1849 3
   */
1850
  protected function internalGetArray(&$value)
1851 30
  {
1852
    if ($value instanceof self) {
1853 30
1854
      $valueTmp = $value->getArray();
1855
      if (\count($valueTmp) === 0) {
1856
        $value = [];
1857
      } else {
1858
        /** @noinspection PhpUnusedLocalVariableInspection */
1859
        $value = &$valueTmp;
1860
      }
1861
1862
    } elseif ($value instanceof \JsonSerializable) {
0 ignored issues
show
Bug introduced by
The class JsonSerializable does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
1863 2
      /** @noinspection PhpUnusedLocalVariableInspection */
1864
      $value = &$value->jsonSerialize();
1865 2
    }
1866
  }
1867
1868
  /**
1869
   * Internal mechanics of remove method.
1870
   *
1871
   * @param mixed $key
1872
   *
1873
   * @return bool
1874
   */
1875 1
  protected function internalRemove($key): bool
1876
  {
1877 1
    $path = \explode($this->pathSeparator, (string)$key);
1878
1879
    // Crawl though the keys
1880
    while (\count($path) > 1) {
1881
      $key = \array_shift($path);
1882
1883
      if (!$this->has($key)) {
1884
        return false;
1885
      }
1886
1887
      $this->array = &$this->array[$key];
1888 1
    }
1889
1890
    $key = \array_shift($path);
1891 1
1892 1
    unset($this->array[$key]);
1893 1
1894
    return true;
1895
  }
1896 1
1897 1
  /**
1898 1
   * Internal mechanic of set method.
1899 1
   *
1900
   * @param mixed $key
1901
   * @param mixed $value
1902 1
   *
1903
   * @return bool
1904
   */
1905
  protected function internalSet($key, $value): bool
1906
  {
1907
    if ($key === null) {
1908
      return false;
1909
    }
1910 15
1911
    // init
1912 15
    $array =& $this->array;
1913 3
    $path = \explode($this->pathSeparator, (string)$key);
1914
1915
    // Crawl through the keys
1916 13
    while (\count($path) > 1) {
1917 13
      $key = \array_shift($path);
1918 11
1919
      // If the key doesn't exist at this depth, we will just create an empty array
1920 3
      // to hold the next value, allowing us to create the arrays to hold final
1921
      // values at the correct depth. Then we'll keep digging into the array.
1922 3
      if (!isset($array[$key]) || !\is_array($array[$key])) {
1923
        $array[$key] = static::create([]);
1924
      }
1925
1926
      $array =& $array[$key];
1927
    }
1928
1929
    $array[\array_shift($path)] = $value;
1930 88
1931
    return true;
1932 88
  }
1933
1934
  /**
1935
   * Return an array with all elements found in input array.
1936
   *
1937
   * @param array $search
1938
   *
1939
   * @return static <p>(Immutable)</p>
1940
   */
1941
  public function intersection(array $search)
1942
  {
1943
    return static::create(\array_values(\array_intersect($this->array, $search)));
1944
  }
1945
1946
  /**
1947
   * Return a boolean flag which indicates whether the two input arrays have any common elements.
1948
   *
1949
   * @param array $search
1950
   *
1951
   * @return bool
1952 14
   */
1953
  public function intersects(array $search): bool
1954 14
  {
1955
    return \count($this->intersection($search)->array) > 0;
1956
  }
1957
1958
  /**
1959
   * Invoke a function on all of an array's values.
1960
   *
1961
   * @param mixed $callable
1962 5
   * @param mixed $arguments
1963
   *
1964 5
   * @return static <p>(Immutable)</p>
1965 2
   */
1966
  public function invoke($callable, $arguments = [])
1967
  {
1968 4
    // If one argument given for each iteration, create an array for it.
1969 4
    if (!\is_array($arguments)) {
1970 2
      $arguments = StaticArrayy::repeat($arguments, \count($this->array))->getArray();
1971
    }
1972 3
1973
    // If the callable has arguments, pass them.
1974 2
    if ($arguments) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $arguments of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1975
      $array = \array_map($callable, $this->array, $arguments);
1976
    } else {
1977
      $array = \array_map($callable, $this->array);
1978
    }
1979
1980
    return static::create($array);
1981
  }
1982 1
1983
  /**
1984 1
   * Check whether array is associative or not.
1985
   *
1986
   * @param bool $recursive
1987
   *
1988
   * @return bool <p>Returns true if associative, false otherwise.</p>
1989
   */
1990
  public function isAssoc(bool $recursive = false): bool
1991
  {
1992
    if ($this->isEmpty()) {
1993
      return false;
1994
    }
1995
1996
    foreach ($this->keys($recursive)->getArray() as $key) {
1997
      if (!\is_string($key)) {
1998
        return false;
1999
      }
2000 25
    }
2001
2002 25
    return true;
2003
  }
2004
2005
  /**
2006
   * Check whether the array is empty or not.
2007
   *
2008
   * @return bool <p>Returns true if empty, false otherwise.</p>
2009
   */
2010
  public function isEmpty(): bool
2011
  {
2012
    return !$this->array;
2013
  }
2014
2015
  /**
2016 4
   * Check if the current array is equal to the given "$array" or not.
2017
   *
2018 4
   * @param array $array
2019
   *
2020 4
   * @return bool
2021
   */
2022
  public function isEqual(array $array): bool
2023
  {
2024
    return ($this->array === $array);
2025
  }
2026
2027
  /**
2028 4
   * Check if the current array is a multi-array.
2029
   *
2030 4
   * @return bool
2031
   */
2032
  public function isMultiArray(): bool
2033
  {
2034
    return !(\count($this->array) === \count($this->array, COUNT_RECURSIVE));
2035
  }
2036
2037
  /**
2038
   * Check whether array is numeric or not.
2039
   *
2040 13
   * @return bool <p>Returns true if numeric, false otherwise.</p>
2041
   */
2042 13
  public function isNumeric(): bool
2043 1
  {
2044
    if ($this->isEmpty()) {
2045
      return false;
2046 12
    }
2047 8
2048
    foreach ($this->keys() as $key) {
2049 8
      if (!\is_int($key)) {
2050 1
        return false;
2051 1
      }
2052 7
    }
2053
2054
    return true;
2055 8
  }
2056 8
2057 4
  /**
2058 4
   * Check if the current array is sequential [0, 1, 2, 3, 4, 5 ...] or not.
2059
   *
2060
   * @param bool $recursive
2061 12
   *
2062
   * @return bool
2063
   */
2064
  public function isSequential(bool $recursive = false): bool
2065
  {
2066
    if ($recursive === true) {
2067
      return $this->array_keys_recursive($this->array) === \range(0, \count($this->array, COUNT_RECURSIVE) - 1);
2068
    }
2069
2070
    return \array_keys($this->array) === \range(0, \count($this->array) - 1);
2071 13
  }
2072
2073 13
  /**
2074 1
   * @return array
2075
   */
2076
  public function jsonSerialize(): array
2077 12
  {
2078 8
    return $this->getArray();
2079
  }
2080 8
2081 1
  /**
2082 1
   * Get all keys from the current array.
2083 7
   *
2084
   * @param bool  $recursive    [optional] <p>
2085
   *                            Get all keys, also from all sub-arrays from an multi-dimensional array.
2086 8
   *                            </p>
2087 8
   * @param mixed $search_value [optional] <p>
2088 4
   *                            If specified, then only keys containing these values are returned.
2089 4
   *                            </p>
2090
   * @param bool  $strict       [optional] <p>
2091
   *                            Determines if strict comparison (===) should be used during the search.
2092 12
   *                            </p>
2093
   *
2094
   * @return static <p>(Immutable) An array of all the keys in input.</p>
2095
   */
2096
  public function keys(bool $recursive = false, $search_value = null, bool $strict = true)
2097
  {
2098
    if ($recursive === true) {
2099
      if ($search_value === null) {
2100
        $array = $this->array_keys_recursive($this->array);
2101
      } else {
2102
        $array = $this->array_keys_recursive($this->array, $search_value, $strict);
2103
      }
2104 10
    } else {
2105
      if ($search_value === null) {
2106 10
        $array = \array_keys($this->array);
2107
      } else {
2108
        $array = \array_keys($this->array, $search_value, $strict);
2109
      }
2110
    }
2111
2112
    return static::create($array);
2113
  }
2114
2115
  /**
2116
   * @param array $input        <p>
2117 4
   *                            An array containing keys to return.
2118
   *                            </p>
2119 4
   * @param mixed $search_value [optional] <p>
2120
   *                            If specified, then only keys containing these values are returned.
2121 4
   *                            </p>
2122
   * @param bool  $strict       [optional] <p>
2123
   *                            Determines if strict comparison (===) should be used during the search.
2124
   *                            </p>
2125
   *
2126
   * @return array an array of all the keys in input.
2127
   */
2128
  protected function array_keys_recursive(array $input = null, $search_value = null, bool $strict = true): array
2129
  {
2130
    // init
2131 15
    $keys = [];
2132
2133 15
    if ($input === null) {
2134 2
      $input = $this->array;
2135
    }
2136
2137
    foreach ($input as $key => $value) {
2138 13
2139
      if (
2140 13
          $search_value === null
2141 13
          ||
2142
          (
2143 13
              \is_array($search_value) === true
2144 7
              &&
2145
              \in_array($key, $search_value, $strict)
2146 9
          )
2147
      ) {
2148 7
        $keys[] = $key;
2149
      }
2150
2151
      // recursive needed?
2152
      if (\is_array($value) === true) {
2153
        $keys = \array_merge($keys, $this->array_keys_recursive($value));
2154
      }
2155
    }
2156
2157
    return $keys;
2158 14
  }
2159
2160 14
  /**
2161 2
   * Sort an array by key in reverse order.
2162
   *
2163
   * @param int $sort_flags [optional] <p>
2164
   *                        You may modify the behavior of the sort using the optional
2165 12
   *                        parameter sort_flags, for details
2166
   *                        see sort.
2167 12
   *                        </p>
2168 12
   *
2169
   * @return static <p>(Mutable) Return this Arrayy object.</p>
2170 12
   */
2171 9
  public function krsort(int $sort_flags = 0)
2172
  {
2173 5
    krsort($this->array, $sort_flags);
2174
2175 4
    return $this;
2176
  }
2177
2178
  /**
2179
   * Get the last value from the current array.
2180
   *
2181
   * @return mixed <p>Return null if there wasn't a element.</p>
2182
   */
2183 10
  public function last()
2184
  {
2185 10
    return $this->pop();
2186 1
  }
2187
2188
  /**
2189 9
   * Get the last value(s) from the current array.
2190
   *
2191
   * @param int|null $number
2192
   *
2193
   * @return static <p>(Immutable)</p>
2194
   */
2195
  public function lastsImmutable(int $number = null)
2196
  {
2197
    if ($this->isEmpty()) {
2198
      return static::create();
2199
    }
2200
2201
    if ($number === null) {
2202 25
      $poppedValue = $this->pop();
2203
2204 25
      if ($poppedValue === null) {
2205 4
        $poppedValue = [$poppedValue];
2206 4
      } else {
2207 21
        $poppedValue = (array)$poppedValue;
2208
      }
2209
2210 25
      $arrayy = static::create($poppedValue);
2211
    } else {
2212
      $number = (int)$number;
2213
      $arrayy = $this->rest(-$number);
2214
    }
2215
2216
    return $arrayy;
2217
  }
2218
2219
  /**
2220
   * Get the last value(s) from the current array.
2221
   *
2222
   * @param int|null $number
2223
   *
2224 16
   * @return static <p>(Mutable)</p>
2225
   */
2226 16
  public function lastsMutable(int $number = null)
2227 4
  {
2228 4
    if ($this->isEmpty()) {
2229 12
      return $this;
2230
    }
2231
2232 16
    if ($number === null) {
2233
      $poppedValue = $this->pop();
2234
2235
      if ($poppedValue === null) {
2236
        $poppedValue = [$poppedValue];
2237
      } else {
2238
        $poppedValue = (array)$poppedValue;
2239
      }
2240
2241
      $this->array = static::create($poppedValue)->array;
2242
    } else {
2243
      $number = (int)$number;
2244
      $this->array = $this->rest(-$number)->array;
2245 16
    }
2246
2247 16
    return $this;
2248 4
  }
2249 4
2250 12
  /**
2251
   * Count the values from the current array.
2252
   *
2253 16
   * alias: for "Arrayy->size()"
2254
   *
2255
   * @see Arrayy::size()
2256
   *
2257
   * @param int $mode
2258
   *
2259
   * @return int
2260
   */
2261
  public function length(int $mode = COUNT_NORMAL): int
2262
  {
2263
    return $this->size($mode);
2264
  }
2265
2266
  /**
2267 17
   * Apply the given function to the every element of the array,
2268
   * collecting the results.
2269 17
   *
2270 4
   * @param \callable $callable
2271 4
   *
2272 13
   * @return static <p>(Immutable) Arrayy object with modified elements.</p>
2273
   */
2274
  public function map($callable)
2275 17
  {
2276
    $result = \array_map($callable, $this->array);
2277
2278
    return static::create($result);
2279
  }
2280
2281
  /**
2282
   * Check if all items in current array match a truth test.
2283 10
   *
2284
   * @param \Closure $closure
2285 10
   *
2286 1
   * @return bool
2287
   */
2288 View Code Duplication
  public function matches(\Closure $closure): bool
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
2289 9
  {
2290
    if (\count($this->array) === 0) {
2291
      return false;
2292
    }
2293
2294
    // init
2295
    $array = $this->array;
2296
2297
    foreach ($array as $key => $value) {
2298
      $value = $closure($value, $key);
2299
2300
      if ($value === false) {
2301
        return false;
2302 1
      }
2303
    }
2304 1
2305
    return true;
2306 1
  }
2307 1
2308 1
  /**
2309 1
   * Check if any item in the current array matches a truth test.
2310 1
   *
2311 1
   * @param \Closure $closure
2312 1
   *
2313 1
   * @return bool
2314 1
   */
2315 1 View Code Duplication
  public function matchesAny(\Closure $closure): bool
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
2316 1
  {
2317 1
    if (\count($this->array) === 0) {
2318 1
      return false;
2319 1
    }
2320 1
2321 1
    // init
2322 1
    $array = $this->array;
2323 1
2324
    foreach ($array as $key => $value) {
2325
      $value = $closure($value, $key);
2326
2327 1
      if ($value === true) {
2328
        return true;
2329
      }
2330
    }
2331
2332
    return false;
2333
  }
2334
2335
  /**
2336
   * Get the max value from an array.
2337 5
   *
2338
   * @return mixed
2339 5
   */
2340 4
  public function max()
2341
  {
2342
    if ($this->count() === 0) {
2343 5
      return false;
2344 5
    }
2345 5
2346
    return max($this->array);
2347 5
  }
2348
2349
  /**
2350
   * Merge the new $array into the current array.
2351
   *
2352
   * - keep key,value from the current array, also if the index is in the new $array
2353
   *
2354
   * @param array $array
2355
   * @param bool  $recursive
2356
   *
2357
   * @return static <p>(Immutable)</p>
2358
   */
2359 View Code Duplication
  public function mergeAppendKeepIndex(array $array = [], bool $recursive = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
2360
  {
2361
    if (true === $recursive) {
2362
      $result = \array_replace_recursive($this->array, $array);
2363
    } else {
2364
      $result = \array_replace($this->array, $array);
2365
    }
2366
2367
    return static::create($result);
2368
  }
2369
2370
  /**
2371
   * Merge the new $array into the current array.
2372 4
   *
2373
   * - replace duplicate assoc-keys from the current array with the key,values from the new $array
2374 4
   * - create new indexes
2375
   *
2376 4
   * @param array $array
2377
   * @param bool  $recursive
2378
   *
2379
   * @return static <p>(Immutable)</p>
2380
   */
2381 View Code Duplication
  public function mergeAppendNewIndex(array $array = [], bool $recursive = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
2382
  {
2383
    if (true === $recursive) {
2384 16
      $result = \array_merge_recursive($this->array, $array);
2385
    } else {
2386 16
      $result = \array_merge($this->array, $array);
2387
    }
2388
2389
    return static::create($result);
2390
  }
2391
2392
  /**
2393
   * Merge the the current array into the $array.
2394
   *
2395
   * - use key,value from the new $array, also if the index is in the current array
2396
   *
2397 8
   * @param array $array
2398
   * @param bool  $recursive
2399 8
   *
2400 8
   * @return static <p>(Immutable)</p>
2401 8
   */
2402 View Code Duplication
  public function mergePrependKeepIndex(array $array = [], bool $recursive = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
2403 1
  {
2404
    if (true === $recursive) {
2405
      $result = \array_replace_recursive($array, $this->array);
2406 8
    } else {
2407
      $result = \array_replace($array, $this->array);
2408
    }
2409
2410
    return static::create($result);
2411
  }
2412
2413
  /**
2414
   * Merge the current array into the new $array.
2415
   *
2416 10
   * - replace duplicate assoc-keys from new $array with the key,values from the current array
2417
   * - create new indexes
2418 10
   *
2419 10
   * @param array $array
2420 9
   * @param bool  $recursive
2421
   *
2422 9
   * @return static <p>(Immutable)</p>
2423
   */
2424 View Code Duplication
  public function mergePrependNewIndex(array $array = [], bool $recursive = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
2425 9
  {
2426
    if (true === $recursive) {
2427
      $result = \array_merge_recursive($array, $this->array);
2428 10
    } else {
2429
      $result = \array_merge($array, $this->array);
2430 10
    }
2431
2432
    return static::create($result);
2433
  }
2434
2435
  /**
2436
   * Get the min value from an array.
2437
   *
2438
   * @return mixed
2439
   */
2440 10
  public function min()
2441
  {
2442 10
    if ($this->count() === 0) {
2443 10
      return false;
2444 9
    }
2445
2446 9
    return min($this->array);
2447
  }
2448 9
2449 1
  /**
2450 1
   * Move an array element to a new index.
2451 8
   *
2452
   * cherry-picked from: http://stackoverflow.com/questions/12624153/move-an-array-element-to-a-new-index-in-php
2453 10
   *
2454
   * @param int|string $from
2455 10
   * @param int|string $to
2456
   *
2457
   * @return static <p>(Immutable)</p>
2458
   */
2459
  public function moveElement($from, $to)
2460
  {
2461
    $array = $this->array;
2462
2463 4
    if (\is_int($from)) {
2464
      $tmp = \array_splice($array, $from, 1);
2465 4
      \array_splice($array, $to, 0, $tmp);
2466 4
      $output = $array;
2467 4
    } elseif (\is_string($from)) {
2468 4
      $indexToMove = \array_search($from, \array_keys($array), true);
2469
      $itemToMove = $array[$from];
2470 4
      \array_splice($array, $indexToMove, 1);
2471
      $i = 0;
2472
      $output = [];
2473
      foreach ($array as $key => $item) {
2474
        if ($i == $to) {
2475
          $output[$from] = $itemToMove;
2476
        }
2477
        $output[$key] = $item;
2478
        $i++;
2479
      }
2480 17
    } else {
2481
      $output = [];
2482 17
    }
2483
2484
    return static::create($output);
2485
  }
2486 17
2487 14
  /**
2488
   * Convert a object into an array.
2489 14
   *
2490
   * @param object $object
2491
   *
2492 5
   * @return mixed
2493 5
   */
2494
  protected static function objectToArray($object)
2495 5
  {
2496
    if (!\is_object($object)) {
2497
      return $object;
2498
    }
2499
2500
    if (\is_object($object)) {
2501
      $object = \get_object_vars($object);
2502
    }
2503
2504
    return \array_map(['self', 'objectToArray'], $object);
2505 4
  }
2506
2507 4
  /**
2508
   * Get a subset of the items from the given array.
2509 4
   *
2510
   * @param mixed[] $keys
2511
   *
2512
   * @return static <p>(Immutable)</p>
2513 4
   */
2514
  public function only(array $keys)
2515
  {
2516
    $array = $this->array;
2517
2518
    return static::create(\array_intersect_key($array, \array_flip($keys)));
2519
  }
2520
2521
  /**
2522
   * Pad array to the specified size with a given value.
2523
   *
2524
   * @param int   $size  <p>Size of the result array.</p>
2525 14
   * @param mixed $value <p>Empty value by default.</p>
2526
   *
2527 14
   * @return static <p>(Immutable) Arrayy object padded to $size with $value.</p>
2528 14
   */
2529
  public function pad(int $size, $value)
2530 14
  {
2531 3
    $result = \array_pad($this->array, $size, $value);
2532 3
2533 3
    return static::create($result);
2534 3
  }
2535
2536 3
  /**
2537 3
   * Pop a specified value off the end of the current array.
2538
   *
2539
   * @return mixed <p>(Mutable) The popped element from the current array.</p>
2540 11
   */
2541
  public function pop()
2542 11
  {
2543
    return \array_pop($this->array);
2544
  }
2545
2546
  /**
2547
   * Prepend a (key) + value to the current array.
2548
   *
2549
   * @param mixed $value
2550
   * @param mixed $key
2551
   *
2552 17
   * @return static <p>(Mutable) Return this Arrayy object, with the prepended value.</p>
2553
   */
2554 17
  public function prepend($value, $key = null)
2555
  {
2556
    if ($key === null) {
2557
      \array_unshift($this->array, $value);
2558 17
    } else {
2559 7
      /** @noinspection AdditionOperationOnArraysInspection */
2560 7
      $this->array = [$key => $value] + $this->array;
2561
    }
2562 7
2563
    return $this;
2564
  }
2565 11
2566
  /**
2567 11
   * Add a suffix to each key.
2568
   *
2569
   * @param mixed $suffix
2570
   *
2571
   * @return static <p>(Immutable) Return an Arrayy object, with the prepended keys.</p>
2572
   */
2573 View Code Duplication
  public function prependToEachKey($suffix)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
2574
  {
2575 4
    $result = [];
2576
    foreach ($this->array as $key => $item) {
2577 4
      if ($item instanceof self) {
2578
        $result[$key] = $item->prependToEachKey($suffix);
2579 4
      } elseif (\is_array($item)) {
2580
        $result[$key] = self::create($item)->prependToEachKey($suffix)->toArray();
2581
      } else {
2582
        $result[$key . $suffix] = $item;
2583 4
      }
2584
2585
    }
2586
2587
    return self::create($result);
2588
  }
2589
2590
  /**
2591
   * Add a suffix to each value.
2592
   *
2593 7
   * @param mixed $suffix
2594
   *
2595 7
   * @return static <p>(Immutable) Return an Arrayy object, with the prepended values.</p>
2596
   */
2597 7 View Code Duplication
  public function prependToEachValue($suffix)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
2598
  {
2599
    $result = [];
2600
    foreach ($this->array as $key => $item) {
2601
      if ($item instanceof self) {
2602
        $result[$key] = $item->prependToEachValue($suffix);
2603
      } elseif (\is_array($item)) {
2604
        $result[$key] = self::create($item)->prependToEachValue($suffix)->toArray();
2605
      } elseif (\is_object($item)) {
2606
        $result[$key] = $item;
2607
      } else {
2608
        $result[$key] = $item . $suffix;
2609
      }
2610 9
    }
2611
2612 9
    return self::create($result);
2613 9
  }
2614 9
2615 2
  /**
2616 1
   * Push one or more values onto the end of array at once.
2617 1
   *
2618 2
   * @return static <p>(Mutable) Return this Arrayy object, with pushed elements to the end of array.</p>
2619 9
   */
2620 View Code Duplication
  public function push(/* variadic arguments allowed */)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
2621 9
  {
2622
    if (\func_num_args()) {
2623
      $args = \array_merge([&$this->array], \func_get_args());
2624
      \array_push(...$args);
2625
    }
2626
2627
    return $this;
2628
  }
2629
2630
  /**
2631
   * Get a random value from the current array.
2632 4
   *
2633
   * @param null|int $number <p>How many values you will take?</p>
2634 4
   *
2635
   * @return static <p>(Immutable)</p>
2636 4
   */
2637
  public function randomImmutable(int $number = null)
2638
  {
2639 4
    if ($this->count() === 0) {
2640
      return static::create();
2641
    }
2642 4
2643 View Code Duplication
    if ($number === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
2644
      $arrayRandValue = [$this->array[\array_rand($this->array)]];
2645
2646
      return static::create($arrayRandValue);
2647
    }
2648
2649
    $arrayTmp = $this->array;
2650 9
    \shuffle($arrayTmp);
2651
2652 9
    return static::create($arrayTmp)->firstsImmutable($number);
2653
  }
2654 9
2655
  /**
2656
   * Pick a random key/index from the keys of this array.
2657
   *
2658
   * @return mixed <p>Get a key/index or null if there wasn't a key/index.</p>
2659
   *
2660
   * @throws \RangeException If array is empty
2661
   */
2662
  public function randomKey()
2663
  {
2664 1
    $result = $this->randomKeys(1);
2665
2666 1
    if (!isset($result[0])) {
2667
      $result[0] = null;
2668 1
    }
2669 1
2670 1
    return $result[0];
2671 1
  }
2672 1
2673
  /**
2674 1
   * Pick a given number of random keys/indexes out of this array.
2675
   *
2676
   * @param int $number <p>The number of keys/indexes (should be <= $this->count())</p>
2677
   *
2678
   * @return static <p>(Immutable)</p>
2679
   *
2680
   * @throws \RangeException If array is empty
2681
   */
2682
  public function randomKeys(int $number)
2683
  {
2684 18
    $count = $this->count();
2685
2686
    if ($number === 0 || $number > $count) {
2687 18
      throw new \RangeException(
2688
          \sprintf(
2689
              'Number of requested keys (%s) must be equal or lower than number of elements in this array (%s)',
2690
              $number,
2691
              $count
2692
          )
2693
      );
2694
    }
2695 18
2696
    $result = (array)\array_rand($this->array, $number);
2697 18
2698
    return static::create($result);
2699
  }
2700
2701
  /**
2702
   * Get a random value from the current array.
2703
   *
2704
   * @param null|int $number <p>How many values you will take?</p>
2705 7
   *
2706
   * @return static <p>(Mutable)</p>
2707 7
   */
2708 7
  public function randomMutable(int $number = null)
2709
  {
2710 7
    if ($this->count() === 0) {
2711
      return static::create();
2712
    }
2713
2714 View Code Duplication
    if ($number === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
2715
      $arrayRandValue = [$this->array[\array_rand($this->array)]];
2716
      $this->array = $arrayRandValue;
2717
2718 7
      return $this;
2719
    }
2720 7
2721 7
    \shuffle($this->array);
2722
2723 7
    return $this->firstsMutable($number);
2724
  }
2725
2726
  /**
2727
   * Pick a random value from the values of this array.
2728
   *
2729
   * @return mixed <p>Get a random value or null if there wasn't a value.</p>
2730
   */
2731
  public function randomValue()
2732
  {
2733 7
    $result = $this->randomImmutable();
2734
2735 7
    if (!isset($result[0])) {
2736 7
      $result[0] = null;
2737 6
    }
2738 6
2739
    return $result[0];
2740
  }
2741 6
2742 6
  /**
2743 7
   * Pick a given number of random values out of this array.
2744
   *
2745 7
   * @param int $number
2746 7
   *
2747 7
   * @return static <p>(Mutable)</p>
2748
   */
2749 7
  public function randomValues(int $number)
2750
  {
2751
    return $this->randomMutable($number);
2752
  }
2753
2754
  /**
2755
   * Get a random value from an array, with the ability to skew the results.
2756
   *
2757
   * Example: randomWeighted(['foo' => 1, 'bar' => 2]) has a 66% chance of returning bar.
2758
   *
2759 1
   * @param array    $array
2760
   * @param null|int $number <p>How many values you will take?</p>
2761 1
   *
2762 1
   * @return static <p>(Immutable)</p>
2763
   */
2764
  public function randomWeighted(array $array, int $number = null)
2765 1
  {
2766
    $options = [];
2767
    foreach ($array as $option => $weight) {
2768
      if ($this->searchIndex($option) !== false) {
2769
        for ($i = 0; $i < $weight; ++$i) {
2770
          $options[] = $option;
2771
        }
2772
      }
2773
    }
2774
2775
    return $this->mergeAppendKeepIndex($options)->randomImmutable($number);
2776
  }
2777 2
2778
  /**
2779 2
   * Reduce the current array via callable e.g. anonymous-function.
2780
   *
2781 2
   * @param \callable $callable
2782
   * @param array     $init
2783
   *
2784
   * @return static <p>(Immutable)</p>
2785
   */
2786
  public function reduce($callable, array $init = [])
2787
  {
2788
    $result = \array_reduce($this->array, $callable, $init);
2789
2790
    if ($result === null) {
2791 2
      $this->array = [];
2792
    } else {
2793 2
      $this->array = (array)$result;
2794
    }
2795 2
2796
    return static::create($this->array);
2797
  }
2798
2799
  /**
2800
   * Create a numerically re-indexed Arrayy object.
2801
   *
2802
   * @return static <p>(Mutable) Return this Arrayy object, with re-indexed array-elements.</p>
2803
   */
2804
  public function reindex()
2805 2
  {
2806
    $this->array = \array_values($this->array);
2807 2
2808
    return $this;
2809 2
  }
2810
2811
  /**
2812
   * Return all items that fail the truth test.
2813
   *
2814
   * @param \Closure $closure
2815
   *
2816
   * @return static <p>(Immutable)</p>
2817
   */
2818 View Code Duplication
  public function reject(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
2819 1
  {
2820
    $filtered = [];
2821 1
2822 1
    foreach ($this->array as $key => $value) {
2823
      if (!$closure($value, $key)) {
2824 1
        $filtered[$key] = $value;
2825
      }
2826
    }
2827
2828
    return static::create($filtered);
2829
  }
2830
2831
  /**
2832
   * Remove a value from the current array (optional using dot-notation).
2833
   *
2834
   * @param mixed $key
2835 3
   *
2836
   * @return static <p>(Immutable)</p>
2837 3
   */
2838 3
  public function remove($key)
2839
  {
2840 3
    // recursive call
2841 3
    if (\is_array($key)) {
2842 3
      foreach ($key as $k) {
2843
        $this->internalRemove($k);
2844 3
      }
2845
2846
      return static::create($this->array);
2847
    }
2848
2849
    $this->internalRemove($key);
2850
2851
    return static::create($this->array);
2852
  }
2853
2854
  /**
2855 1
   * Remove the first value from the current array.
2856
   *
2857 1
   * @return static <p>(Immutable)</p>
2858
   */
2859 1
  public function removeFirst()
2860
  {
2861 1
    $tmpArray = $this->array;
2862
    \array_shift($tmpArray);
2863 1
2864
    return static::create($tmpArray);
2865
  }
2866
2867
  /**
2868
   * Remove the last value from the current array.
2869
   *
2870
   * @return static <p>(Immutable)</p>
2871
   */
2872
  public function removeLast()
2873 15
  {
2874
    $tmpArray = $this->array;
2875 15
    \array_pop($tmpArray);
2876
2877 15
    return static::create($tmpArray);
2878
  }
2879
2880
  /**
2881
   * Removes a particular value from an array (numeric or associative).
2882
   *
2883
   * @param mixed $value
2884
   *
2885 8
   * @return static <p>(Immutable)</p>
2886
   */
2887 8
  public function removeValue($value)
2888
  {
2889 8
    $isNumericArray = true;
2890
    foreach ($this->array as $key => $item) {
2891
      if ($item === $value) {
2892
        if (!\is_int($key)) {
2893
          $isNumericArray = false;
2894
        }
2895
        unset($this->array[$key]);
2896
      }
2897
    }
2898
2899
    if ($isNumericArray) {
2900
      $this->array = \array_values($this->array);
2901
    }
2902
2903 4
    return static::create($this->array);
2904
  }
2905 4
2906
  /**
2907 4
   * Generate array of repeated arrays.
2908
   *
2909
   * @param int $times <p>How many times has to be repeated.</p>
2910
   *
2911
   * @return Arrayy
2912
   */
2913
  public function repeat($times): Arrayy
2914
  {
2915
    if ($times === 0) {
2916
      return new static();
2917 20
    }
2918
2919 20
    return static::create(\array_fill(0, (int)$times, $this->array));
2920
  }
2921
2922
  /**
2923
   * Replace a key with a new key/value pair.
2924
   *
2925
   * @param mixed $replace
2926
   * @param mixed $key
2927
   * @param mixed $value
2928
   *
2929 9
   * @return static <p>(Immutable)</p>
2930
   */
2931
  public function replace($replace, $key, $value)
2932 9
  {
2933
    $this->remove($replace);
2934 9
2935
    return $this->set($key, $value);
2936
  }
2937
2938
  /**
2939 9
   * Create an array using the current array as values and the other array as keys.
2940 1
   *
2941 1
   * @param array $keys <p>An array of keys.</p>
2942
   *
2943 9
   * @return static <p>(Immutable) Arrayy object with keys from the other array.</p>
2944 7
   */
2945 7
  public function replaceAllKeys(array $keys)
2946
  {
2947
    $result = \array_combine($keys, $this->array);
2948 9
2949
    return static::create($result);
2950
  }
2951
2952
  /**
2953
   * Create an array using the current array as keys and the other array as values.
2954
   *
2955
   * @param array $array <p>An array o values.</p>
2956
   *
2957
   * @return static <p>(Immutable) Arrayy object with values from the other array.</p>
2958
   */
2959 17
  public function replaceAllValues(array $array)
2960
  {
2961 17
    $result = \array_combine($this->array, $array);
2962
2963 17
    return static::create($result);
2964
  }
2965
2966
  /**
2967
   * Replace the keys in an array with another set.
2968
   *
2969
   * @param array $keys <p>An array of keys matching the array's size</p>
2970
   *
2971
   * @return static <p>(Immutable)</p>
2972
   */
2973
  public function replaceKeys(array $keys)
2974
  {
2975
    $values = \array_values($this->array);
2976 11
    $result = \array_combine($keys, $values);
2977
2978
    return static::create($result);
2979 11
  }
2980 4
2981 4
  /**
2982
   * Replace the first matched value in an array.
2983 11
   *
2984
   * @param mixed $search      <p>The value to replace.</p>
2985
   * @param mixed $replacement <p>The value to replace.</p>
2986
   *
2987
   * @return static <p>(Immutable)</p>
2988
   */
2989
  public function replaceOneValue($search, $replacement = '')
2990
  {
2991 4
    $array = $this->array;
2992
    $key = \array_search($search, $array, true);
2993 4
2994
    if ($key !== false) {
2995
      $array[$key] = $replacement;
2996
    }
2997
2998
    return static::create($array);
2999
  }
3000
3001
  /**
3002
   * Replace values in the current array.
3003 1
   *
3004
   * @param mixed $search      <p>The value to replace.</p>
3005 1
   * @param mixed $replacement <p>What to replace it with.</p>
3006
   *
3007 1
   * @return static <p>(Immutable)</p>
3008 1
   */
3009 1
  public function replaceValues($search, $replacement = '')
3010 1
  {
3011 1
    $array = $this->each(
3012 1
        function ($value) use ($search, $replacement) {
3013 1
          return UTF8::str_replace($search, $replacement, $value);
3014 1
        }
3015 1
    );
3016 1
3017 1
    return $array;
3018 1
  }
3019 1
3020
  /**
3021
   * Get the last elements from index $from until the end of this array.
3022 1
   *
3023
   * @param int $from
3024
   *
3025 1
   * @return static <p>(Immutable)</p>
3026
   */
3027
  public function rest(int $from = 1)
3028
  {
3029
    $tmpArray = $this->array;
3030
3031
    return static::create(\array_splice($tmpArray, $from));
3032
  }
3033 93
3034
  /**
3035 93
   * Return the array in the reverse order.
3036
   *
3037
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3038
   */
3039
  public function reverse()
3040
  {
3041
    $this->array = \array_reverse($this->array);
3042
3043
    return $this;
3044
  }
3045
3046
  /**
3047 4
   * Sort an array in reverse order.
3048
   *
3049 4
   * @param int $sort_flags [optional] <p>
3050
   *                        You may modify the behavior of the sort using the optional
3051 4
   *                        parameter sort_flags, for details
3052
   *                        see sort.
3053
   *                        </p>
3054
   *
3055
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3056
   */
3057
  public function rsort(int $sort_flags = 0)
3058
  {
3059
    \rsort($this->array, $sort_flags);
3060
3061
    return $this;
3062
  }
3063
3064 19
  /**
3065
   * Search for the first index of the current array via $value.
3066 19
   *
3067
   * @param mixed $value
3068 19
   *
3069
   * @return int|float|string
3070
   */
3071
  public function searchIndex($value)
3072
  {
3073
    return \array_search($value, $this->array, true);
3074
  }
3075
3076
  /**
3077
   * Search for the value of the current array via $index.
3078
   *
3079
   * @param mixed $index
3080
   *
3081
   * @return static <p>(Immutable) Will return a empty Arrayy if the value wasn't found.</p>
3082
   */
3083 18
  public function searchValue($index)
3084
  {
3085 18
    // init
3086
    $return = [];
3087 18
3088
    if ($this->isEmpty()) {
3089
      return static::create();
3090
    }
3091
3092
    // php cast "bool"-index into "int"-index
3093
    if ((bool)$index === $index) {
3094
      $index = (int)$index;
3095
    }
3096
3097
    if (\array_key_exists($index, $this->array) === true) {
3098 1
      $return = [$this->array[$index]];
3099
    }
3100 1
3101
3102
    return static::create($return);
3103
  }
3104
3105
  /**
3106
   * Set a value for the current array (optional using dot-notation).
3107
   *
3108
   * @param mixed $key   <p>The key to set.</p>
3109
   * @param mixed $value <p>Its value.</p>
3110
   *
3111 1
   * @return static <p>(Immutable)</p>
3112
   */
3113 1
  public function set($key, $value)
3114
  {
3115
    $this->internalSet($key, $value);
3116
3117
    return static::create($this->array);
3118
  }
3119
3120
  /**
3121
   * Get a value from a array and set it if it was not.
3122
   *
3123
   * WARNING: this method only set the value, if the $key is not already set
3124
   *
3125
   * @param mixed $key      <p>The key</p>
3126
   * @param mixed $fallback <p>The default value to set if it isn't.</p>
3127
   *
3128
   * @return mixed <p>(Mutable)</p>
3129 1
   */
3130
  public function setAndGet($key, $fallback = null)
3131 1
  {
3132 1
    // If the key doesn't exist, set it.
3133
    if (!$this->has($key)) {
3134
      $this->array = $this->set($key, $fallback)->getArray();
3135 1
    }
3136 1
3137
    return $this->get($key);
3138 1
  }
3139 1
3140
  /**
3141 1
   * Shifts a specified value off the beginning of array.
3142
   *
3143 1
   * @return mixed <p>(Mutable) A shifted element from the current array.</p>
3144
   */
3145 1
  public function shift()
3146 1
  {
3147 1
    return \array_shift($this->array);
3148
  }
3149
3150
  /**
3151 1
   * Shuffle the current array.
3152
   *
3153 1
   * @param bool  $secure <p>using a CSPRNG | @link https://paragonie.com/b/JvICXzh_jhLyt4y3</p>
3154
   * @param array $array  [optional]
3155
   *
3156
   * @return static <p>(Immutable)</p>
3157
   */
3158
  public function shuffle(bool $secure = false, array $array = null)
3159
  {
3160
    if ($array === null) {
3161
      $array = $this->array;
3162
    }
3163
3164
    if ($secure !== true) {
3165 18
      \shuffle($array);
3166
    } else {
3167 18
      $size = \count($array);
3168
      $keys = \array_keys($array);
3169
      for ($i = $size - 1; $i > 0; --$i) {
3170 18
        $r = \random_int(0, $i);
3171 18
        if ($r !== $i) {
3172 6
          $temp = $array[$keys[$r]];
3173 6
          $array[$keys[$r]] = $array[$keys[$i]];
3174 13
          $array[$keys[$i]] = $temp;
3175 13
        }
3176 13
      }
3177 13
3178 13
      // Reset indices
3179
      $array = \array_values($array);
3180 18
    }
3181
3182
    foreach ($array as $key => $value) {
3183
      // recursive needed?
3184
      if (\is_array($value) === true) {
3185
        $array[$key] = $this->shuffle($secure, $value);
3186
      }
3187
    }
3188
3189
    return static::create($array);
3190
  }
3191
3192 19
  /**
3193
   * Counts all elements in an array, or something in an object.
3194 19
   * <p>For objects, if you have SPL installed, you can hook into count() by implementing interface {@see Countable}.
3195
   * The interface has exactly one method, {@see Countable::count()}, which returns the return value for the count()
3196 19
   * function. Please see the {@see Array} section of the manual for a detailed explanation of how arrays are
3197 19
   * implemented and used in PHP.
3198 19
   *
3199
   * @return int the number of elements in var, which is
3200
   * typically an array, since anything else will have one
3201 19
   * element.
3202 19
   * </p>
3203 9
   * <p>
3204 5
   * If var is not an array or an object with
3205 5
   * implemented Countable interface,
3206 4
   * 1 will be returned.
3207
   * There is one exception, if var is &null;,
3208 9
   * 0 will be returned.
3209 10
   * </p>
3210 10
   * <p>
3211 10
   * Caution: count may return 0 for a variable that isn't set,
3212 10
   * but it may also return 0 for a variable that has been initialized with an
3213 4
   * empty array. Use isset to test if a variable is set.
3214 4
   *
3215 6
   * @return int
3216
   */
3217 10
  public function sizeRecursive(): int
3218
  {
3219 19
    return \count($this->array, COUNT_RECURSIVE);
3220
  }
3221
3222
  /**
3223
   * Counts all elements in an array, or something in an object.
3224
   * <p>For objects, if you have SPL installed, you can hook into count() by implementing interface {@see Countable}.
3225
   * The interface has exactly one method, {@see Countable::count()}, which returns the return value for the count()
3226
   * function. Please see the {@see Array} section of the manual for a detailed explanation of how arrays are
3227
   * implemented and used in PHP.
3228
   *
3229
   * @link http://php.net/manual/en/function.count.php
3230 1
   *
3231
   * @param int $mode [optional] If the optional mode parameter is set to
3232 1
   *                  COUNT_RECURSIVE (or 1), count
3233
   *                  will recursively count the array. This is particularly useful for
3234 1
   *                  counting all the elements of a multidimensional array. count does not detect infinite recursion.
3235 1
   *
3236 1
   * @return int the number of elements in var, which is
3237 1
   * typically an array, since anything else will have one
3238 1
   * element.
3239 1
   * </p>
3240
   * <p>
3241
   * If var is not an array or an object with
3242 1
   * implemented Countable interface,
3243
   * 1 will be returned.
3244
   * There is one exception, if var is &null;,
3245
   * 0 will be returned.
3246
   * </p>
3247
   * <p>
3248
   * Caution: count may return 0 for a variable that isn't set,
3249
   * but it may also return 0 for a variable that has been initialized with an
3250 1
   * empty array. Use isset to test if a variable is set.
3251
   *
3252 1
   * @return int
3253
   */
3254 1
  public function size(int $mode = COUNT_NORMAL): int
3255 1
  {
3256
    return \count($this->array, $mode);
3257
  }
3258 1
3259
  /**
3260 1
   * Extract a slice of the array.
3261
   *
3262
   * @param int      $offset       <p>Slice begin index.</p>
3263
   * @param int|null $length       <p>Length of the slice.</p>
3264
   * @param bool     $preserveKeys <p>Whether array keys are preserved or no.</p>
3265
   *
3266
   * @return static <p>A slice of the original array with length $length.</p>
3267
   */
3268
  public function slice(int $offset, int $length = null, bool $preserveKeys = false)
3269
  {
3270
    $result = \array_slice($this->array, $offset, $length, $preserveKeys);
3271 1
3272
    return static::create($result);
3273 1
  }
3274
3275 1
  /**
3276
   * Sort the current array and optional you can keep the keys.
3277 1
   *
3278
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3279
   * @param int        $strategy  <p>sort_flags => use e.g.: <strong>SORT_REGULAR</strong> (default) or
3280
   *                              <strong>SORT_NATURAL</strong></p>
3281
   * @param bool       $keepKeys
3282
   *
3283
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3284
   */
3285 186
  public function sort($direction = SORT_ASC, int $strategy = SORT_REGULAR, bool $keepKeys = false)
3286
  {
3287 186
    $this->sorting($this->array, $direction, $strategy, $keepKeys);
3288
3289
    return $this;
3290
  }
3291
3292
  /**
3293
   * Sort the current array by key.
3294
   *
3295
   * @link http://php.net/manual/en/function.ksort.php
3296
   * @link http://php.net/manual/en/function.krsort.php
3297
   *
3298 6
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3299
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3300 6
   *                              <strong>SORT_NATURAL</strong></p>
3301
   *
3302
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3303
   */
3304
  public function sortKeys($direction = SORT_ASC, int $strategy = SORT_REGULAR)
3305
  {
3306
    $this->sorterKeys($this->array, $direction, $strategy);
3307
3308
    return $this;
3309
  }
3310 19
3311
  /**
3312 19
   * Sort the current array by value.
3313
   *
3314
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3315
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3316
   *                              <strong>SORT_NATURAL</strong></p>
3317
   *
3318
   * @return static <p>(Mutable)</p>
3319
   */
3320 9
  public function sortValueKeepIndex($direction = SORT_ASC, int $strategy = SORT_REGULAR)
3321
  {
3322
    return $this->sort($direction, $strategy, true);
3323
  }
3324 9
3325 9
  /**
3326
   * Sort the current array by value.
3327 8
   *
3328 8
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3329 8
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3330
   *                              <strong>SORT_NATURAL</strong></p>
3331 8
   *
3332 9
   * @return static <p>(Mutable)</p>
3333 9
   */
3334 9
  public function sortValueNewIndex($direction = SORT_ASC, int $strategy = SORT_REGULAR)
3335
  {
3336 9
    return $this->sort($direction, $strategy, false);
3337
  }
3338
3339 9
  /**
3340
   * Sort a array by value, by a closure or by a property.
3341
   *
3342 9
   * - If the sorter is null, the array is sorted naturally.
3343
   * - Associative (string) keys will be maintained, but numeric keys will be re-indexed.
3344
   *
3345
   * @param \callable|null $sorter
3346
   * @param string|int     $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3347
   * @param int            $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3348
   *                                  <strong>SORT_NATURAL</strong></p>
3349
   *
3350 9
   * @return static <p>(Immutable)</p>
3351
   */
3352
  public function sorter($sorter = null, $direction = SORT_ASC, int $strategy = SORT_REGULAR)
3353
  {
3354
    $array = (array)$this->array;
3355 9
    $direction = $this->getDirection($direction);
3356
3357 9
    // Transform all values into their results.
3358 9
    if ($sorter) {
3359 9
      $arrayy = static::create($array);
3360 8
3361 8
      $that = $this;
3362 8
      $results = $arrayy->each(
3363
          function ($value) use ($sorter, $that) {
3364 8
            return \is_callable($sorter) ? $sorter($value) : $that->get($sorter, null, $value);
3365 9
          }
3366 9
      );
3367 9
3368
      $results = $results->getArray();
3369 9
    } else {
3370
      $results = $array;
3371
    }
3372 9
3373
    // Sort by the results and replace by original values
3374
    \array_multisort($results, $direction, $strategy, $array);
3375 9
3376
    return static::create($array);
3377
  }
3378
3379
  /**
3380
   * sorting keys
3381
   *
3382
   * @param array      $elements
3383
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3384
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3385 9
   *                              <strong>SORT_NATURAL</strong></p>
3386
   *
3387 9
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3388
   */
3389
  protected function sorterKeys(array &$elements, $direction = SORT_ASC, int $strategy = SORT_REGULAR)
3390
  {
3391
    $direction = $this->getDirection($direction);
3392
3393
    switch ($direction) {
3394
      case 'desc':
3395 4
      case SORT_DESC:
3396
        \krsort($elements, $strategy);
3397 4
        break;
3398 4
      case 'asc':
3399 4
      case SORT_ASC:
3400 4
      default:
3401
        \ksort($elements, $strategy);
3402 4
    }
3403
3404
    return $this;
3405
  }
3406
3407
  /**
3408
   * @param array      &$elements
3409
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3410 2
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3411
   *                              <strong>SORT_NATURAL</strong></p>
3412 2
   * @param bool       $keepKeys
3413
   *
3414
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3415
   */
3416
  protected function sorting(array &$elements, $direction = SORT_ASC, int $strategy = SORT_REGULAR, bool $keepKeys = false)
3417
  {
3418
    $direction = $this->getDirection($direction);
3419
3420
    if (!$strategy) {
3421
      $strategy = SORT_REGULAR;
3422
    }
3423 9
3424
    switch ($direction) {
3425 9
      case 'desc':
3426 4
      case SORT_DESC:
3427 4
        if ($keepKeys) {
3428 5
          arsort($elements, $strategy);
3429
        } else {
3430
          \rsort($elements, $strategy);
3431 9
        }
3432
        break;
3433
      case 'asc':
3434
      case SORT_ASC:
3435
      default:
3436
        if ($keepKeys) {
3437
          \asort($elements, $strategy);
3438
        } else {
3439
          \sort($elements, $strategy);
3440
        }
3441
    }
3442
3443
    return $this;
3444
  }
3445
3446
  /**
3447
   * Split an array in the given amount of pieces.
3448
   *
3449
   * @param int  $numberOfPieces
3450
   * @param bool $keepKeys
3451
   *
3452
   * @return static <p>(Immutable)</p>
3453
   */
3454
  public function split(int $numberOfPieces = 2, bool $keepKeys = false)
3455
  {
3456
    $arrayCount = $this->count();
3457
3458
    if ($arrayCount === 0) {
3459
      $result = [];
3460
    } else {
3461
      $numberOfPieces = (int)$numberOfPieces;
3462
      $splitSize = (int)\ceil($arrayCount / $numberOfPieces);
3463
      $result = \array_chunk($this->array, $splitSize, $keepKeys);
3464
    }
3465
3466
    return static::create($result);
3467
  }
3468
3469
  /**
3470
   * Stripe all empty items.
3471
   *
3472
   * @return static <p>(Immutable)</p>
3473
   */
3474
  public function stripEmpty()
3475
  {
3476
    return $this->filter(
3477
        function ($item) {
3478
          if ($item === null) {
3479
            return false;
3480
          }
3481
3482
          return (bool)\trim((string)$item);
3483
        }
3484
    );
3485
  }
3486
3487
  /**
3488
   * Swap two values between positions by key.
3489
   *
3490
   * @param string|int $swapA <p>a key in the array</p>
3491
   * @param string|int $swapB <p>a key in the array</p>
3492
   *
3493
   * @return static <p>(Immutable)</p>
3494
   */
3495
  public function swap($swapA, $swapB)
3496
  {
3497
    $array = $this->array;
3498
3499
    list($array[$swapA], $array[$swapB]) = [$array[$swapB], $array[$swapA]];
3500
3501
    return static::create($array);
3502
  }
3503
3504
  /**
3505
   * alias: for "Arrayy->getArray()"
3506
   *
3507
   * @see Arrayy::getArray()
3508
   */
3509
  public function toArray()
3510
  {
3511
    return $this->getArray();
3512
  }
3513
3514
  /**
3515
   * Convert the current array to JSON.
3516
   *
3517
   * @param null|int $options [optional] <p>e.g. JSON_PRETTY_PRINT</p>
3518
   * @param int      $depth   [optional] <p>Set the maximum depth. Must be greater than zero.</p>
3519
   *
3520
   * @return string
3521
   */
3522
  public function toJson($options = null, int $depth = 512): string
3523
  {
3524
    return UTF8::json_encode($this->array, $options, $depth);
3525
  }
3526
3527
  /**
3528
   * Implodes array to a string with specified separator.
3529
   *
3530
   * @param string $separator [optional] <p>The element's separator.</p>
3531
   *
3532
   * @return string <p>The string representation of array, separated by ",".</p>
3533
   */
3534
  public function toString(string $separator = ','): string
3535
  {
3536
    return $this->implode($separator);
3537
  }
3538
3539
  /**
3540
   * Return a duplicate free copy of the current array.
3541
   *
3542
   * @return static <p>(Mutable)</p>
3543
   */
3544
  public function unique()
3545
  {
3546
    // INFO: \array_unique() can't handle e.g. "stdClass"-values in an array
3547
3548
    $this->array = \array_reduce(
0 ignored issues
show
Documentation Bug introduced by
It seems like \array_reduce($this->arr...esultArray; }, array()) of type * is incompatible with the declared type array of property $array.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
3549
        $this->array,
3550
        function ($resultArray, $value) {
3551
          if (!\in_array($value, $resultArray, true)) {
3552
            $resultArray[] = $value;
3553
          }
3554
3555
          return $resultArray;
3556
        },
3557
        []
3558
    );
3559
3560 View Code Duplication
    if ($this->array === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
3561
      $this->array = [];
3562
    } else {
3563
      $this->array = (array)$this->array;
3564
    }
3565
3566
    return $this;
3567
  }
3568
3569
  /**
3570
   * Return a duplicate free copy of the current array. (with the old keys)
3571
   *
3572
   * @return static <p>(Mutable)</p>
3573
   */
3574
  public function uniqueKeepIndex()
3575
  {
3576
    // INFO: \array_unique() can't handle e.g. "stdClass"-values in an array
3577
3578
    // init
3579
    $array = $this->array;
3580
3581
    $this->array = \array_reduce(
0 ignored issues
show
Documentation Bug introduced by
It seems like \array_reduce(\array_key...esultArray; }, array()) of type * is incompatible with the declared type array of property $array.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
3582
        \array_keys($array),
3583
        function ($resultArray, $key) use ($array) {
3584
          if (!\in_array($array[$key], $resultArray, true)) {
3585
            $resultArray[$key] = $array[$key];
3586
          }
3587
3588
          return $resultArray;
3589
        },
3590
        []
3591
    );
3592
3593 View Code Duplication
    if ($this->array === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
3594
      $this->array = [];
3595
    } else {
3596
      $this->array = (array)$this->array;
3597
    }
3598
3599
    return $this;
3600
  }
3601
3602
  /**
3603
   * alias: for "Arrayy->unique()"
3604
   *
3605
   * @see Arrayy::unique()
3606
   *
3607
   * @return static <p>(Mutable) Return this Arrayy object, with the appended values.</p>
3608
   */
3609
  public function uniqueNewIndex()
3610
  {
3611
    return $this->unique();
3612
  }
3613
3614
  /**
3615
   * Prepends one or more values to the beginning of array at once.
3616
   *
3617
   * @return static <p>(Mutable) Return this Arrayy object, with prepended elements to the beginning of array.</p>
3618
   */
3619 View Code Duplication
  public function unshift(/* variadic arguments allowed */)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
3620
  {
3621
    if (\func_num_args()) {
3622
      $args = \array_merge([&$this->array], \func_get_args());
3623
      \array_unshift(...$args);
3624
    }
3625
3626
    return $this;
3627
  }
3628
3629
  /**
3630
   * Get all values from a array.
3631
   *
3632
   * @return static <p>(Immutable)</p>
3633
   */
3634
  public function values()
3635
  {
3636
    return static::create(\array_values((array)$this->array));
3637
  }
3638
3639
  /**
3640
   * Apply the given function to every element in the array, discarding the results.
3641
   *
3642
   * @param \callable $callable
3643
   * @param bool      $recursive <p>Whether array will be walked recursively or no</p>
3644
   *
3645
   * @return static <p>(Mutable) Return this Arrayy object, with modified elements.</p>
3646
   */
3647
  public function walk($callable, bool $recursive = false)
3648
  {
3649
    if (true === $recursive) {
3650
      \array_walk_recursive($this->array, $callable);
3651
    } else {
3652
      \array_walk($this->array, $callable);
3653
    }
3654
3655
    return $this;
3656
  }
3657
}
3658