Completed
Push — master ( 3f9802...577040 )
by Lars
02:55
created

Arrayy::krsort()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 1
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 = ArrayyIterator::class;
28
29
  /**
30
   * @var string
31
   */
32
  protected $pathSeparator = '.';
33
34
  /** @noinspection MagicMethodsValidityInspection */
35
  /**
36
   * Initializes
37
   *
38
   * @param mixed  $array <p>Should be an array, otherwise it will try to convert it into an array.</p>
39
   * @param string $iteratorClass
40
   */
41 869
  public function __construct($array = [], $iteratorClass = ArrayyIterator::class)
42
  {
43 869
    $array = $this->fallbackForArray($array);
44 867
    $this->array = $array;
45
46 867
    $this->setIteratorClass($iteratorClass);
47 867
  }
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
   */
56 2
  public function &__get($key)
57
  {
58 2
    $return = $this->get($key);
59
60 2
    if (\is_array($return)) {
61
      return static::create($return);
62
    }
63
64 2
    return $return;
65
  }
66
67
  /**
68
   * Call object as function.
69
   *
70
   * @param mixed $key
71
   *
72
   * @return mixed
73
   */
74 1
  public function __invoke($key = null)
75
  {
76 1
    if ($key !== null) {
77 1
      if (isset($this->array[$key])) {
78 1
        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
   */
105 2
  public function __set($key, $value)
106
  {
107 2
    $this->internalSet($key, $value);
108 2
  }
109
110
  /**
111
   * magic to string
112
   *
113
   * @return string
114
   */
115 15
  public function __toString()
116
  {
117 15
    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
   */
139 1
  public function add($value)
140
  {
141 1
    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
   */
152 9
  public function append($value, $key = null)
153
  {
154 9
    if ($key !== null) {
155
      $this->array[$key] = $value;
156
    } else {
157 9
      $this->array[] = $value;
158
    }
159
160 9
    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
   */
174 4
  public function asort(int $sort_flags = 0)
175
  {
176 4
    \asort($this->array, $sort_flags);
177
178 4
    return $this;
179
  }
180
181
  /**
182
   * Counts all elements in an array, or something in an object.
183
   * <p>For objects, if you have SPL installed, you can hook into count() by implementing interface {@see Countable}.
184
   * The interface has exactly one method, {@see Countable::count()}, which returns the return value for the count()
185
   * function. Please see the {@see Array} section of the manual for a detailed explanation of how arrays are
186
   * implemented and used in PHP.
187
   *
188
   * @link http://php.net/manual/en/function.count.php
189
   *
190
   * @param int $mode [optional] If the optional mode parameter is set to
191
   *                  COUNT_RECURSIVE (or 1), count
192
   *                  will recursively count the array. This is particularly useful for
193
   *                  counting all the elements of a multidimensional array. count does not detect infinite recursion.
194
   *
195
   * @return int the number of elements in var, which is
196
   * typically an array, since anything else will have one
197
   * element.
198
   * </p>
199
   * <p>
200
   * If var is not an array or an object with
201
   * implemented Countable interface,
202
   * 1 will be returned.
203
   * There is one exception, if var is &null;,
204
   * 0 will be returned.
205
   * </p>
206
   * <p>
207
   * Caution: count may return 0 for a variable that isn't set,
208
   * but it may also return 0 for a variable that has been initialized with an
209
   * empty array. Use isset to test if a variable is set.
210
   *
211
   * @return int
212
   */
213 37
  public function count(int $mode = COUNT_NORMAL): int
214
  {
215 37
    return \count($this->array, $mode);
216
  }
217
218
  /**
219
   * Exchange the array for another one.
220
   *
221
   * @param array|static $data
222
   *
223
   * @return array
224
   */
225 1
  public function exchangeArray($data): array
226
  {
227 1
    $this->array = $this->fallbackForArray($data);
228
229 1
    return $this->array;
230
  }
231
232
  /**
233
   * Creates a copy of the ArrayyObject.
234
   *
235
   * @return array
236
   */
237 1
  public function getArrayCopy(): array
238
  {
239 1
    return $this->array;
240
  }
241
242
  /**
243
   * Returns a new ArrayyIterator, thus implementing the \ArrayIterator interface.
244
   *
245
   * @return \ArrayIterator <p>An iterator for the values in the array.</p>
246
   */
247 20
  public function getIterator(): \ArrayIterator
248
  {
249 20
    $iterator = $this->getIteratorClass();
250
251 20
    return new $iterator($this->array);
252
  }
253
254
  /**
255
   * Gets the iterator classname for the ArrayObject.
256
   *
257
   * @return string
258
   */
259 20
  public function getIteratorClass(): string
260
  {
261 20
    return $this->iteratorClass;
262
  }
263
264
  /**
265
   * Sort the entries by key
266
   *
267
   * @param int $sort_flags [optional] <p>
268
   *                        You may modify the behavior of the sort using the optional
269
   *                        parameter sort_flags, for details
270
   *                        see sort.
271
   *                        </p>
272
   *
273
   * @return static <p>(Mutable) Return this Arrayy object.</p>
274
   */
275 4
  public function ksort(int $sort_flags = 0)
276
  {
277 4
    \ksort($this->array, $sort_flags);
278
279 4
    return $this;
280
  }
281
282
  /**
283
   * Sort an array using a case insensitive "natural order" algorithm
284
   *
285
   * @return static <p>(Mutable) Return this Arrayy object.</p>
286
   */
287
  public function natcasesort()
288
  {
289
    \natcasesort($this->array);
290
291
    return $this;
292
  }
293
294
  /**
295
   * Sort entries using a "natural order" algorithm
296
   *
297
   * @return static <p>(Mutable) Return this Arrayy object.</p>
298
   */
299 1
  public function natsort()
300
  {
301 1
    \natsort($this->array);
302
303 1
    return $this;
304
  }
305
306
  /**
307
   * Whether or not an offset exists.
308
   *
309
   * @param int|float|string $offset
310
   *
311
   * @return bool
312
   */
313 40
  public function offsetExists($offset): bool
314
  {
315 40
    if ($this->isEmpty()) {
316 4
      return false;
317
    }
318
319
    // php cast "bool"-index into "int"-index
320 36
    if ((bool)$offset === $offset) {
321 1
      $offset = (int)$offset;
322
    }
323
324 36
    $tmpReturn = \array_key_exists($offset, $this->array);
325
326
    if (
327 36
        $tmpReturn === true
328
        ||
329
        (
330 12
            $tmpReturn === false
331
            &&
332 36
            \strpos((string)$offset, $this->pathSeparator) === false
333
        )
334
    ) {
335 34
      return $tmpReturn;
336
    }
337
338 3
    $offsetExists = false;
339
340 3
    if (\strpos((string)$offset, $this->pathSeparator) !== false) {
341
342 3
      $offsetExists = false;
343 3
      $explodedPath = \explode($this->pathSeparator, (string)$offset);
344 3
      $lastOffset = \array_pop($explodedPath);
345 3
      $containerPath = \implode($this->pathSeparator, $explodedPath);
346
347 3
      $this->callAtPath(
348 3
          $containerPath,
349 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...
350 3
            $offsetExists = \array_key_exists($lastOffset, $container);
351 3
          }
352
      );
353
    }
354
355 3
    return $offsetExists;
356
  }
357
358
  /**
359
   * Returns the value at specified offset.
360
   *
361
   * @param int|float|string $offset
362
   *
363
   * @return mixed <p>Will return null if the offset did not exists.</p>
364
   */
365 26
  public function offsetGet($offset)
366
  {
367 26
    return $this->offsetExists($offset) ? $this->get($offset) : null;
368
  }
369
370
  /**
371
   * Assigns a value to the specified offset.
372
   *
373
   * @param int|float|string $offset
374
   * @param mixed            $value
375
   */
376 17
  public function offsetSet($offset, $value)
377
  {
378 17
    if ($offset === null) {
379 4
      $this->array[] = $value;
380
    } else {
381 13
      $this->internalSet($offset, $value);
382
    }
383 17
  }
384
385
  /**
386
   * Unset an offset.
387
   *
388
   * @param int|float|string $offset
389
   */
390 7
  public function offsetUnset($offset)
391
  {
392 7
    if ($this->isEmpty()) {
393 1
      return;
394
    }
395
396 6
    if (\array_key_exists($offset, $this->array)) {
397 4
      unset($this->array[$offset]);
398
399 4
      return;
400
    }
401
402 3
    if (\strpos((string)$offset, $this->pathSeparator) !== false) {
403
404 2
      $path = \explode($this->pathSeparator, (string)$offset);
405 2
      $pathToUnset = \array_pop($path);
406
407 2
      $this->callAtPath(
408 2
          \implode($this->pathSeparator, $path),
409 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...
410 2
            unset($offset[$pathToUnset]);
411 2
          }
412
      );
413
414
    }
415 3
  }
416
417
  /**
418
   * Serialize the current "Arrayy"-object.
419
   *
420
   * @return string
421
   */
422 1
  public function serialize()
423
  {
424 1
    return parent::serialize();
425
  }
426
427
  /**
428
   * Sets the iterator classname for the current "Arrayy"-object.
429
   *
430
   * @param string $class
431
   *
432
   * @return void
433
   *
434
   * @throws \InvalidArgumentException
435
   */
436 867
  public function setIteratorClass($class)
437
  {
438 867
    if (\class_exists($class)) {
439 867
      $this->iteratorClass = $class;
440
441 867
      return;
442
    }
443
444
    if (\strpos($class, '\\') === 0) {
445
      $class = '\\' . $class;
446
      if (\class_exists($class)) {
447
        $this->iteratorClass = $class;
448
449
        return;
450
      }
451
    }
452
453
    throw new \InvalidArgumentException('The iterator class does not exist: ' . $class);
454
  }
455
456
  /**
457
   * Sort the entries with a user-defined comparison function and maintain key association.
458
   *
459
   * @param \callable $function
460
   *
461
   * @return static <p>(Mutable) Return this Arrayy object.</p>
462
   *
463
   * @throws \InvalidArgumentException
464
   */
465 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...
466
  {
467
    if (!\is_callable($function)) {
468
      throw new \InvalidArgumentException(
469
          'Passed function must be callable'
470
      );
471
    }
472
473
    \uasort($this->array, $function);
474
475
    return $this;
476
  }
477
478
  /**
479
   * Sort the entries by keys using a user-defined comparison function.
480
   *
481
   * @param \callable $function
482
   *
483
   * @return static <p>(Mutable) Return this Arrayy object.</p>
484
   *
485
   * @throws \InvalidArgumentException
486
   */
487 5
  public function uksort($function)
488
  {
489 5
    return $this->customSortKeys($function);
490
  }
491
492
  /**
493
   * Unserialize an string and return this object.
494
   *
495
   * @param string $string
496
   *
497
   * @return static <p>(Mutable)</p>
498
   */
499 1
  public function unserialize($string)
500
  {
501 1
    parent::unserialize($string);
502
503 1
    return $this;
504
  }
505
506
  /**
507
   * Add a suffix to each key.
508
   *
509
   * @param mixed $prefix
510
   *
511
   * @return static <p>(Immutable) Return an Arrayy object, with the prefixed keys.</p>
512
   */
513 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...
514
  {
515 10
    $result = [];
516 10
    foreach ($this->array as $key => $item) {
517 9
      if ($item instanceof self) {
518
        $result[$prefix . $key] = $item->appendToEachKey($prefix);
519 9
      } elseif (\is_array($item)) {
520
        $result[$prefix . $key] = self::create($item)->appendToEachKey($prefix)->toArray();
521
      } else {
522 9
        $result[$prefix . $key] = $item;
523
      }
524
    }
525
526 10
    return self::create($result);
527
  }
528
529
  /**
530
   * Add a prefix to each value.
531
   *
532
   * @param mixed $prefix
533
   *
534
   * @return static <p>(Immutable) Return an Arrayy object, with the prefixed values.</p>
535
   */
536 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...
537
  {
538 10
    $result = [];
539 10
    foreach ($this->array as $key => $item) {
540 9
      if ($item instanceof self) {
541
        $result[$key] = $item->appendToEachValue($prefix);
542 9
      } elseif (\is_array($item)) {
543
        $result[$key] = self::create($item)->appendToEachValue($prefix)->toArray();
544 9
      } elseif (\is_object($item)) {
545 1
        $result[$key] = $item;
546
      } else {
547 9
        $result[$key] = $prefix . $item;
548
      }
549
    }
550
551 10
    return self::create($result);
552
  }
553
554
  /**
555
   * Convert an array into a object.
556
   *
557
   * @param array $array PHP array
558
   *
559
   * @return \stdClass (object)
560
   */
561 4
  protected static function arrayToObject(array $array = []): \stdClass
562
  {
563 4
    $object = new \stdClass();
564
565 4
    if (!\is_array($array) || \count($array, COUNT_NORMAL) <= 0) {
566 1
      return $object;
567
    }
568
569 3
    foreach ($array as $name => $value) {
570 3
      if (\is_array($value)) {
571 1
        $object->{$name} = self::arrayToObject($value);
572 1
        continue;
573
      }
574 3
      $object->{$name} = $value;
575
    }
576
577 3
    return $object;
578
  }
579
580
  /**
581
   * @param array $input        <p>
582
   *                            An array containing keys to return.
583
   *                            </p>
584
   * @param mixed $search_value [optional] <p>
585
   *                            If specified, then only keys containing these values are returned.
586
   *                            </p>
587
   * @param bool  $strict       [optional] <p>
588
   *                            Determines if strict comparison (===) should be used during the search.
589
   *                            </p>
590
   *
591
   * @return array an array of all the keys in input.
592
   */
593 10
  protected function array_keys_recursive(array $input = null, $search_value = null, bool $strict = true): array
594
  {
595
    // init
596 10
    $keys = [];
597
598 10
    if ($input === null) {
599
      $input = $this->array;
600
    }
601
602 10
    foreach ($input as $key => $value) {
603
604
      if (
605 10
          $search_value === null
606
          ||
607
          (
608
              \is_array($search_value) === true
609
              &&
610 10
              \in_array($key, $search_value, $strict)
611
          )
612
      ) {
613 10
        $keys[] = $key;
614
      }
615
616
      // check if recursive is needed
617 10
      if (\is_array($value) === true) {
618 10
        $keys = \array_merge($keys, $this->array_keys_recursive($value));
619
      }
620
    }
621
622 10
    return $keys;
623
  }
624
625
  /**
626
   * Sort an array in reverse order and maintain index association.
627
   *
628
   * @return static <p>(Mutable) Return this Arrayy object.</p>
629
   */
630 4
  public function arsort()
631
  {
632 4
    \arsort($this->array);
633
634 4
    return $this;
635
  }
636
637
  /**
638
   * Iterate over the current array and execute a callback for each loop.
639
   *
640
   * @param \Closure $closure
641
   *
642
   * @return static <p>(Immutable)</p>
643
   */
644 2 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...
645
  {
646 2
    $array = $this->array;
647
648 2
    foreach ($array as $key => $value) {
649 2
      $closure($value, $key);
650
    }
651
652 2
    return static::create($array);
653
  }
654
655
  /**
656
   * Returns the average value of the current array.
657
   *
658
   * @param int $decimals <p>The number of decimal-numbers to return.</p>
659
   *
660
   * @return int|double <p>The average value.</p>
661
   */
662 10
  public function average($decimals = 0)
663
  {
664 10
    $count = \count($this->array, COUNT_NORMAL);
665
666 10
    if (!$count) {
667 2
      return 0;
668
    }
669
670 8
    if (!\is_int($decimals)) {
671 3
      $decimals = 0;
672
    }
673
674 8
    return \round(\array_sum($this->array) / $count, $decimals);
675
  }
676
677
  /**
678
   * @param mixed      $path
679
   * @param \callable  $callable
680
   * @param null|array $currentOffset
681
   */
682 4
  protected function callAtPath($path, $callable, &$currentOffset = null)
683
  {
684 4
    if ($currentOffset === null) {
685 4
      $currentOffset = &$this->array;
686
    }
687
688 4
    $explodedPath = \explode($this->pathSeparator, $path);
689 4
    $nextPath = \array_shift($explodedPath);
690
691 4
    if (!isset($currentOffset[$nextPath])) {
692
      return;
693
    }
694
695 4
    if (!empty($explodedPath)) {
696 1
      $this->callAtPath(
697 1
          \implode($this->pathSeparator, $explodedPath),
698 1
          $callable,
699 1
          $currentOffset[$nextPath]
700
      );
701
    } else {
702 4
      $callable($currentOffset[$nextPath]);
703
    }
704 4
  }
705
706
  /**
707
   * Changes all keys in an array.
708
   *
709
   * @param int $case [optional] <p> Either <strong>CASE_UPPER</strong><br />
710
   *                  or <strong>CASE_LOWER</strong> (default)</p>
711
   *
712
   * @return static <p>(Immutable)</p>
713
   */
714 1
  public function changeKeyCase(int $case = CASE_LOWER)
715
  {
716 1
    return static::create(UTF8::array_change_key_case($this->array, $case));
717
  }
718
719
  /**
720
   * Change the path separator of the array wrapper.
721
   *
722
   * By default, the separator is: "."
723
   *
724
   * @param string $separator <p>Separator to set.</p>
725
   *
726
   * @return static <p>Mutable</p>
727
   */
728 1
  public function changeSeparator($separator)
729
  {
730 1
    $this->pathSeparator = $separator;
731
732 1
    return $this;
733
  }
734
735
  /**
736
   * Create a chunked version of the current array.
737
   *
738
   * @param int  $size         <p>Size of each chunk.</p>
739
   * @param bool $preserveKeys <p>Whether array keys are preserved or no.</p>
740
   *
741
   * @return static <p>(Immutable) A new array of chunks from the original array.</p>
742
   */
743 4
  public function chunk($size, $preserveKeys = false)
744
  {
745 4
    $result = \array_chunk($this->array, $size, $preserveKeys);
746
747 4
    return static::create($result);
748
  }
749
750
  /**
751
   * Clean all falsy values from the current array.
752
   *
753
   * @return static <p>(Immutable)</p>
754
   */
755 8
  public function clean()
756
  {
757 8
    return $this->filter(
758 8
        function ($value) {
759 7
          return (bool)$value;
760 8
        }
761
    );
762
  }
763
764
  /**
765
   * WARNING!!! -> Clear the current array.
766
   *
767
   * @return static <p>(Mutable) Return this Arrayy object, with an empty array.</p>
768
   */
769 4
  public function clear()
770
  {
771 4
    $this->array = [];
772
773 4
    return $this;
774
  }
775
776
  /**
777
   * Check if an item is in the current array.
778
   *
779
   * @param string|int|float $value
780
   * @param bool             $recursive
781
   * @param bool             $strict
782
   *
783
   * @return bool
784
   */
785 22
  public function contains($value, $recursive = false, $strict = true): bool
786
  {
787 22
    if ($recursive === true) {
788 18
      return $this->in_array_recursive($value, $this->array, $strict);
789
    }
790
791 13
    return \in_array($value, $this->array, $strict);
792
  }
793
794
  /**
795
   * Check if an (case-insensitive) string is in the current array.
796
   *
797
   * @param string $value
798
   * @param bool   $recursive
799
   *
800
   * @return bool
801
   */
802 26
  public function containsCaseInsensitive($value, $recursive = false): bool
803
  {
804 26
    if ($recursive === true) {
805 26
      return $this->in_array_recursive(
806 26
          UTF8::strtoupper($value),
807 26
          $this->walk(
808 26
              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...
809 22
                $val = UTF8::strtoupper($val);
810 26
              },
811 26
              true
812 26
          )->getArray(),
813 26
          true
814
      );
815
    }
816
817 13
    return \in_array(
818 13
        UTF8::strtoupper($value),
819 13
        $this->walk(
820 13
            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...
821 11
              $val = UTF8::strtoupper($val);
822 13
            },
823 13
            false
824 13
        )->getArray(),
825 13
        true
826
    );
827
  }
828
829
  /**
830
   * Check if the given key/index exists in the array.
831
   *
832
   * @param string|int|float $key <p>key/index to search for</p>
833
   *
834
   * @return bool <p>Returns true if the given key/index exists in the array, false otherwise.</p>
835
   */
836 4
  public function containsKey($key): bool
837
  {
838 4
    return $this->offsetExists($key);
839
  }
840
841
  /**
842
   * Check if all given needles are present in the array as key/index.
843
   *
844
   * @param array $needles <p>The keys you are searching for.</p>
845
   * @param bool  $recursive
846
   *
847
   * @return bool <p>Returns true if all the given keys/indexes exists in the array, false otherwise.</p>
848
   */
849 2
  public function containsKeys(array $needles, $recursive = false): bool
850
  {
851 2
    if ($recursive === true) {
852 2
      return \count(
853 2
                 \array_intersect($needles, $this->keys(true)->getArray()),
854 2
                 COUNT_RECURSIVE
855
             )
856
             ===
857 2
             \count(
858 2
                 $needles,
859 2
                 COUNT_RECURSIVE
860
             );
861
    }
862
863 1
    return \count(
864 1
               \array_intersect($needles, $this->keys()->getArray()),
865 1
               COUNT_NORMAL
866
           )
867
           ===
868 1
           \count(
869 1
               $needles,
870 1
               COUNT_NORMAL
871
           );
872
  }
873
874
  /**
875
   * Check if all given needles are present in the array as key/index.
876
   *
877
   * @param array $needles <p>The keys you are searching for.</p>
878
   *
879
   * @return bool <p>Returns true if all the given keys/indexes exists in the array, false otherwise.</p>
880
   */
881 1
  public function containsKeysRecursive(array $needles): bool
882
  {
883 1
    return $this->containsKeys($needles, true);
884
  }
885
886
  /**
887
   * alias: for "Arrayy->contains()"
888
   *
889
   * @see Arrayy::contains()
890
   *
891
   * @param string|int|float $value
892
   *
893
   * @return bool
894
   */
895 9
  public function containsValue($value): bool
896
  {
897 9
    return $this->contains($value);
898
  }
899
900
  /**
901
   * alias: for "Arrayy->contains($value, true)"
902
   *
903
   * @see Arrayy::contains()
904
   *
905
   * @param string|int|float $value
906
   *
907
   * @return bool
908
   */
909 18
  public function containsValueRecursive($value): bool
910
  {
911 18
    return $this->contains($value, true);
912
  }
913
914
  /**
915
   * Check if all given needles are present in the array.
916
   *
917
   * @param array $needles
918
   *
919
   * @return bool <p>Returns true if all the given values exists in the array, false otherwise.</p>
920
   */
921 1
  public function containsValues(array $needles): bool
922
  {
923 1
    return \count(\array_intersect($needles, $this->array), COUNT_NORMAL)
924
           ===
925 1
           \count($needles, COUNT_NORMAL);
926
  }
927
928
  /**
929
   * Counts all the values of an array
930
   *
931
   * @link http://php.net/manual/en/function.array-count-values.php
932
   *
933
   * @return static <p>
934
   *                (Immutable)
935
   *                An associative Arrayy-object of values from input as
936
   *                keys and their count as value.
937
   *                </p>
938
   */
939 1
  public function countValues(): self
940
  {
941 1
    return new static(\array_count_values($this->array));
942
  }
943
944
  /**
945
   * Creates an Arrayy object.
946
   *
947
   * @param array $array
948
   *
949
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
950
   */
951 537
  public static function create($array = []): self
952
  {
953 537
    return new static($array);
954
  }
955
956
  /**
957
   * WARNING: Creates an Arrayy object by reference.
958
   *
959
   * @param array $array
960
   *
961
   * @return static <p>(Mutable) Return this Arrayy object.</p>
962
   */
963 1
  public function createByReference(array &$array = []): self
964
  {
965 1
    $array = $this->fallbackForArray($array);
966
967 1
    $this->array = &$array;
968
969 1
    return $this;
970
  }
971
972
  /**
973
   * Create an new Arrayy object via JSON.
974
   *
975
   * @param string $json
976
   *
977
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
978
   */
979 5
  public static function createFromJson(string $json)
980
  {
981 5
    $array = UTF8::json_decode($json, true);
982
983 5
    return static::create($array);
984
  }
985
986
  /**
987
   * Create an new instance filled with values from an object that have implemented ArrayAccess.
988
   *
989
   * @param \ArrayAccess $object <p>Object that implements ArrayAccess</p>
990
   *
991
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
992
   */
993 4
  public static function createFromObject(\ArrayAccess $object)
994
  {
995 4
    $array = new static();
996 4
    foreach ($object as $key => $value) {
997
      /** @noinspection OffsetOperationsInspection */
998 3
      $array[$key] = $value;
999
    }
1000
1001 4
    return $array;
1002
  }
1003
1004
  /**
1005
   * Create an new instance filled with values from an object.
1006
   *
1007
   * @param object $object
1008
   *
1009
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
1010
   */
1011 5
  public static function createFromObjectVars($object): self
1012
  {
1013 5
    return new static(self::objectToArray($object));
1014
  }
1015
1016
  /**
1017
   * Create an new Arrayy object via string.
1018
   *
1019
   * @param string      $str       <p>The input string.</p>
1020
   * @param string|null $delimiter <p>The boundary string.</p>
1021
   * @param string|null $regEx     <p>Use the $delimiter or the $regEx, so if $pattern is null, $delimiter will be
1022
   *                               used.</p>
1023
   *
1024
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
1025
   */
1026 8
  public static function createFromString(string $str, string $delimiter = null, string $regEx = null)
1027
  {
1028 8
    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...
1029 1
      \preg_match_all($regEx, $str, $array);
1030
1031 1
      if (!empty($array)) {
1032 1
        $array = $array[0];
1033
      }
1034
1035
    } else {
1036 7
      $array = \explode($delimiter, $str);
1037
    }
1038
1039
    // trim all string in the array
1040 8
    \array_walk(
1041
        $array,
1042 8
        function (&$val) {
1043
          /** @noinspection ReferenceMismatchInspection */
1044 8
          if (\is_string($val)) {
1045 8
            $val = \trim($val);
1046
          }
1047 8
        }
1048
    );
1049
1050 8
    return static::create($array);
1051
  }
1052
1053
  /**
1054
   * Create an new instance containing a range of elements.
1055
   *
1056
   * @param mixed $low  <p>First value of the sequence.</p>
1057
   * @param mixed $high <p>The sequence is ended upon reaching the end value.</p>
1058
   * @param int   $step <p>Used as the increment between elements in the sequence.</p>
1059
   *
1060
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
1061
   */
1062 1
  public static function createWithRange($low, $high, int $step = 1)
1063
  {
1064 1
    return static::create(\range($low, $high, $step));
1065
  }
1066
1067
  /**
1068
   * Custom sort by index via "uksort".
1069
   *
1070
   * @link http://php.net/manual/en/function.uksort.php
1071
   *
1072
   * @param \callable $function
1073
   *
1074
   * @return static <p>(Mutable) Return this Arrayy object.</p>
1075
   *
1076
   * @throws \InvalidArgumentException
1077
   */
1078 5 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...
1079
  {
1080 5
    if (!\is_callable($function)) {
1081
      throw new \InvalidArgumentException(
1082
          'Passed function must be callable'
1083
      );
1084
    }
1085
1086 5
    \uksort($this->array, $function);
1087
1088 5
    return $this;
1089
  }
1090
1091
  /**
1092
   * Custom sort by value via "usort".
1093
   *
1094
   * @link http://php.net/manual/en/function.usort.php
1095
   *
1096
   * @param \callable $function
1097
   *
1098
   * @return static <p>(Mutable) Return this Arrayy object.</p>
1099
   *
1100
   * @throws \InvalidArgumentException
1101
   */
1102 5 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...
1103
  {
1104 5
    if (!\is_callable($function)) {
1105
      throw new \InvalidArgumentException(
1106
          'Passed function must be callable'
1107
      );
1108
    }
1109
1110 5
    \usort($this->array, $function);
1111
1112 5
    return $this;
1113
  }
1114
1115
  /**
1116
   * Return values that are only in the current array.
1117
   *
1118
   * @param array $array
1119
   *
1120
   * @return static <p>(Immutable)</p>
1121
   */
1122 12
  public function diff(array $array = [])
1123
  {
1124 12
    $result = \array_diff($this->array, $array);
1125
1126 12
    return static::create($result);
1127
  }
1128
1129
  /**
1130
   * Return values that are only in the current multi-dimensional array.
1131
   *
1132
   * @param array      $array
1133
   * @param null|array $helperVariableForRecursion <p>(only for internal usage)</p>
1134
   *
1135
   * @return static <p>(Immutable)</p>
1136
   */
1137 1
  public function diffRecursive(array $array = [], $helperVariableForRecursion = null)
1138
  {
1139 1
    $result = [];
1140
1141
    if (
1142 1
        $helperVariableForRecursion !== null
1143
        &&
1144 1
        \is_array($helperVariableForRecursion)
1145
    ) {
1146 1
      $arrayForTheLoop = $helperVariableForRecursion;
1147
    } else {
1148 1
      $arrayForTheLoop = $this->array;
1149
    }
1150
1151 1
    foreach ($arrayForTheLoop as $key => $value) {
1152 1
      if (\array_key_exists($key, $array)) {
1153 1
        if (\is_array($value)) {
1154 1
          $recursiveDiff = $this->diffRecursive($array[$key], $value);
1155 1
          if (!empty($recursiveDiff)) {
1156 1
            $result[$key] = $recursiveDiff;
1157
          }
1158 1
        } else if ($value != $array[$key]) {
1159 1
          $result[$key] = $value;
1160
        }
1161
      } else {
1162 1
        $result[$key] = $value;
1163
      }
1164
    }
1165
1166 1
    return static::create($result);
1167
  }
1168
1169
  /**
1170
   * Return values that are only in the new $array.
1171
   *
1172
   * @param array $array
1173
   *
1174
   * @return static <p>(Immutable)</p>
1175
   */
1176 8
  public function diffReverse(array $array = [])
1177
  {
1178 8
    $result = \array_diff($array, $this->array);
1179
1180 8
    return static::create($result);
1181
  }
1182
1183
  /**
1184
   * Divide an array into two arrays. One with keys and the other with values.
1185
   *
1186
   * @return static <p>(Immutable)</p>
1187
   */
1188 1
  public function divide()
1189
  {
1190 1
    return static::create(
1191
        [
1192 1
            $this->keys(),
1193 1
            $this->values(),
1194
        ]
1195
    );
1196
  }
1197
1198
  /**
1199
   * Iterate over the current array and modify the array's value.
1200
   *
1201
   * @param \Closure $closure
1202
   *
1203
   * @return static <p>(Immutable)</p>
1204
   */
1205 4 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...
1206
  {
1207 4
    $array = $this->array;
1208
1209 4
    foreach ($array as $key => $value) {
1210 4
      $array[$key] = $closure($value, $key);
1211
    }
1212
1213 4
    return static::create($array);
1214
  }
1215
1216
  /**
1217
   * Check if a value is in the current array using a closure.
1218
   *
1219
   * @param \Closure $closure
1220
   *
1221
   * @return bool <p>Returns true if the given value is found, false otherwise.</p>
1222
   */
1223 4
  public function exists(\Closure $closure): bool
1224
  {
1225 4
    $isExists = false;
1226 4
    foreach ($this->array as $key => $value) {
1227 3
      if ($closure($value, $key)) {
1228 1
        $isExists = true;
1229 3
        break;
1230
      }
1231
    }
1232
1233 4
    return $isExists;
1234
  }
1235
1236
  /**
1237
   * create a fallback for array
1238
   *
1239
   * 1. use the current array, if it's a array
1240
   * 2. call "getArray()" on object, if there is a "Arrayy"-object
1241
   * 3. fallback to empty array, if there is nothing
1242
   * 4. call "createFromObject()" on object, if there is a "\ArrayAccess"-object
1243
   * 5. call "__toArray()" on object, if the method exists
1244
   * 6. cast a string or object with "__toString()" into an array
1245
   * 7. throw a "InvalidArgumentException"-Exception
1246
   *
1247
   * @param $array
1248
   *
1249
   * @return array
1250
   *
1251
   * @throws \InvalidArgumentException
1252
   */
1253 869
  protected function fallbackForArray(&$array): array
1254
  {
1255 869
    if (\is_array($array)) {
1256 866
      return $array;
1257
    }
1258
1259 11
    if ($array instanceof self) {
1260 1
      return $array->getArray();
1261
    }
1262
1263 10
    if (!$array) {
1264 6
      return [];
1265
    }
1266
1267 9
    $isObject = \is_object($array);
1268
1269 9
    if ($isObject && $array instanceof \ArrayAccess) {
1270
      /** @noinspection ReferenceMismatchInspection */
1271
      return static::createFromObject($array)->getArray();
1272
    }
1273
1274 9
    if ($isObject && $array instanceof \ArrayObject) {
1275
      return $array->getArrayCopy();
1276
    }
1277
1278 9
    if ($isObject && \method_exists($array, '__toArray')) {
1279
      return (array)$array->__toArray();
1280
    }
1281
1282
    /** @noinspection ReferenceMismatchInspection */
1283
    if (
1284 9
        \is_string($array)
1285
        ||
1286 9
        ($isObject && \method_exists($array, '__toString'))
1287
    ) {
1288 7
      return [(string)$array];
1289
    }
1290
1291 2
    throw new \InvalidArgumentException(
1292 2
        'Passed value should be a array'
1293
    );
1294
  }
1295
1296
  /**
1297
   * Fill the array until "$num" with "$default" values.
1298
   *
1299
   * @param int   $num
1300
   * @param mixed $default
1301
   *
1302
   * @return static <p>(Immutable)</p>
1303
   */
1304 8
  public function fillWithDefaults(int $num, $default = null)
1305
  {
1306 8
    if ($num < 0) {
1307 1
      throw new \InvalidArgumentException('The $num parameter can only contain non-negative values.');
1308
    }
1309
1310 7
    $tmpArray = $this->array;
1311
1312 7
    $count = \count($tmpArray);
1313
1314 7
    while ($count < $num) {
1315 4
      $tmpArray[] = $default;
1316 4
      $count++;
1317
    }
1318
1319 7
    return static::create($tmpArray);
1320
  }
1321
1322
  /**
1323
   * Find all items in an array that pass the truth test.
1324
   *
1325
   * @param \Closure|null $closure [optional] <p>
1326
   *                               The callback function to use
1327
   *                               </p>
1328
   *                               <p>
1329
   *                               If no callback is supplied, all entries of
1330
   *                               input equal to false (see
1331
   *                               converting to
1332
   *                               boolean) will be removed.
1333
   *                               </p>
1334
   *
1335
   *  * @param int $flag [optional] <p>
1336
   *                               Flag determining what arguments are sent to <i>callback</i>:
1337
   *                               </p><ul>
1338
   *                               <li>
1339
   *                               <b>ARRAY_FILTER_USE_KEY</b> [1] - pass key as the only argument
1340
   *                               to <i>callback</i> instead of the value</span>
1341
   *                               </li>
1342
   *                               <li>
1343
   *                               <b>ARRAY_FILTER_USE_BOTH</b> [2] - pass both value and key as
1344
   *                               arguments to <i>callback</i> instead of the value</span>
1345
   *                               </li>
1346
   *                               </ul>
1347
   *
1348
   * @return static <p>(Immutable)</p>
1349
   */
1350 9
  public function filter($closure = null, int $flag = 0)
1351
  {
1352 9
    if (!$closure) {
1353 1
      return $this->clean();
1354
    }
1355
1356 9
    $array = \array_filter($this->array, $closure, $flag);
1357
1358 9
    return static::create($array);
1359
  }
1360
1361
  /**
1362
   * Filters an array of objects (or a numeric array of associative arrays) based on the value of a particular property
1363
   * within that.
1364
   *
1365
   * @param string          $property
1366
   * @param string|string[] $value
1367
   * @param string          $comparisonOp
1368
   *                            <p>
1369
   *                            'eq' (equals),<br />
1370
   *                            'gt' (greater),<br />
1371
   *                            'gte' || 'ge' (greater or equals),<br />
1372
   *                            'lt' (less),<br />
1373
   *                            'lte' || 'le' (less or equals),<br />
1374
   *                            'ne' (not equals),<br />
1375
   *                            'contains',<br />
1376
   *                            'notContains',<br />
1377
   *                            'newer' (via strtotime),<br />
1378
   *                            'older' (via strtotime),<br />
1379
   *                            </p>
1380
   *
1381
   * @return static <p>(Immutable)</p>
1382
   */
1383 1
  public function filterBy(string $property, $value, string $comparisonOp = null)
1384
  {
1385 1
    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...
1386 1
      $comparisonOp = \is_array($value) ? 'contains' : 'eq';
1387
    }
1388
1389
    $ops = [
1390 1
        'eq'          => function ($item, $prop, $value) {
1391 1
          return $item[$prop] === $value;
1392 1
        },
1393 1
        'gt'          => function ($item, $prop, $value) {
1394
          return $item[$prop] > $value;
1395 1
        },
1396 1
        'ge'          => function ($item, $prop, $value) {
1397
          return $item[$prop] >= $value;
1398 1
        },
1399 1
        'gte'         => function ($item, $prop, $value) {
1400
          return $item[$prop] >= $value;
1401 1
        },
1402 1
        'lt'          => function ($item, $prop, $value) {
1403 1
          return $item[$prop] < $value;
1404 1
        },
1405 1
        'le'          => function ($item, $prop, $value) {
1406
          return $item[$prop] <= $value;
1407 1
        },
1408 1
        'lte'         => function ($item, $prop, $value) {
1409
          return $item[$prop] <= $value;
1410 1
        },
1411 1
        'ne'          => function ($item, $prop, $value) {
1412
          return $item[$prop] !== $value;
1413 1
        },
1414 1
        'contains'    => function ($item, $prop, $value) {
1415 1
          return \in_array($item[$prop], (array)$value, true);
1416 1
        },
1417 1
        'notContains' => function ($item, $prop, $value) {
1418
          return !\in_array($item[$prop], (array)$value, true);
1419 1
        },
1420 1
        'newer'       => function ($item, $prop, $value) {
1421
          return \strtotime($item[$prop]) > \strtotime($value);
1422 1
        },
1423 1
        'older'       => function ($item, $prop, $value) {
1424
          return \strtotime($item[$prop]) < \strtotime($value);
1425 1
        },
1426
    ];
1427
1428 1
    $result = \array_values(
1429 1
        \array_filter(
1430 1
            (array)$this->array,
1431 1
            function ($item) use (
1432 1
                $property,
1433 1
                $value,
1434 1
                $ops,
1435 1
                $comparisonOp
1436
            ) {
1437 1
              $item = (array)$item;
1438 1
              $itemArrayy = new Arrayy($item);
1439 1
              $item[$property] = $itemArrayy->get($property, []);
1440
1441 1
              return $ops[$comparisonOp]($item, $property, $value);
1442 1
            }
1443
        )
1444
    );
1445
1446 1
    return static::create($result);
1447
  }
1448
1449
  /**
1450
   * Find the first item in an array that passes the truth test,
1451
   *  otherwise return false
1452
   *
1453
   * @param \Closure $closure
1454
   *
1455
   * @return mixed|false <p>Return false if we did not find the value.</p>
1456
   */
1457 8 View Code Duplication
  public function find(\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...
1458
  {
1459 8
    foreach ($this->array as $key => $value) {
1460 6
      if ($closure($value, $key)) {
1461 6
        return $value;
1462
      }
1463
    }
1464
1465 3
    return false;
1466
  }
1467
1468
  /**
1469
   * find by ...
1470
   *
1471
   * @param string          $property
1472
   * @param string|string[] $value
1473
   * @param string          $comparisonOp
1474
   *
1475
   * @return static <p>(Immutable)</p>
1476
   */
1477
  public function findBy(string $property, $value, string $comparisonOp = 'eq')
1478
  {
1479
    return $this->filterBy($property, $value, $comparisonOp);
1480
  }
1481
1482
  /**
1483
   * Get the first value from the current array.
1484
   *
1485
   * @return mixed <p>Return null if there wasn't a element.</p>
1486
   */
1487 13
  public function first()
1488
  {
1489 13
    $tmpArray = $this->array;
1490 13
    $result = \array_shift($tmpArray);
1491
1492 13
    if ($result === null) {
1493 3
      return null;
1494
    }
1495
1496 10
    return $result;
1497
  }
1498
1499
  /**
1500
   * Get the first value(s) from the current array.
1501
   *
1502
   * @param int|null $number <p>How many values you will take?</p>
1503
   *
1504
   * @return static <p>(Immutable)</p>
1505
   */
1506 28
  public function firstsImmutable(int $number = null)
1507
  {
1508 28
    if ($number === null) {
1509 7
      $arrayTmp = $this->array;
1510 7
      $array = (array)\array_shift($arrayTmp);
1511
    } else {
1512 21
      $number = (int)$number;
1513 21
      $arrayTmp = $this->array;
1514 21
      $array = \array_splice($arrayTmp, 0, $number, true);
1515
    }
1516
1517 28
    return static::create($array);
1518
  }
1519
1520
  /**
1521
   * Get the first value(s) from the current array.
1522
   *
1523
   * @param int|null $number <p>How many values you will take?</p>
1524
   *
1525
   * @return static <p>(Mutable)</p>
1526
   */
1527 26
  public function firstsMutable(int $number = null)
1528
  {
1529 26
    if ($number === null) {
1530 11
      $this->array = (array)\array_shift($this->array);
1531
    } else {
1532 15
      $number = (int)$number;
1533 15
      $this->array = \array_splice($this->array, 0, $number, true);
1534
    }
1535
1536 26
    return $this;
1537
  }
1538
1539
  /**
1540
   * Exchanges all keys with their associated values in an array.
1541
   *
1542
   * @return static <p>(Immutable)</p>
1543
   */
1544 1
  public function flip()
1545
  {
1546 1
    $result = \array_flip($this->array);
1547
1548 1
    return static::create($result);
1549
  }
1550
1551
  /**
1552
   * Get a value from an array (optional using dot-notation).
1553
   *
1554
   * @param mixed $key       <p>The key to look for.</p>
1555
   * @param mixed $fallback  <p>Value to fallback to.</p>
1556
   * @param array $array     <p>The array to get from, if it's set to "null" we use the current array from the
1557
   *                         class.</p>
1558
   *
1559
   * @return mixed
1560
   */
1561 61
  public function get($key, $fallback = null, array $array = null)
1562
  {
1563 61
    if ($array !== null) {
1564 3
      $usedArray = $array;
1565
    } else {
1566 58
      $usedArray = $this->array;
1567
    }
1568
1569 61
    if ($key === null) {
1570 1
      return static::create($usedArray);
1571
    }
1572
1573
    // php cast "bool"-index into "int"-index
1574 61
    if ((bool)$key === $key) {
1575 2
      $key = (int)$key;
1576
    }
1577
1578 61
    if (\array_key_exists($key, $usedArray) === true) {
1579 51
      if (\is_array($usedArray[$key])) {
1580 6
        return static::create($usedArray[$key]);
1581
      }
1582
1583 47
      return $usedArray[$key];
1584
    }
1585
1586
    // Crawl through array, get key according to object or not
1587 20
    foreach (\explode($this->pathSeparator, (string)$key) as $segment) {
1588 20
      if (!isset($usedArray[$segment])) {
1589 19
        return $fallback instanceof \Closure ? $fallback() : $fallback;
1590
      }
1591
1592 5
      $usedArray = $usedArray[$segment];
1593
    }
1594
1595 5
    if (\is_array($usedArray)) {
1596
      return static::create($usedArray);
1597
    }
1598
1599 5
    return $usedArray;
1600
  }
1601
1602
  /**
1603
   * Get the current array from the "Arrayy"-object.
1604
   *
1605
   * @return array
1606
   */
1607 578
  public function getArray(): array
1608
  {
1609 578
    \array_map(['self', 'internalGetArray'], $this->array);
1610
1611 578
    return $this->array;
1612
  }
1613
1614
  /**
1615
   * Returns the values from a single column of the input array, identified by
1616
   * the $columnKey, can be used to extract data-columns from multi-arrays.
1617
   *
1618
   * Info: Optionally, you may provide an $indexKey to index the values in the returned
1619
   * array by the values from the $indexKey column in the input array.
1620
   *
1621
   * @param mixed $columnKey
1622
   * @param mixed $indexKey
1623
   *
1624
   * @return static <p>(Immutable)</p>
1625
   */
1626 1
  public function getColumn($columnKey = null, $indexKey = null)
1627
  {
1628 1
    $result = \array_column($this->array, $columnKey, $indexKey);
1629
1630 1
    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 1628 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...
1631
  }
1632
1633
  /**
1634
   * Get correct PHP constant for direction.
1635
   *
1636
   * @param int|string $direction
1637
   *
1638
   * @return int
1639
   */
1640 38
  protected function getDirection($direction): int
1641
  {
1642 38
    if (\is_string($direction)) {
1643 10
      $direction = \strtolower($direction);
1644
1645 10
      if ($direction === 'desc') {
1646 2
        $direction = SORT_DESC;
1647
      } else {
1648 8
        $direction = SORT_ASC;
1649
      }
1650
    }
1651
1652
    if (
1653 38
        $direction !== SORT_DESC
1654
        &&
1655 38
        $direction !== SORT_ASC
1656
    ) {
1657
      $direction = SORT_ASC;
1658
    }
1659
1660 38
    return $direction;
1661
  }
1662
1663
  /**
1664
   * alias: for "Arrayy->keys()"
1665
   *
1666
   * @see Arrayy::keys()
1667
   *
1668
   * @return static <p>(Immutable)</p>
1669
   */
1670 1
  public function getKeys()
1671
  {
1672 1
    return $this->keys();
1673
  }
1674
1675
  /**
1676
   * Get the current array from the "Arrayy"-object as object.
1677
   *
1678
   * @return \stdClass (object)
1679
   */
1680 4
  public function getObject(): \stdClass
1681
  {
1682 4
    return self::arrayToObject($this->getArray());
1683
  }
1684
1685
  /**
1686
   * alias: for "Arrayy->randomImmutable()"
1687
   *
1688
   * @see Arrayy::randomImmutable()
1689
   *
1690
   * @return static <p>(Immutable)</p>
1691
   */
1692 4
  public function getRandom()
1693
  {
1694 4
    return $this->randomImmutable();
1695
  }
1696
1697
  /**
1698
   * alias: for "Arrayy->randomKey()"
1699
   *
1700
   * @see Arrayy::randomKey()
1701
   *
1702
   * @return mixed <p>Get a key/index or null if there wasn't a key/index.</p>
1703
   */
1704 3
  public function getRandomKey()
1705
  {
1706 3
    return $this->randomKey();
1707
  }
1708
1709
  /**
1710
   * alias: for "Arrayy->randomKeys()"
1711
   *
1712
   * @see Arrayy::randomKeys()
1713
   *
1714
   * @param int $number
1715
   *
1716
   * @return static <p>(Immutable)</p>
1717
   */
1718 8
  public function getRandomKeys(int $number)
1719
  {
1720 8
    return $this->randomKeys($number);
1721
  }
1722
1723
  /**
1724
   * alias: for "Arrayy->randomValue()"
1725
   *
1726
   * @see Arrayy::randomValue()
1727
   *
1728
   * @return mixed <p>get a random value or null if there wasn't a value.</p>
1729
   */
1730 3
  public function getRandomValue()
1731
  {
1732 3
    return $this->randomValue();
1733
  }
1734
1735
  /**
1736
   * alias: for "Arrayy->randomValues()"
1737
   *
1738
   * @see Arrayy::randomValues()
1739
   *
1740
   * @param int $number
1741
   *
1742
   * @return static <p>(Immutable)</p>
1743
   */
1744 6
  public function getRandomValues(int $number)
1745
  {
1746 6
    return $this->randomValues($number);
1747
  }
1748
1749
  /**
1750
   * Group values from a array according to the results of a closure.
1751
   *
1752
   * @param \callable $grouper <p>A callable function name.</p>
1753
   * @param bool      $saveKeys
1754
   *
1755
   * @return static <p>(Immutable)</p>
1756
   */
1757 3
  public function group($grouper, bool $saveKeys = false)
1758
  {
1759 3
    $array = (array)$this->array;
1760 3
    $result = [];
1761
1762
    // Iterate over values, group by property/results from closure.
1763 3
    foreach ($array as $key => $value) {
1764
1765 3
      $groupKey = \is_callable($grouper) ? $grouper($value, $key) : $this->get($grouper, null, $array);
1766 3
      $newValue = $this->get($groupKey, null, $result);
1767
1768 3
      if ($groupKey instanceof self) {
1769
        $groupKey = $groupKey->getArray();
1770
      }
1771
1772 3
      if ($newValue instanceof self) {
1773 3
        $newValue = $newValue->getArray();
1774
      }
1775
1776
      // Add to results.
1777 3
      if ($groupKey !== null) {
1778 2
        if ($saveKeys) {
1779 1
          $result[$groupKey] = $newValue;
1780 1
          $result[$groupKey][$key] = $value;
1781
        } else {
1782 1
          $result[$groupKey] = $newValue;
1783 3
          $result[$groupKey][] = $value;
1784
        }
1785
      }
1786
1787
    }
1788
1789 3
    return static::create($result);
1790
  }
1791
1792
  /**
1793
   * Check if an array has a given key.
1794
   *
1795
   * @param mixed $key
1796
   *
1797
   * @return bool
1798
   */
1799 22
  public function has($key): bool
1800
  {
1801
    // Generate unique string to use as marker.
1802 22
    $unFound = \uniqid('arrayy', true);
1803
1804 22
    return $this->get($key, $unFound) !== $unFound;
1805
  }
1806
1807
  /**
1808
   * Implodes the values of this array.
1809
   *
1810
   * @param string $glue
1811
   *
1812
   * @return string
1813
   */
1814 27
  public function implode(string $glue = ''): string
1815
  {
1816 27
    return $this->implode_recursive($glue, $this->array, false);
1817
  }
1818
1819
  /**
1820
   * Implodes the keys of this array.
1821
   *
1822
   * @param string $glue
1823
   *
1824
   * @return string
1825
   */
1826 8
  public function implodeKeys(string $glue = ''): string
1827
  {
1828 8
    return $this->implode_recursive($glue, $this->array, true);
1829
  }
1830
1831
  /**
1832
   * @param mixed               $glue
1833
   * @param string|array|static $pieces
1834
   * @param bool                $useKeys
1835
   *
1836
   * @return string
1837
   */
1838 35
  protected function implode_recursive($glue = '', $pieces = [], bool $useKeys = false): string
1839
  {
1840 35
    if ($pieces instanceof self) {
1841 1
      $pieces = $pieces->getArray();
1842
    }
1843
1844 35
    if (\is_array($pieces)) {
1845 35
      $pieces_count = \count($pieces, COUNT_NORMAL);
1846 35
      $pieces_count_not_zero = $pieces_count > 0;
1847
1848 35
      return \implode(
1849 35
          $glue,
1850 35
          \array_map(
1851 35
              [$this, 'implode_recursive'],
1852 35
              \array_fill(0, ($pieces_count_not_zero ? $pieces_count : 1), $glue),
1853 35
              ($useKeys === true && $pieces_count_not_zero ? $this->array_keys_recursive($pieces) : $pieces)
1854
          )
1855
      );
1856
    }
1857
1858 35
    return (string)$pieces;
1859
  }
1860
1861
  /**
1862
   * @param mixed $needle   <p>
1863
   *                        The searched value.
1864
   *                        </p>
1865
   *                        <p>
1866
   *                        If needle is a string, the comparison is done
1867
   *                        in a case-sensitive manner.
1868
   *                        </p>
1869
   * @param array $haystack <p>
1870
   *                        The array.
1871
   *                        </p>
1872
   * @param bool  $strict   [optional] <p>
1873
   *                        If the third parameter strict is set to true
1874
   *                        then the in_array function will also check the
1875
   *                        types of the
1876
   *                        needle in the haystack.
1877
   *                        </p>
1878
   *
1879
   * @return bool true if needle is found in the array, false otherwise.
1880
   */
1881 44
  protected function in_array_recursive($needle, array $haystack = null, $strict = true): bool
1882
  {
1883 44
    if ($haystack === null) {
1884
      $haystack = $this->array;
1885
    }
1886
1887 44
    foreach ($haystack as $item) {
1888
1889 36
      if (\is_array($item) === true) {
1890 8
        $returnTmp = $this->in_array_recursive($needle, $item, $strict);
1891
      } else {
1892 36
        $returnTmp = ($strict === true ? $item === $needle : $item == $needle);
1893
      }
1894
1895 36
      if ($returnTmp === true) {
1896 36
        return true;
1897
      }
1898
    }
1899
1900 18
    return false;
1901
  }
1902
1903
  /**
1904
   * Given a list and an iterate-function that returns
1905
   * a key for each element in the list (or a property name),
1906
   * returns an object with an index of each item.
1907
   *
1908
   * @param mixed $key
1909
   *
1910
   * @return static <p>(Immutable)</p>
1911
   */
1912 3
  public function indexBy($key)
1913
  {
1914 3
    $results = [];
1915
1916 3
    foreach ($this->array as $a) {
1917 3
      if (\array_key_exists($key, $a) === true) {
1918 3
        $results[$a[$key]] = $a;
1919
      }
1920
    }
1921
1922 3
    return static::create($results);
1923
  }
1924
1925
  /**
1926
   * alias: for "Arrayy->searchIndex()"
1927
   *
1928
   * @see Arrayy::searchIndex()
1929
   *
1930
   * @param mixed $value <p>The value to search for.</p>
1931
   *
1932
   * @return mixed
1933
   */
1934 4
  public function indexOf($value)
1935
  {
1936 4
    return $this->searchIndex($value);
1937
  }
1938
1939
  /**
1940
   * Get everything but the last..$to items.
1941
   *
1942
   * @param int $to
1943
   *
1944
   * @return static <p>(Immutable)</p>
1945
   */
1946 12
  public function initial(int $to = 1)
1947
  {
1948 12
    return $this->firstsImmutable(\count($this->array, COUNT_NORMAL) - $to);
1949
  }
1950
1951
  /**
1952
   * @param mixed $value
1953
   */
1954 476
  protected function internalGetArray(&$value)
1955
  {
1956 476
    if ($value instanceof self) {
1957
1958
      $valueTmp = $value->getArray();
1959
      if (\count($valueTmp, COUNT_NORMAL) === 0) {
1960
        $value = [];
1961
      } else {
1962
        /** @noinspection PhpUnusedLocalVariableInspection */
1963
        $value = &$valueTmp;
1964
      }
1965
1966 476
    } 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...
1967
      /** @noinspection PhpUnusedLocalVariableInspection */
1968
      $value = &$value->jsonSerialize();
1969
    }
1970 476
  }
1971
1972
  /**
1973
   * Internal mechanics of remove method.
1974
   *
1975
   * @param mixed $key
1976
   *
1977
   * @return bool
1978
   */
1979 18
  protected function internalRemove($key): bool
1980
  {
1981 18
    $path = \explode($this->pathSeparator, (string)$key);
1982
1983
    // Crawl though the keys
1984 18
    while (\count($path, COUNT_NORMAL) > 1) {
1985
      $key = \array_shift($path);
1986
1987
      if (!$this->has($key)) {
1988
        return false;
1989
      }
1990
1991
      $this->array = &$this->array[$key];
1992
    }
1993
1994 18
    $key = \array_shift($path);
1995
1996 18
    unset($this->array[$key]);
1997
1998 18
    return true;
1999
  }
2000
2001
  /**
2002
   * Internal mechanic of set method.
2003
   *
2004
   * @param mixed $key
2005
   * @param mixed $value
2006
   *
2007
   * @return bool
2008
   */
2009 30
  protected function internalSet($key, $value): bool
2010
  {
2011 30
    if ($key === null) {
2012
      return false;
2013
    }
2014
2015
    // init
2016 30
    $array =& $this->array;
2017 30
    $path = \explode($this->pathSeparator, (string)$key);
2018
2019
    // Crawl through the keys
2020 30
    while (\count($path, COUNT_NORMAL) > 1) {
2021 3
      $key = \array_shift($path);
2022
2023
      // If the key doesn't exist at this depth, we will just create an empty array
2024
      // to hold the next value, allowing us to create the arrays to hold final
2025
      // values at the correct depth. Then we'll keep digging into the array.
2026 3
      if (!isset($array[$key]) || !\is_array($array[$key])) {
2027
        $array[$key] = static::create([]);
2028
      }
2029
2030 3
      $array =& $array[$key];
2031
    }
2032
2033 30
    $array[\array_shift($path)] = $value;
2034
2035 30
    return true;
2036
  }
2037
2038
  /**
2039
   * Return an array with all elements found in input array.
2040
   *
2041
   * @param array $search
2042
   *
2043
   * @return static <p>(Immutable)</p>
2044
   */
2045 2
  public function intersection(array $search)
2046
  {
2047 2
    return static::create(\array_values(\array_intersect($this->array, $search)));
2048
  }
2049
2050
  /**
2051
   * Return a boolean flag which indicates whether the two input arrays have any common elements.
2052
   *
2053
   * @param array $search
2054
   *
2055
   * @return bool
2056
   */
2057 1
  public function intersects(array $search): bool
2058
  {
2059 1
    return \count($this->intersection($search)->array, COUNT_NORMAL) > 0;
2060
  }
2061
2062
  /**
2063
   * Invoke a function on all of an array's values.
2064
   *
2065
   * @param mixed $callable
2066
   * @param mixed $arguments
2067
   *
2068
   * @return static <p>(Immutable)</p>
2069
   */
2070 1
  public function invoke($callable, $arguments = [])
2071
  {
2072
    // If one argument given for each iteration, create an array for it.
2073 1
    if (!\is_array($arguments)) {
2074 1
      $arguments = StaticArrayy::repeat(
2075 1
          $arguments,
2076 1
          \count($this->array, COUNT_NORMAL)
2077 1
      )->getArray();
2078
    }
2079
2080
    // If the callable has arguments, pass them.
2081 1
    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...
2082 1
      $array = \array_map($callable, $this->array, $arguments);
2083
    } else {
2084 1
      $array = \array_map($callable, $this->array);
2085
    }
2086
2087 1
    return static::create($array);
2088
  }
2089
2090
  /**
2091
   * Check whether array is associative or not.
2092
   *
2093
   * @param bool $recursive
2094
   *
2095
   * @return bool <p>Returns true if associative, false otherwise.</p>
2096
   */
2097 15
  public function isAssoc(bool $recursive = false): bool
2098
  {
2099 15
    if ($this->isEmpty()) {
2100 3
      return false;
2101
    }
2102
2103 13
    foreach ($this->keys($recursive)->getArray() as $key) {
2104 13
      if (!\is_string($key)) {
2105 13
        return false;
2106
      }
2107
    }
2108
2109 3
    return true;
2110
  }
2111
2112
  /**
2113
   * Check whether the array is empty or not.
2114
   *
2115
   * @return bool <p>Returns true if empty, false otherwise.</p>
2116
   */
2117 88
  public function isEmpty(): bool
2118
  {
2119 88
    return !$this->array;
2120
  }
2121
2122
  /**
2123
   * Check if the current array is equal to the given "$array" or not.
2124
   *
2125
   * @param array $array
2126
   *
2127
   * @return bool
2128
   */
2129
  public function isEqual(array $array): bool
2130
  {
2131
    return ($this->array === $array);
2132
  }
2133
2134
  /**
2135
   * Check if the current array is a multi-array.
2136
   *
2137
   * @return bool
2138
   */
2139 14
  public function isMultiArray(): bool
2140
  {
2141
    return !(
2142 14
        \count($this->array, COUNT_NORMAL)
2143
        ===
2144 14
        \count($this->array, COUNT_RECURSIVE)
2145
    );
2146
  }
2147
2148
  /**
2149
   * Check whether array is numeric or not.
2150
   *
2151
   * @return bool <p>Returns true if numeric, false otherwise.</p>
2152
   */
2153 5
  public function isNumeric(): bool
2154
  {
2155 5
    if ($this->isEmpty()) {
2156 2
      return false;
2157
    }
2158
2159 4
    foreach ($this->keys() as $key) {
2160 4
      if (!\is_int($key)) {
2161 4
        return false;
2162
      }
2163
    }
2164
2165 2
    return true;
2166
  }
2167
2168
  /**
2169
   * Check if the current array is sequential [0, 1, 2, 3, 4, 5 ...] or not.
2170
   *
2171
   * @param bool $recursive
2172
   *
2173
   * @return bool
2174
   */
2175 1
  public function isSequential(bool $recursive = false): bool
2176
  {
2177
2178
    // recursive
2179
2180 1
    if ($recursive === true) {
2181
      return $this->array_keys_recursive($this->array)
2182
             ===
2183
             \range(0, \count($this->array, COUNT_RECURSIVE) - 1);
2184
    }
2185
2186
    // non recursive
2187
2188 1
    return \array_keys($this->array)
2189
           ===
2190 1
           \range(0, \count($this->array, COUNT_NORMAL) - 1);
2191
  }
2192
2193
  /**
2194
   * @return array
2195
   */
2196
  public function jsonSerialize(): array
2197
  {
2198
    return $this->getArray();
2199
  }
2200
2201
  /**
2202
   * Get all keys from the current array.
2203
   *
2204
   * @param bool  $recursive    [optional] <p>
2205
   *                            Get all keys, also from all sub-arrays from an multi-dimensional array.
2206
   *                            </p>
2207
   * @param mixed $search_value [optional] <p>
2208
   *                            If specified, then only keys containing these values are returned.
2209
   *                            </p>
2210
   * @param bool  $strict       [optional] <p>
2211
   *                            Determines if strict comparison (===) should be used during the search.
2212
   *                            </p>
2213
   *
2214
   * @return static <p>(Immutable) An array of all the keys in input.</p>
2215
   */
2216 26
  public function keys(bool $recursive = false, $search_value = null, bool $strict = true)
2217
  {
2218
2219
    // recursive
2220
2221 26
    if ($recursive === true) {
2222 3
      if ($search_value === null) {
2223 3
        $array = $this->array_keys_recursive($this->array);
2224
      } else {
2225
        $array = $this->array_keys_recursive($this->array, $search_value, $strict);
2226
      }
2227
2228 3
      return static::create($array);
2229
    }
2230
2231
    // non recursive
2232
2233 25
    if ($search_value === null) {
2234 25
      $array = \array_keys($this->array);
2235
    } else {
2236
      $array = \array_keys($this->array, $search_value, $strict);
2237
    }
2238
2239 25
    return static::create($array);
2240
  }
2241
2242
  /**
2243
   * Sort an array by key in reverse order.
2244
   *
2245
   * @param int $sort_flags [optional] <p>
2246
   *                        You may modify the behavior of the sort using the optional
2247
   *                        parameter sort_flags, for details
2248
   *                        see sort.
2249
   *                        </p>
2250
   *
2251
   * @return static <p>(Mutable) Return this Arrayy object.</p>
2252
   */
2253 4
  public function krsort(int $sort_flags = 0)
2254
  {
2255 4
    krsort($this->array, $sort_flags);
2256
2257 4
    return $this;
2258
  }
2259
2260
  /**
2261
   * Get the last value from the current array.
2262
   *
2263
   * @return mixed <p>Return null if there wasn't a element.</p>
2264
   */
2265 4
  public function last()
2266
  {
2267 4
    return $this->pop();
2268
  }
2269
2270
  /**
2271
   * Get the last value(s) from the current array.
2272
   *
2273
   * @param int|null $number
2274
   *
2275
   * @return static <p>(Immutable)</p>
2276
   */
2277 13
  public function lastsImmutable(int $number = null)
2278
  {
2279 13
    if ($this->isEmpty()) {
2280 1
      return static::create();
2281
    }
2282
2283 12
    if ($number === null) {
2284 8
      $poppedValue = $this->pop();
2285
2286 8
      if ($poppedValue === null) {
2287 1
        $poppedValue = [$poppedValue];
2288
      } else {
2289 7
        $poppedValue = (array)$poppedValue;
2290
      }
2291
2292 8
      $arrayy = static::create($poppedValue);
2293
    } else {
2294 4
      $number = (int)$number;
2295 4
      $arrayy = $this->rest(-$number);
2296
    }
2297
2298 12
    return $arrayy;
2299
  }
2300
2301
  /**
2302
   * Get the last value(s) from the current array.
2303
   *
2304
   * @param int|null $number
2305
   *
2306
   * @return static <p>(Mutable)</p>
2307
   */
2308 13
  public function lastsMutable(int $number = null)
2309
  {
2310 13
    if ($this->isEmpty()) {
2311 1
      return $this;
2312
    }
2313
2314 12
    if ($number === null) {
2315 8
      $poppedValue = $this->pop();
2316
2317 8
      if ($poppedValue === null) {
2318 1
        $poppedValue = [$poppedValue];
2319
      } else {
2320 7
        $poppedValue = (array)$poppedValue;
2321
      }
2322
2323 8
      $this->array = static::create($poppedValue)->array;
2324
    } else {
2325 4
      $number = (int)$number;
2326 4
      $this->array = $this->rest(-$number)->array;
2327
    }
2328
2329 12
    return $this;
2330
  }
2331
2332
  /**
2333
   * Count the values from the current array.
2334
   *
2335
   * alias: for "Arrayy->count()"
2336
   *
2337
   * @see Arrayy::count()
2338
   *
2339
   * @param int $mode
2340
   *
2341
   * @return int
2342
   */
2343 20
  public function length(int $mode = COUNT_NORMAL): int
2344
  {
2345 20
    return $this->count($mode);
2346
  }
2347
2348
  /**
2349
   * Apply the given function to the every element of the array,
2350
   * collecting the results.
2351
   *
2352
   * @param \callable $callable
2353
   *
2354
   * @return static <p>(Immutable) Arrayy object with modified elements.</p>
2355
   */
2356 4
  public function map($callable)
2357
  {
2358 4
    $result = \array_map($callable, $this->array);
2359
2360 4
    return static::create($result);
2361
  }
2362
2363
  /**
2364
   * Check if all items in current array match a truth test.
2365
   *
2366
   * @param \Closure $closure
2367
   *
2368
   * @return bool
2369
   */
2370 15 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...
2371
  {
2372 15
    if (\count($this->array, COUNT_NORMAL) === 0) {
2373 2
      return false;
2374
    }
2375
2376
    // init
2377 13
    $array = $this->array;
2378
2379 13
    foreach ($array as $key => $value) {
2380 13
      $value = $closure($value, $key);
2381
2382 13
      if ($value === false) {
2383 13
        return false;
2384
      }
2385
    }
2386
2387 7
    return true;
2388
  }
2389
2390
  /**
2391
   * Check if any item in the current array matches a truth test.
2392
   *
2393
   * @param \Closure $closure
2394
   *
2395
   * @return bool
2396
   */
2397 14 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...
2398
  {
2399 14
    if (\count($this->array, COUNT_NORMAL) === 0) {
2400 2
      return false;
2401
    }
2402
2403
    // init
2404 12
    $array = $this->array;
2405
2406 12
    foreach ($array as $key => $value) {
2407 12
      $value = $closure($value, $key);
2408
2409 12
      if ($value === true) {
2410 12
        return true;
2411
      }
2412
    }
2413
2414 4
    return false;
2415
  }
2416
2417
  /**
2418
   * Get the max value from an array.
2419
   *
2420
   * @return mixed
2421
   */
2422 10 View Code Duplication
  public function max()
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...
2423
  {
2424 10
    if (\count($this->array, COUNT_NORMAL) === 0) {
2425 1
      return false;
2426
    }
2427
2428 9
    return max($this->array);
2429
  }
2430
2431
  /**
2432
   * Merge the new $array into the current array.
2433
   *
2434
   * - keep key,value from the current array, also if the index is in the new $array
2435
   *
2436
   * @param array $array
2437
   * @param bool  $recursive
2438
   *
2439
   * @return static <p>(Immutable)</p>
2440
   */
2441 25 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...
2442
  {
2443 25
    if (true === $recursive) {
2444 4
      $result = \array_replace_recursive($this->array, $array);
2445
    } else {
2446 21
      $result = \array_replace($this->array, $array);
2447
    }
2448
2449 25
    return static::create($result);
2450
  }
2451
2452
  /**
2453
   * Merge the new $array into the current array.
2454
   *
2455
   * - replace duplicate assoc-keys from the current array with the key,values from the new $array
2456
   * - create new indexes
2457
   *
2458
   * @param array $array
2459
   * @param bool  $recursive
2460
   *
2461
   * @return static <p>(Immutable)</p>
2462
   */
2463 16 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...
2464
  {
2465 16
    if (true === $recursive) {
2466 4
      $result = \array_merge_recursive($this->array, $array);
2467
    } else {
2468 12
      $result = \array_merge($this->array, $array);
2469
    }
2470
2471 16
    return static::create($result);
2472
  }
2473
2474
  /**
2475
   * Merge the the current array into the $array.
2476
   *
2477
   * - use key,value from the new $array, also if the index is in the current array
2478
   *
2479
   * @param array $array
2480
   * @param bool  $recursive
2481
   *
2482
   * @return static <p>(Immutable)</p>
2483
   */
2484 16 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...
2485
  {
2486 16
    if (true === $recursive) {
2487 4
      $result = \array_replace_recursive($array, $this->array);
2488
    } else {
2489 12
      $result = \array_replace($array, $this->array);
2490
    }
2491
2492 16
    return static::create($result);
2493
  }
2494
2495
  /**
2496
   * Merge the current array into the new $array.
2497
   *
2498
   * - replace duplicate assoc-keys from new $array with the key,values from the current array
2499
   * - create new indexes
2500
   *
2501
   * @param array $array
2502
   * @param bool  $recursive
2503
   *
2504
   * @return static <p>(Immutable)</p>
2505
   */
2506 17 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...
2507
  {
2508 17
    if (true === $recursive) {
2509 4
      $result = \array_merge_recursive($array, $this->array);
2510
    } else {
2511 13
      $result = \array_merge($array, $this->array);
2512
    }
2513
2514 17
    return static::create($result);
2515
  }
2516
2517
  /**
2518
   * Get the min value from an array.
2519
   *
2520
   * @return mixed
2521
   */
2522 10 View Code Duplication
  public function min()
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...
2523
  {
2524 10
    if (\count($this->array, COUNT_NORMAL) === 0) {
2525 1
      return false;
2526
    }
2527
2528 9
    return min($this->array);
2529
  }
2530
2531
  /**
2532
   * Move an array element to a new index.
2533
   *
2534
   * cherry-picked from: http://stackoverflow.com/questions/12624153/move-an-array-element-to-a-new-index-in-php
2535
   *
2536
   * @param int|string $from
2537
   * @param int|string $to
2538
   *
2539
   * @return static <p>(Immutable)</p>
2540
   */
2541 1
  public function moveElement($from, $to)
2542
  {
2543 1
    $array = $this->array;
2544
2545 1
    if (\is_int($from)) {
2546 1
      $tmp = \array_splice($array, $from, 1);
2547 1
      \array_splice($array, $to, 0, $tmp);
2548 1
      $output = $array;
2549 1
    } elseif (\is_string($from)) {
2550 1
      $indexToMove = \array_search($from, \array_keys($array), true);
2551 1
      $itemToMove = $array[$from];
2552 1
      \array_splice($array, $indexToMove, 1);
2553 1
      $i = 0;
2554 1
      $output = [];
2555 1
      foreach ($array as $key => $item) {
2556 1
        if ($i == $to) {
2557 1
          $output[$from] = $itemToMove;
2558
        }
2559 1
        $output[$key] = $item;
2560 1
        $i++;
2561
      }
2562
    } else {
2563
      $output = [];
2564
    }
2565
2566 1
    return static::create($output);
2567
  }
2568
2569
  /**
2570
   * Convert a object into an array.
2571
   *
2572
   * @param object $object
2573
   *
2574
   * @return mixed
2575
   */
2576 5
  protected static function objectToArray($object)
2577
  {
2578 5
    if (!\is_object($object)) {
2579 4
      return $object;
2580
    }
2581
2582 5
    if (\is_object($object)) {
2583 5
      $object = \get_object_vars($object);
2584
    }
2585
2586 5
    return \array_map(['self', 'objectToArray'], $object);
2587
  }
2588
2589
  /**
2590
   * Get a subset of the items from the given array.
2591
   *
2592
   * @param mixed[] $keys
2593
   *
2594
   * @return static <p>(Immutable)</p>
2595
   */
2596
  public function only(array $keys)
2597
  {
2598
    $array = $this->array;
2599
2600
    return static::create(\array_intersect_key($array, \array_flip($keys)));
2601
  }
2602
2603
  /**
2604
   * Pad array to the specified size with a given value.
2605
   *
2606
   * @param int   $size  <p>Size of the result array.</p>
2607
   * @param mixed $value <p>Empty value by default.</p>
2608
   *
2609
   * @return static <p>(Immutable) Arrayy object padded to $size with $value.</p>
2610
   */
2611 4
  public function pad(int $size, $value)
2612
  {
2613 4
    $result = \array_pad($this->array, $size, $value);
2614
2615 4
    return static::create($result);
2616
  }
2617
2618
  /**
2619
   * Pop a specified value off the end of the current array.
2620
   *
2621
   * @return mixed <p>(Mutable) The popped element from the current array.</p>
2622
   */
2623 16
  public function pop()
2624
  {
2625 16
    return \array_pop($this->array);
2626
  }
2627
2628
  /**
2629
   * Prepend a (key) + value to the current array.
2630
   *
2631
   * @param mixed $value
2632
   * @param mixed $key
2633
   *
2634
   * @return static <p>(Mutable) Return this Arrayy object, with the prepended value.</p>
2635
   */
2636 8
  public function prepend($value, $key = null)
2637
  {
2638 8
    if ($key === null) {
2639 8
      \array_unshift($this->array, $value);
2640
    } else {
2641
      /** @noinspection AdditionOperationOnArraysInspection */
2642 1
      $this->array = [$key => $value] + $this->array;
2643
    }
2644
2645 8
    return $this;
2646
  }
2647
2648
  /**
2649
   * Add a suffix to each key.
2650
   *
2651
   * @param mixed $suffix
2652
   *
2653
   * @return static <p>(Immutable) Return an Arrayy object, with the prepended keys.</p>
2654
   */
2655 10 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...
2656
  {
2657 10
    $result = [];
2658 10
    foreach ($this->array as $key => $item) {
2659 9
      if ($item instanceof self) {
2660
        $result[$key] = $item->prependToEachKey($suffix);
2661 9
      } elseif (\is_array($item)) {
2662
        $result[$key] = self::create($item)->prependToEachKey($suffix)->toArray();
2663
      } else {
2664 9
        $result[$key . $suffix] = $item;
2665
      }
2666
2667
    }
2668
2669 10
    return self::create($result);
2670
  }
2671
2672
  /**
2673
   * Add a suffix to each value.
2674
   *
2675
   * @param mixed $suffix
2676
   *
2677
   * @return static <p>(Immutable) Return an Arrayy object, with the prepended values.</p>
2678
   */
2679 10 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...
2680
  {
2681 10
    $result = [];
2682 10
    foreach ($this->array as $key => $item) {
2683 9
      if ($item instanceof self) {
2684
        $result[$key] = $item->prependToEachValue($suffix);
2685 9
      } elseif (\is_array($item)) {
2686
        $result[$key] = self::create($item)->prependToEachValue($suffix)->toArray();
2687 9
      } elseif (\is_object($item)) {
2688 1
        $result[$key] = $item;
2689
      } else {
2690 9
        $result[$key] = $item . $suffix;
2691
      }
2692
    }
2693
2694 10
    return self::create($result);
2695
  }
2696
2697
  /**
2698
   * Push one or more values onto the end of array at once.
2699
   *
2700
   * @return static <p>(Mutable) Return this Arrayy object, with pushed elements to the end of array.</p>
2701
   */
2702 4 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...
2703
  {
2704 4
    if (\func_num_args()) {
2705 4
      $args = \array_merge([&$this->array], \func_get_args());
2706 4
      \array_push(...$args);
2707
    }
2708
2709 4
    return $this;
2710
  }
2711
2712
  /**
2713
   * Get a random value from the current array.
2714
   *
2715
   * @param null|int $number <p>How many values you will take?</p>
2716
   *
2717
   * @return static <p>(Immutable)</p>
2718
   */
2719 18
  public function randomImmutable(int $number = null)
2720
  {
2721 18
    if (\count($this->array, COUNT_NORMAL) === 0) {
2722 1
      return static::create();
2723
    }
2724
2725 17 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...
2726 14
      $arrayRandValue = [$this->array[\array_rand($this->array)]];
2727
2728 14
      return static::create($arrayRandValue);
2729
    }
2730
2731 5
    $arrayTmp = $this->array;
2732 5
    \shuffle($arrayTmp);
2733
2734 5
    return static::create($arrayTmp)->firstsImmutable($number);
2735
  }
2736
2737
  /**
2738
   * Pick a random key/index from the keys of this array.
2739
   *
2740
   * @return mixed <p>Get a key/index or null if there wasn't a key/index.</p>
2741
   *
2742
   * @throws \RangeException If array is empty
2743
   */
2744 4
  public function randomKey()
2745
  {
2746 4
    $result = $this->randomKeys(1);
2747
2748 4
    if (!isset($result[0])) {
2749
      $result[0] = null;
2750
    }
2751
2752 4
    return $result[0];
2753
  }
2754
2755
  /**
2756
   * Pick a given number of random keys/indexes out of this array.
2757
   *
2758
   * @param int $number <p>The number of keys/indexes (should be <= \count($this->array))</p>
2759
   *
2760
   * @return static <p>(Immutable)</p>
2761
   *
2762
   * @throws \RangeException If array is empty
2763
   */
2764 13
  public function randomKeys(int $number)
2765
  {
2766 13
    $count = \count($this->array, COUNT_NORMAL);
2767
2768 13
    if ($number === 0 || $number > $count) {
2769 2
      throw new \RangeException(
2770 2
          \sprintf(
2771 2
              'Number of requested keys (%s) must be equal or lower than number of elements in this array (%s)',
2772 2
              $number,
2773 2
              $count
2774
          )
2775
      );
2776
    }
2777
2778 11
    $result = (array)\array_rand($this->array, $number);
2779
2780 11
    return static::create($result);
2781
  }
2782
2783
  /**
2784
   * Get a random value from the current array.
2785
   *
2786
   * @param null|int $number <p>How many values you will take?</p>
2787
   *
2788
   * @return static <p>(Mutable)</p>
2789
   */
2790 17
  public function randomMutable(int $number = null)
2791
  {
2792 17
    if (\count($this->array, COUNT_NORMAL) === 0) {
2793
      return static::create();
2794
    }
2795
2796 17 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...
2797 7
      $arrayRandValue = [$this->array[\array_rand($this->array)]];
2798 7
      $this->array = $arrayRandValue;
2799
2800 7
      return $this;
2801
    }
2802
2803 11
    \shuffle($this->array);
2804
2805 11
    return $this->firstsMutable($number);
2806
  }
2807
2808
  /**
2809
   * Pick a random value from the values of this array.
2810
   *
2811
   * @return mixed <p>Get a random value or null if there wasn't a value.</p>
2812
   */
2813 4
  public function randomValue()
2814
  {
2815 4
    $result = $this->randomImmutable();
2816
2817 4
    if (!isset($result[0])) {
2818
      $result[0] = null;
2819
    }
2820
2821 4
    return $result[0];
2822
  }
2823
2824
  /**
2825
   * Pick a given number of random values out of this array.
2826
   *
2827
   * @param int $number
2828
   *
2829
   * @return static <p>(Mutable)</p>
2830
   */
2831 7
  public function randomValues(int $number)
2832
  {
2833 7
    return $this->randomMutable($number);
2834
  }
2835
2836
  /**
2837
   * Get a random value from an array, with the ability to skew the results.
2838
   *
2839
   * Example: randomWeighted(['foo' => 1, 'bar' => 2]) has a 66% chance of returning bar.
2840
   *
2841
   * @param array    $array
2842
   * @param null|int $number <p>How many values you will take?</p>
2843
   *
2844
   * @return static <p>(Immutable)</p>
2845
   */
2846 9
  public function randomWeighted(array $array, int $number = null)
2847
  {
2848 9
    $options = [];
2849 9
    foreach ($array as $option => $weight) {
2850 9
      if ($this->searchIndex($option) !== false) {
2851 9
        for ($i = 0; $i < $weight; ++$i) {
2852 1
          $options[] = $option;
2853
        }
2854
      }
2855
    }
2856
2857 9
    return $this->mergeAppendKeepIndex($options)->randomImmutable($number);
2858
  }
2859
2860
  /**
2861
   * Reduce the current array via callable e.g. anonymous-function.
2862
   *
2863
   * @param \callable $callable
2864
   * @param array     $init
2865
   *
2866
   * @return static <p>(Immutable)</p>
2867
   */
2868 4
  public function reduce($callable, array $init = [])
2869
  {
2870 4
    $result = \array_reduce($this->array, $callable, $init);
2871
2872 4
    if ($result === null) {
2873
      $this->array = [];
2874
    } else {
2875 4
      $this->array = (array)$result;
2876
    }
2877
2878 4
    return static::create($this->array);
2879
  }
2880
2881
  /**
2882
   * Create a numerically re-indexed Arrayy object.
2883
   *
2884
   * @return static <p>(Mutable) Return this Arrayy object, with re-indexed array-elements.</p>
2885
   */
2886 9
  public function reindex()
2887
  {
2888 9
    $this->array = \array_values($this->array);
2889
2890 9
    return $this;
2891
  }
2892
2893
  /**
2894
   * Return all items that fail the truth test.
2895
   *
2896
   * @param \Closure $closure
2897
   *
2898
   * @return static <p>(Immutable)</p>
2899
   */
2900 1 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...
2901
  {
2902 1
    $filtered = [];
2903
2904 1
    foreach ($this->array as $key => $value) {
2905 1
      if (!$closure($value, $key)) {
2906 1
        $filtered[$key] = $value;
2907
      }
2908
    }
2909
2910 1
    return static::create($filtered);
2911
  }
2912
2913
  /**
2914
   * Remove a value from the current array (optional using dot-notation).
2915
   *
2916
   * @param mixed $key
2917
   *
2918
   * @return static <p>(Immutable)</p>
2919
   */
2920 18
  public function remove($key)
2921
  {
2922
    // recursive call
2923 18
    if (\is_array($key)) {
2924
      foreach ($key as $k) {
2925
        $this->internalRemove($k);
2926
      }
2927
2928
      return static::create($this->array);
2929
    }
2930
2931 18
    $this->internalRemove($key);
2932
2933 18
    return static::create($this->array);
2934
  }
2935
2936
  /**
2937
   * Remove the first value from the current array.
2938
   *
2939
   * @return static <p>(Immutable)</p>
2940
   */
2941 7
  public function removeFirst()
2942
  {
2943 7
    $tmpArray = $this->array;
2944 7
    \array_shift($tmpArray);
2945
2946 7
    return static::create($tmpArray);
2947
  }
2948
2949
  /**
2950
   * Remove the last value from the current array.
2951
   *
2952
   * @return static <p>(Immutable)</p>
2953
   */
2954 7
  public function removeLast()
2955
  {
2956 7
    $tmpArray = $this->array;
2957 7
    \array_pop($tmpArray);
2958
2959 7
    return static::create($tmpArray);
2960
  }
2961
2962
  /**
2963
   * Removes a particular value from an array (numeric or associative).
2964
   *
2965
   * @param mixed $value
2966
   *
2967
   * @return static <p>(Immutable)</p>
2968
   */
2969 7
  public function removeValue($value)
2970
  {
2971 7
    $isNumericArray = true;
2972 7
    foreach ($this->array as $key => $item) {
2973 6
      if ($item === $value) {
2974 6
        if (!\is_int($key)) {
2975
          $isNumericArray = false;
2976
        }
2977 6
        unset($this->array[$key]);
2978
      }
2979
    }
2980
2981 7
    if ($isNumericArray) {
2982 7
      $this->array = \array_values($this->array);
2983
    }
2984
2985 7
    return static::create($this->array);
2986
  }
2987
2988
  /**
2989
   * Generate array of repeated arrays.
2990
   *
2991
   * @param int $times <p>How many times has to be repeated.</p>
2992
   *
2993
   * @return Arrayy
2994
   */
2995 1
  public function repeat($times): self
2996
  {
2997 1
    if ($times === 0) {
2998 1
      return new static();
2999
    }
3000
3001 1
    return static::create(\array_fill(0, (int)$times, $this->array));
3002
  }
3003
3004
  /**
3005
   * Replace a key with a new key/value pair.
3006
   *
3007
   * @param mixed $replace
3008
   * @param mixed $key
3009
   * @param mixed $value
3010
   *
3011
   * @return static <p>(Immutable)</p>
3012
   */
3013 2
  public function replace($replace, $key, $value)
3014
  {
3015 2
    $this->remove($replace);
3016
3017 2
    return $this->set($key, $value);
3018
  }
3019
3020
  /**
3021
   * Create an array using the current array as values and the other array as keys.
3022
   *
3023
   * @param array $keys <p>An array of keys.</p>
3024
   *
3025
   * @return static <p>(Immutable) Arrayy object with keys from the other array.</p>
3026
   */
3027 2
  public function replaceAllKeys(array $keys)
3028
  {
3029 2
    $result = \array_combine($keys, $this->array);
3030
3031 2
    return static::create($result);
3032
  }
3033
3034
  /**
3035
   * Create an array using the current array as keys and the other array as values.
3036
   *
3037
   * @param array $array <p>An array o values.</p>
3038
   *
3039
   * @return static <p>(Immutable) Arrayy object with values from the other array.</p>
3040
   */
3041 2
  public function replaceAllValues(array $array)
3042
  {
3043 2
    $result = \array_combine($this->array, $array);
3044
3045 2
    return static::create($result);
3046
  }
3047
3048
  /**
3049
   * Replace the keys in an array with another set.
3050
   *
3051
   * @param array $keys <p>An array of keys matching the array's size</p>
3052
   *
3053
   * @return static <p>(Immutable)</p>
3054
   */
3055 1
  public function replaceKeys(array $keys)
3056
  {
3057 1
    $values = \array_values($this->array);
3058 1
    $result = \array_combine($keys, $values);
3059
3060 1
    return static::create($result);
3061
  }
3062
3063
  /**
3064
   * Replace the first matched value in an array.
3065
   *
3066
   * @param mixed $search      <p>The value to replace.</p>
3067
   * @param mixed $replacement <p>The value to replace.</p>
3068
   *
3069
   * @return static <p>(Immutable)</p>
3070
   */
3071 3
  public function replaceOneValue($search, $replacement = '')
3072
  {
3073 3
    $array = $this->array;
3074 3
    $key = \array_search($search, $array, true);
3075
3076 3
    if ($key !== false) {
3077 3
      $array[$key] = $replacement;
3078
    }
3079
3080 3
    return static::create($array);
3081
  }
3082
3083
  /**
3084
   * Replace values in the current array.
3085
   *
3086
   * @param mixed $search      <p>The value to replace.</p>
3087
   * @param mixed $replacement <p>What to replace it with.</p>
3088
   *
3089
   * @return static <p>(Immutable)</p>
3090
   */
3091 1
  public function replaceValues($search, $replacement = '')
3092
  {
3093 1
    $array = $this->each(
3094 1
        function ($value) use ($search, $replacement) {
3095 1
          return UTF8::str_replace($search, $replacement, $value);
3096 1
        }
3097
    );
3098
3099 1
    return $array;
3100
  }
3101
3102
  /**
3103
   * Get the last elements from index $from until the end of this array.
3104
   *
3105
   * @param int $from
3106
   *
3107
   * @return static <p>(Immutable)</p>
3108
   */
3109 15
  public function rest(int $from = 1)
3110
  {
3111 15
    $tmpArray = $this->array;
3112
3113 15
    return static::create(\array_splice($tmpArray, $from));
3114
  }
3115
3116
  /**
3117
   * Return the array in the reverse order.
3118
   *
3119
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3120
   */
3121 8
  public function reverse()
3122
  {
3123 8
    $this->array = \array_reverse($this->array);
3124
3125 8
    return $this;
3126
  }
3127
3128
  /**
3129
   * Sort an array in reverse order.
3130
   *
3131
   * @param int $sort_flags [optional] <p>
3132
   *                        You may modify the behavior of the sort using the optional
3133
   *                        parameter sort_flags, for details
3134
   *                        see sort.
3135
   *                        </p>
3136
   *
3137
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3138
   */
3139 4
  public function rsort(int $sort_flags = 0)
3140
  {
3141 4
    \rsort($this->array, $sort_flags);
3142
3143 4
    return $this;
3144
  }
3145
3146
  /**
3147
   * Search for the first index of the current array via $value.
3148
   *
3149
   * @param mixed $value
3150
   *
3151
   * @return int|float|string
3152
   */
3153 20
  public function searchIndex($value)
3154
  {
3155 20
    return \array_search($value, $this->array, true);
3156
  }
3157
3158
  /**
3159
   * Search for the value of the current array via $index.
3160
   *
3161
   * @param mixed $index
3162
   *
3163
   * @return static <p>(Immutable) Will return a empty Arrayy if the value wasn't found.</p>
3164
   */
3165 9
  public function searchValue($index)
3166
  {
3167
    // init
3168 9
    $return = [];
3169
3170 9
    if ($this->isEmpty()) {
3171
      return static::create();
3172
    }
3173
3174
    // php cast "bool"-index into "int"-index
3175 9
    if ((bool)$index === $index) {
3176 1
      $index = (int)$index;
3177
    }
3178
3179 9
    if (\array_key_exists($index, $this->array) === true) {
3180 7
      $return = [$this->array[$index]];
3181
    }
3182
3183
3184 9
    return static::create($return);
3185
  }
3186
3187
  /**
3188
   * Set a value for the current array (optional using dot-notation).
3189
   *
3190
   * @param mixed $key   <p>The key to set.</p>
3191
   * @param mixed $value <p>Its value.</p>
3192
   *
3193
   * @return static <p>(Immutable)</p>
3194
   */
3195 17
  public function set($key, $value)
3196
  {
3197 17
    $this->internalSet($key, $value);
3198
3199 17
    return static::create($this->array);
3200
  }
3201
3202
  /**
3203
   * Get a value from a array and set it if it was not.
3204
   *
3205
   * WARNING: this method only set the value, if the $key is not already set
3206
   *
3207
   * @param mixed $key      <p>The key</p>
3208
   * @param mixed $fallback <p>The default value to set if it isn't.</p>
3209
   *
3210
   * @return mixed <p>(Mutable)</p>
3211
   */
3212 11
  public function setAndGet($key, $fallback = null)
3213
  {
3214
    // If the key doesn't exist, set it.
3215 11
    if (!$this->has($key)) {
3216 4
      $this->array = $this->set($key, $fallback)->getArray();
3217
    }
3218
3219 11
    return $this->get($key);
3220
  }
3221
3222
  /**
3223
   * Shifts a specified value off the beginning of array.
3224
   *
3225
   * @return mixed <p>(Mutable) A shifted element from the current array.</p>
3226
   */
3227 4
  public function shift()
3228
  {
3229 4
    return \array_shift($this->array);
3230
  }
3231
3232
  /**
3233
   * Shuffle the current array.
3234
   *
3235
   * @param bool  $secure <p>using a CSPRNG | @link https://paragonie.com/b/JvICXzh_jhLyt4y3</p>
3236
   * @param array $array  [optional]
3237
   *
3238
   * @return static <p>(Immutable)</p>
3239
   */
3240 1
  public function shuffle(bool $secure = false, array $array = null)
3241
  {
3242 1
    if ($array === null) {
3243 1
      $array = $this->array;
3244
    }
3245
3246 1
    if ($secure !== true) {
3247 1
      \shuffle($array);
3248
    } else {
3249 1
      $size = \count($array, COUNT_NORMAL);
3250 1
      $keys = \array_keys($array);
3251 1
      for ($i = $size - 1; $i > 0; --$i) {
3252
        try {
3253 1
          $r = \random_int(0, $i);
3254
        } catch (\Exception $e) {
3255
          $r = \mt_rand();
3256
        }
3257 1
        if ($r !== $i) {
3258 1
          $temp = $array[$keys[$r]];
3259 1
          $array[$keys[$r]] = $array[$keys[$i]];
3260 1
          $array[$keys[$i]] = $temp;
3261
        }
3262
      }
3263
3264
      // reset indices
3265 1
      $array = \array_values($array);
3266
    }
3267
3268 1
    foreach ($array as $key => $value) {
3269
      // check if recursive is needed
3270 1
      if (\is_array($value) === true) {
3271 1
        $array[$key] = $this->shuffle($secure, $value);
3272
      }
3273
    }
3274
3275 1
    return static::create($array);
3276
  }
3277
3278
  /**
3279
   * Count the values from the current array.
3280
   *
3281
   * alias: for "Arrayy->count()"
3282
   *
3283
   * @param int $mode
3284
   *
3285
   * @return int
3286
   */
3287 20
  public function size(int $mode = COUNT_NORMAL): int
3288
  {
3289 20
    return $this->count($mode);
3290
  }
3291
3292
  /**
3293
   * Counts all elements in an array, or something in an object.
3294
   * <p>For objects, if you have SPL installed, you can hook into count() by implementing interface {@see Countable}.
3295
   * The interface has exactly one method, {@see Countable::count()}, which returns the return value for the count()
3296
   * function. Please see the {@see Array} section of the manual for a detailed explanation of how arrays are
3297
   * implemented and used in PHP.
3298
   *
3299
   * @return int the number of elements in var, which is
3300
   * typically an array, since anything else will have one
3301
   * element.
3302
   * </p>
3303
   * <p>
3304
   * If var is not an array or an object with
3305
   * implemented Countable interface,
3306
   * 1 will be returned.
3307
   * There is one exception, if var is &null;,
3308
   * 0 will be returned.
3309
   * </p>
3310
   * <p>
3311
   * Caution: count may return 0 for a variable that isn't set,
3312
   * but it may also return 0 for a variable that has been initialized with an
3313
   * empty array. Use isset to test if a variable is set.
3314
   *
3315
   * @return int
3316
   */
3317 10
  public function sizeRecursive(): int
3318
  {
3319 10
    return \count($this->array, COUNT_RECURSIVE);
3320
  }
3321
3322
  /**
3323
   * Extract a slice of the array.
3324
   *
3325
   * @param int      $offset       <p>Slice begin index.</p>
3326
   * @param int|null $length       <p>Length of the slice.</p>
3327
   * @param bool     $preserveKeys <p>Whether array keys are preserved or no.</p>
3328
   *
3329
   * @return static <p>A slice of the original array with length $length.</p>
3330
   */
3331 4
  public function slice(int $offset, int $length = null, bool $preserveKeys = false)
3332
  {
3333 4
    $result = \array_slice($this->array, $offset, $length, $preserveKeys);
3334
3335 4
    return static::create($result);
3336
  }
3337
3338
  /**
3339
   * Sort the current array and optional you can keep the keys.
3340
   *
3341
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3342
   * @param int        $strategy  <p>sort_flags => use e.g.: <strong>SORT_REGULAR</strong> (default) or
3343
   *                              <strong>SORT_NATURAL</strong></p>
3344
   * @param bool       $keepKeys
3345
   *
3346
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3347
   */
3348 19
  public function sort($direction = SORT_ASC, int $strategy = SORT_REGULAR, bool $keepKeys = false)
3349
  {
3350 19
    $this->sorting($this->array, $direction, $strategy, $keepKeys);
3351
3352 19
    return $this;
3353
  }
3354
3355
  /**
3356
   * Sort the current array by key.
3357
   *
3358
   * @link http://php.net/manual/en/function.ksort.php
3359
   * @link http://php.net/manual/en/function.krsort.php
3360
   *
3361
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3362
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3363
   *                              <strong>SORT_NATURAL</strong></p>
3364
   *
3365
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3366
   */
3367 18
  public function sortKeys($direction = SORT_ASC, int $strategy = SORT_REGULAR)
3368
  {
3369 18
    $this->sorterKeys($this->array, $direction, $strategy);
3370
3371 18
    return $this;
3372
  }
3373
3374
  /**
3375
   * Sort the current array by value.
3376
   *
3377
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3378
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3379
   *                              <strong>SORT_NATURAL</strong></p>
3380
   *
3381
   * @return static <p>(Mutable)</p>
3382
   */
3383 1
  public function sortValueKeepIndex($direction = SORT_ASC, int $strategy = SORT_REGULAR)
3384
  {
3385 1
    return $this->sort($direction, $strategy, true);
3386
  }
3387
3388
  /**
3389
   * Sort the current array by value.
3390
   *
3391
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3392
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3393
   *                              <strong>SORT_NATURAL</strong></p>
3394
   *
3395
   * @return static <p>(Mutable)</p>
3396
   */
3397 1
  public function sortValueNewIndex($direction = SORT_ASC, int $strategy = SORT_REGULAR)
3398
  {
3399 1
    return $this->sort($direction, $strategy, false);
3400
  }
3401
3402
  /**
3403
   * Sort a array by value, by a closure or by a property.
3404
   *
3405
   * - If the sorter is null, the array is sorted naturally.
3406
   * - Associative (string) keys will be maintained, but numeric keys will be re-indexed.
3407
   *
3408
   * @param \callable|null $sorter
3409
   * @param string|int     $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3410
   * @param int            $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3411
   *                                  <strong>SORT_NATURAL</strong></p>
3412
   *
3413
   * @return static <p>(Immutable)</p>
3414
   */
3415 1
  public function sorter($sorter = null, $direction = SORT_ASC, int $strategy = SORT_REGULAR)
3416
  {
3417 1
    $array = (array)$this->array;
3418 1
    $direction = $this->getDirection($direction);
3419
3420
    // Transform all values into their results.
3421 1
    if ($sorter) {
3422 1
      $arrayy = static::create($array);
3423
3424 1
      $that = $this;
3425 1
      $results = $arrayy->each(
3426 1
          function ($value) use ($sorter, $that) {
3427 1
            return \is_callable($sorter) ? $sorter($value) : $that->get($sorter, null, $value);
3428 1
          }
3429
      );
3430
3431 1
      $results = $results->getArray();
3432
    } else {
3433 1
      $results = $array;
3434
    }
3435
3436
    // Sort by the results and replace by original values
3437 1
    \array_multisort($results, $direction, $strategy, $array);
3438
3439 1
    return static::create($array);
3440
  }
3441
3442
  /**
3443
   * sorting keys
3444
   *
3445
   * @param array      $elements
3446
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3447
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3448
   *                              <strong>SORT_NATURAL</strong></p>
3449
   *
3450
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3451
   */
3452 18
  protected function sorterKeys(array &$elements, $direction = SORT_ASC, int $strategy = SORT_REGULAR)
3453
  {
3454 18
    $direction = $this->getDirection($direction);
3455
3456
    switch ($direction) {
3457 18
      case 'desc':
3458 18
      case SORT_DESC:
3459 6
        \krsort($elements, $strategy);
3460 6
        break;
3461 13
      case 'asc':
3462 13
      case SORT_ASC:
3463
      default:
3464 13
        \ksort($elements, $strategy);
3465
    }
3466
3467 18
    return $this;
3468
  }
3469
3470
  /**
3471
   * @param array      &$elements
3472
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3473
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3474
   *                              <strong>SORT_NATURAL</strong></p>
3475
   * @param bool       $keepKeys
3476
   *
3477
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3478
   */
3479 19
  protected function sorting(array &$elements, $direction = SORT_ASC, int $strategy = SORT_REGULAR, bool $keepKeys = false)
3480
  {
3481 19
    $direction = $this->getDirection($direction);
3482
3483 19
    if (!$strategy) {
3484 19
      $strategy = SORT_REGULAR;
3485
    }
3486
3487
    switch ($direction) {
3488 19
      case 'desc':
3489 19
      case SORT_DESC:
3490 9
        if ($keepKeys) {
3491 5
          arsort($elements, $strategy);
3492
        } else {
3493 4
          \rsort($elements, $strategy);
3494
        }
3495 9
        break;
3496 10
      case 'asc':
3497 10
      case SORT_ASC:
3498
      default:
3499 10
        if ($keepKeys) {
3500 4
          \asort($elements, $strategy);
3501
        } else {
3502 6
          \sort($elements, $strategy);
3503
        }
3504
    }
3505
3506 19
    return $this;
3507
  }
3508
3509
  /**
3510
   * Split an array in the given amount of pieces.
3511
   *
3512
   * @param int  $numberOfPieces
3513
   * @param bool $keepKeys
3514
   *
3515
   * @return static <p>(Immutable)</p>
3516
   */
3517 1
  public function split(int $numberOfPieces = 2, bool $keepKeys = false)
3518
  {
3519 1
    $arrayCount = \count($this->array, COUNT_NORMAL);
3520
3521 1
    if ($arrayCount === 0) {
3522 1
      $result = [];
3523
    } else {
3524 1
      $splitSize = (int)\ceil($arrayCount / $numberOfPieces);
3525 1
      $result = \array_chunk($this->array, $splitSize, $keepKeys);
3526
    }
3527
3528 1
    return static::create($result);
3529
  }
3530
3531
  /**
3532
   * Stripe all empty items.
3533
   *
3534
   * @return static <p>(Immutable)</p>
3535
   */
3536 1
  public function stripEmpty()
3537
  {
3538 1
    return $this->filter(
3539 1
        function ($item) {
3540 1
          if ($item === null) {
3541 1
            return false;
3542
          }
3543
3544 1
          return (bool)\trim((string)$item);
3545 1
        }
3546
    );
3547
  }
3548
3549
  /**
3550
   * Swap two values between positions by key.
3551
   *
3552
   * @param string|int $swapA <p>a key in the array</p>
3553
   * @param string|int $swapB <p>a key in the array</p>
3554
   *
3555
   * @return static <p>(Immutable)</p>
3556
   */
3557 1
  public function swap($swapA, $swapB)
3558
  {
3559 1
    $array = $this->array;
3560
3561 1
    list($array[$swapA], $array[$swapB]) = [$array[$swapB], $array[$swapA]];
3562
3563 1
    return static::create($array);
3564
  }
3565
3566
  /**
3567
   * alias: for "Arrayy->getArray()"
3568
   *
3569
   * @see Arrayy::getArray()
3570
   */
3571 186
  public function toArray()
3572
  {
3573 186
    return $this->getArray();
3574
  }
3575
3576
  /**
3577
   * Convert the current array to JSON.
3578
   *
3579
   * @param int $options [optional] <p>e.g. JSON_PRETTY_PRINT</p>
3580
   * @param int $depth   [optional] <p>Set the maximum depth. Must be greater than zero.</p>
3581
   *
3582
   * @return string
3583
   */
3584 6
  public function toJson(int $options = 0, int $depth = 512): string
3585
  {
3586 6
    return UTF8::json_encode($this->array, $options, $depth);
3587
  }
3588
3589
  /**
3590
   * Implodes array to a string with specified separator.
3591
   *
3592
   * @param string $separator [optional] <p>The element's separator.</p>
3593
   *
3594
   * @return string <p>The string representation of array, separated by ",".</p>
3595
   */
3596 19
  public function toString(string $separator = ','): string
3597
  {
3598 19
    return $this->implode($separator);
3599
  }
3600
3601
  /**
3602
   * Return a duplicate free copy of the current array.
3603
   *
3604
   * @return static <p>(Mutable)</p>
3605
   */
3606 9
  public function unique()
3607
  {
3608
    // INFO: \array_unique() can't handle e.g. "stdClass"-values in an array
3609
3610 9
    $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...
3611 9
        $this->array,
3612 9
        function ($resultArray, $value) {
3613 8
          if (!\in_array($value, $resultArray, true)) {
3614 8
            $resultArray[] = $value;
3615
          }
3616
3617 8
          return $resultArray;
3618 9
        },
3619 9
        []
3620
    );
3621
3622 9 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...
3623
      $this->array = [];
3624
    } else {
3625 9
      $this->array = (array)$this->array;
3626
    }
3627
3628 9
    return $this;
3629
  }
3630
3631
  /**
3632
   * Return a duplicate free copy of the current array. (with the old keys)
3633
   *
3634
   * @return static <p>(Mutable)</p>
3635
   */
3636 9
  public function uniqueKeepIndex()
3637
  {
3638
    // INFO: \array_unique() can't handle e.g. "stdClass"-values in an array
3639
3640
    // init
3641 9
    $array = $this->array;
3642
3643 9
    $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...
3644 9
        \array_keys($array),
3645 9
        function ($resultArray, $key) use ($array) {
3646 8
          if (!\in_array($array[$key], $resultArray, true)) {
3647 8
            $resultArray[$key] = $array[$key];
3648
          }
3649
3650 8
          return $resultArray;
3651 9
        },
3652 9
        []
3653
    );
3654
3655 9 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...
3656
      $this->array = [];
3657
    } else {
3658 9
      $this->array = (array)$this->array;
3659
    }
3660
3661 9
    return $this;
3662
  }
3663
3664
  /**
3665
   * alias: for "Arrayy->unique()"
3666
   *
3667
   * @see Arrayy::unique()
3668
   *
3669
   * @return static <p>(Mutable) Return this Arrayy object, with the appended values.</p>
3670
   */
3671 9
  public function uniqueNewIndex()
3672
  {
3673 9
    return $this->unique();
3674
  }
3675
3676
  /**
3677
   * Prepends one or more values to the beginning of array at once.
3678
   *
3679
   * @return static <p>(Mutable) Return this Arrayy object, with prepended elements to the beginning of array.</p>
3680
   */
3681 4 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...
3682
  {
3683 4
    if (\func_num_args()) {
3684 4
      $args = \array_merge([&$this->array], \func_get_args());
3685 4
      \array_unshift(...$args);
3686
    }
3687
3688 4
    return $this;
3689
  }
3690
3691
  /**
3692
   * Get all values from a array.
3693
   *
3694
   * @return static <p>(Immutable)</p>
3695
   */
3696 2
  public function values()
3697
  {
3698 2
    return static::create(\array_values((array)$this->array));
3699
  }
3700
3701
  /**
3702
   * Apply the given function to every element in the array, discarding the results.
3703
   *
3704
   * @param \callable $callable
3705
   * @param bool      $recursive <p>Whether array will be walked recursively or no</p>
3706
   *
3707
   * @return static <p>(Mutable) Return this Arrayy object, with modified elements.</p>
3708
   */
3709 35
  public function walk($callable, bool $recursive = false)
3710
  {
3711 35
    if (true === $recursive) {
3712 30
      \array_walk_recursive($this->array, $callable);
3713
    } else {
3714 18
      \array_walk($this->array, $callable);
3715
    }
3716
3717 35
    return $this;
3718
  }
3719
}
3720