Completed
Push — master ( 301894...a87d00 )
by Lars
02:21
created

Arrayy::getRandomKeys()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
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 870
  public function __construct($array = [], $iteratorClass = ArrayyIterator::class)
42
  {
43 870
    $array = $this->fallbackForArray($array);
44 868
    $this->array = $array;
45
46 868
    $this->setIteratorClass($iteratorClass);
47 868
  }
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 868
  public function setIteratorClass($class)
437
  {
438 868
    if (\class_exists($class)) {
439 868
      $this->iteratorClass = $class;
440
441 868
      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 mixed $array
948
   *
949
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
950
   */
951 538
  public static function create($array = []): self
952
  {
953 538
    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
        } elseif ($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 870
  protected function fallbackForArray(&$array): array
1254
  {
1255 870
    if (\is_array($array)) {
1256 867
      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 62
  public function get($key, $fallback = null, array $array = null)
1562
  {
1563 62
    if ($array !== null) {
1564 3
      $usedArray = $array;
1565
    } else {
1566 59
      $usedArray = $this->array;
1567
    }
1568
1569 62
    if ($key === null) {
1570 1
      return static::create($usedArray);
1571
    }
1572
1573
    // php cast "bool"-index into "int"-index
1574 62
    if ((bool)$key === $key) {
1575 2
      $key = (int)$key;
1576
    }
1577
1578 62
    if (\array_key_exists($key, $usedArray) === true) {
1579 52
      if (\is_array($usedArray[$key])) {
1580 6
        return static::create($usedArray[$key]);
1581
      }
1582
1583 48
      return $usedArray[$key];
1584
    }
1585
1586
    // Crawl through array, get key according to object or not
1587 21
    foreach (\explode($this->pathSeparator, (string)$key) as $segment) {
1588 21
      if (!isset($usedArray[$segment])) {
1589 20
        return $fallback instanceof \Closure ? $fallback() : $fallback;
1590
      }
1591
1592 6
      $usedArray = $usedArray[$segment];
1593
    }
1594
1595 6
    if (\is_array($usedArray)) {
1596 1
      return static::create($usedArray);
1597
    }
1598
1599 6
    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);
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 23
  public function has($key): bool
1800
  {
1801 23
    static $UN_FOUND = null;
1802
1803 23
    if ($UN_FOUND === null) {
1804
      // Generate unique string to use as marker.
1805 1
      $UN_FOUND = \uniqid('arrayy', true);
1806
    }
1807
1808 23
    return $this->get($key, $UN_FOUND) !== $UN_FOUND;
1809
  }
1810
1811
  /**
1812
   * Implodes the values of this array.
1813
   *
1814
   * @param string $glue
1815
   *
1816
   * @return string
1817
   */
1818 27
  public function implode(string $glue = ''): string
1819
  {
1820 27
    return $this->implode_recursive($glue, $this->array, false);
1821
  }
1822
1823
  /**
1824
   * Implodes the keys of this array.
1825
   *
1826
   * @param string $glue
1827
   *
1828
   * @return string
1829
   */
1830 8
  public function implodeKeys(string $glue = ''): string
1831
  {
1832 8
    return $this->implode_recursive($glue, $this->array, true);
1833
  }
1834
1835
  /**
1836
   * @param mixed               $glue
1837
   * @param string|array|static $pieces
1838
   * @param bool                $useKeys
1839
   *
1840
   * @return string
1841
   */
1842 35
  protected function implode_recursive($glue = '', $pieces = [], bool $useKeys = false): string
1843
  {
1844 35
    if ($pieces instanceof self) {
1845 1
      $pieces = $pieces->getArray();
1846
    }
1847
1848 35
    if (\is_array($pieces)) {
1849 35
      $pieces_count = \count($pieces, COUNT_NORMAL);
1850 35
      $pieces_count_not_zero = $pieces_count > 0;
1851
1852 35
      return \implode(
1853 35
          $glue,
1854 35
          \array_map(
1855 35
              [$this, 'implode_recursive'],
1856 35
              \array_fill(0, ($pieces_count_not_zero ? $pieces_count : 1), $glue),
1857 35
              ($useKeys === true && $pieces_count_not_zero ? $this->array_keys_recursive($pieces) : $pieces)
1858
          )
1859
      );
1860
    }
1861
1862 35
    return (string)$pieces;
1863
  }
1864
1865
  /**
1866
   * @param mixed $needle   <p>
1867
   *                        The searched value.
1868
   *                        </p>
1869
   *                        <p>
1870
   *                        If needle is a string, the comparison is done
1871
   *                        in a case-sensitive manner.
1872
   *                        </p>
1873
   * @param array $haystack <p>
1874
   *                        The array.
1875
   *                        </p>
1876
   * @param bool  $strict   [optional] <p>
1877
   *                        If the third parameter strict is set to true
1878
   *                        then the in_array function will also check the
1879
   *                        types of the
1880
   *                        needle in the haystack.
1881
   *                        </p>
1882
   *
1883
   * @return bool true if needle is found in the array, false otherwise.
1884
   */
1885 44
  protected function in_array_recursive($needle, array $haystack = null, $strict = true): bool
1886
  {
1887 44
    if ($haystack === null) {
1888
      $haystack = $this->array;
1889
    }
1890
1891 44
    foreach ($haystack as $item) {
1892
1893 36
      if (\is_array($item) === true) {
1894 8
        $returnTmp = $this->in_array_recursive($needle, $item, $strict);
1895
      } else {
1896 36
        $returnTmp = ($strict === true ? $item === $needle : $item == $needle);
1897
      }
1898
1899 36
      if ($returnTmp === true) {
1900 36
        return true;
1901
      }
1902
    }
1903
1904 18
    return false;
1905
  }
1906
1907
  /**
1908
   * Given a list and an iterate-function that returns
1909
   * a key for each element in the list (or a property name),
1910
   * returns an object with an index of each item.
1911
   *
1912
   * @param mixed $key
1913
   *
1914
   * @return static <p>(Immutable)</p>
1915
   */
1916 3
  public function indexBy($key)
1917
  {
1918 3
    $results = [];
1919
1920 3
    foreach ($this->array as $a) {
1921 3
      if (\array_key_exists($key, $a) === true) {
1922 3
        $results[$a[$key]] = $a;
1923
      }
1924
    }
1925
1926 3
    return static::create($results);
1927
  }
1928
1929
  /**
1930
   * alias: for "Arrayy->searchIndex()"
1931
   *
1932
   * @see Arrayy::searchIndex()
1933
   *
1934
   * @param mixed $value <p>The value to search for.</p>
1935
   *
1936
   * @return mixed
1937
   */
1938 4
  public function indexOf($value)
1939
  {
1940 4
    return $this->searchIndex($value);
1941
  }
1942
1943
  /**
1944
   * Get everything but the last..$to items.
1945
   *
1946
   * @param int $to
1947
   *
1948
   * @return static <p>(Immutable)</p>
1949
   */
1950 12
  public function initial(int $to = 1)
1951
  {
1952 12
    return $this->firstsImmutable(\count($this->array, COUNT_NORMAL) - $to);
1953
  }
1954
1955
  /**
1956
   * @param mixed $value
1957
   */
1958 476
  protected function internalGetArray(&$value)
1959
  {
1960 476
    if ($value instanceof self) {
1961
1962
      $valueTmp = $value->getArray();
1963
      if (\count($valueTmp, COUNT_NORMAL) === 0) {
1964
        $value = [];
1965
      } else {
1966
        /** @noinspection PhpUnusedLocalVariableInspection */
1967
        $value = &$valueTmp;
1968
      }
1969
1970 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...
1971
      /** @noinspection PhpUnusedLocalVariableInspection */
1972
      $value = &$value->jsonSerialize();
1973
    }
1974 476
  }
1975
1976
  /**
1977
   * Internal mechanics of remove method.
1978
   *
1979
   * @param mixed $key
1980
   *
1981
   * @return bool
1982
   */
1983 18
  protected function internalRemove($key): bool
1984
  {
1985 18
    $path = \explode($this->pathSeparator, (string)$key);
1986
1987
    // Crawl though the keys
1988 18
    while (\count($path, COUNT_NORMAL) > 1) {
1989
      $key = \array_shift($path);
1990
1991
      if (!$this->has($key)) {
1992
        return false;
1993
      }
1994
1995
      $this->array = &$this->array[$key];
1996
    }
1997
1998 18
    $key = \array_shift($path);
1999
2000 18
    unset($this->array[$key]);
2001
2002 18
    return true;
2003
  }
2004
2005
  /**
2006
   * Internal mechanic of set method.
2007
   *
2008
   * @param mixed $key
2009
   * @param mixed $value
2010
   *
2011
   * @return bool
2012
   */
2013 30
  protected function internalSet($key, $value): bool
2014
  {
2015 30
    if ($key === null) {
2016
      return false;
2017
    }
2018
2019
    // init
2020 30
    $array =& $this->array;
2021 30
    $path = \explode($this->pathSeparator, (string)$key);
2022
2023
    // Crawl through the keys
2024 30
    while (\count($path, COUNT_NORMAL) > 1) {
2025 3
      $key = \array_shift($path);
2026
2027
      // If the key doesn't exist at this depth, we will just create an empty array
2028
      // to hold the next value, allowing us to create the arrays to hold final
2029
      // values at the correct depth. Then we'll keep digging into the array.
2030 3
      if (!isset($array[$key]) || !\is_array($array[$key])) {
2031
        $array[$key] = static::create([]);
2032
      }
2033
2034 3
      $array =& $array[$key];
2035
    }
2036
2037 30
    $array[\array_shift($path)] = $value;
2038
2039 30
    return true;
2040
  }
2041
2042
  /**
2043
   * Return an array with all elements found in input array.
2044
   *
2045
   * @param array $search
2046
   *
2047
   * @return static <p>(Immutable)</p>
2048
   */
2049 2
  public function intersection(array $search)
2050
  {
2051 2
    return static::create(\array_values(\array_intersect($this->array, $search)));
2052
  }
2053
2054
  /**
2055
   * Return a boolean flag which indicates whether the two input arrays have any common elements.
2056
   *
2057
   * @param array $search
2058
   *
2059
   * @return bool
2060
   */
2061 1
  public function intersects(array $search): bool
2062
  {
2063 1
    return \count($this->intersection($search)->array, COUNT_NORMAL) > 0;
2064
  }
2065
2066
  /**
2067
   * Invoke a function on all of an array's values.
2068
   *
2069
   * @param mixed $callable
2070
   * @param mixed $arguments
2071
   *
2072
   * @return static <p>(Immutable)</p>
2073
   */
2074 1
  public function invoke($callable, $arguments = [])
2075
  {
2076
    // If one argument given for each iteration, create an array for it.
2077 1
    if (!\is_array($arguments)) {
2078 1
      $arguments = StaticArrayy::repeat(
2079 1
          $arguments,
2080 1
          \count($this->array, COUNT_NORMAL)
2081 1
      )->getArray();
2082
    }
2083
2084
    // If the callable has arguments, pass them.
2085 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...
2086 1
      $array = \array_map($callable, $this->array, $arguments);
2087
    } else {
2088 1
      $array = \array_map($callable, $this->array);
2089
    }
2090
2091 1
    return static::create($array);
2092
  }
2093
2094
  /**
2095
   * Check whether array is associative or not.
2096
   *
2097
   * @param bool $recursive
2098
   *
2099
   * @return bool <p>Returns true if associative, false otherwise.</p>
2100
   */
2101 15
  public function isAssoc(bool $recursive = false): bool
2102
  {
2103 15
    if ($this->isEmpty()) {
2104 3
      return false;
2105
    }
2106
2107 13
    foreach ($this->keys($recursive)->getArray() as $key) {
2108 13
      if (!\is_string($key)) {
2109 13
        return false;
2110
      }
2111
    }
2112
2113 3
    return true;
2114
  }
2115
2116
  /**
2117
   * Check whether the array is empty or not.
2118
   *
2119
   * @return bool <p>Returns true if empty, false otherwise.</p>
2120
   */
2121 88
  public function isEmpty(): bool
2122
  {
2123 88
    return !$this->array;
2124
  }
2125
2126
  /**
2127
   * Check if the current array is equal to the given "$array" or not.
2128
   *
2129
   * @param array $array
2130
   *
2131
   * @return bool
2132
   */
2133
  public function isEqual(array $array): bool
2134
  {
2135
    return ($this->array === $array);
2136
  }
2137
2138
  /**
2139
   * Check if the current array is a multi-array.
2140
   *
2141
   * @return bool
2142
   */
2143 14
  public function isMultiArray(): bool
2144
  {
2145
    return !(
2146 14
        \count($this->array, COUNT_NORMAL)
2147
        ===
2148 14
        \count($this->array, COUNT_RECURSIVE)
2149
    );
2150
  }
2151
2152
  /**
2153
   * Check whether array is numeric or not.
2154
   *
2155
   * @return bool <p>Returns true if numeric, false otherwise.</p>
2156
   */
2157 5
  public function isNumeric(): bool
2158
  {
2159 5
    if ($this->isEmpty()) {
2160 2
      return false;
2161
    }
2162
2163 4
    foreach ($this->keys() as $key) {
2164 4
      if (!\is_int($key)) {
2165 4
        return false;
2166
      }
2167
    }
2168
2169 2
    return true;
2170
  }
2171
2172
  /**
2173
   * Check if the current array is sequential [0, 1, 2, 3, 4, 5 ...] or not.
2174
   *
2175
   * @param bool $recursive
2176
   *
2177
   * @return bool
2178
   */
2179 1
  public function isSequential(bool $recursive = false): bool
2180
  {
2181
2182
    // recursive
2183
2184 1
    if ($recursive === true) {
2185
      return $this->array_keys_recursive($this->array)
2186
             ===
2187
             \range(0, \count($this->array, COUNT_RECURSIVE) - 1);
2188
    }
2189
2190
    // non recursive
2191
2192 1
    return \array_keys($this->array)
2193
           ===
2194 1
           \range(0, \count($this->array, COUNT_NORMAL) - 1);
2195
  }
2196
2197
  /**
2198
   * @return array
2199
   */
2200
  public function jsonSerialize(): array
2201
  {
2202
    return $this->getArray();
2203
  }
2204
2205
  /**
2206
   * Get all keys from the current array.
2207
   *
2208
   * @param bool  $recursive    [optional] <p>
2209
   *                            Get all keys, also from all sub-arrays from an multi-dimensional array.
2210
   *                            </p>
2211
   * @param mixed $search_value [optional] <p>
2212
   *                            If specified, then only keys containing these values are returned.
2213
   *                            </p>
2214
   * @param bool  $strict       [optional] <p>
2215
   *                            Determines if strict comparison (===) should be used during the search.
2216
   *                            </p>
2217
   *
2218
   * @return static <p>(Immutable) An array of all the keys in input.</p>
2219
   */
2220 26
  public function keys(bool $recursive = false, $search_value = null, bool $strict = true)
2221
  {
2222
2223
    // recursive
2224
2225 26
    if ($recursive === true) {
2226 3
      if ($search_value === null) {
2227 3
        $array = $this->array_keys_recursive($this->array);
2228
      } else {
2229
        $array = $this->array_keys_recursive($this->array, $search_value, $strict);
2230
      }
2231
2232 3
      return static::create($array);
2233
    }
2234
2235
    // non recursive
2236
2237 25
    if ($search_value === null) {
2238 25
      $array = \array_keys($this->array);
2239
    } else {
2240
      $array = \array_keys($this->array, $search_value, $strict);
2241
    }
2242
2243 25
    return static::create($array);
2244
  }
2245
2246
  /**
2247
   * Sort an array by key in reverse order.
2248
   *
2249
   * @param int $sort_flags [optional] <p>
2250
   *                        You may modify the behavior of the sort using the optional
2251
   *                        parameter sort_flags, for details
2252
   *                        see sort.
2253
   *                        </p>
2254
   *
2255
   * @return static <p>(Mutable) Return this Arrayy object.</p>
2256
   */
2257 4
  public function krsort(int $sort_flags = 0)
2258
  {
2259 4
    krsort($this->array, $sort_flags);
2260
2261 4
    return $this;
2262
  }
2263
2264
  /**
2265
   * Get the last value from the current array.
2266
   *
2267
   * @return mixed <p>Return null if there wasn't a element.</p>
2268
   */
2269 4
  public function last()
2270
  {
2271 4
    return $this->pop();
2272
  }
2273
2274
  /**
2275
   * Get the last value(s) from the current array.
2276
   *
2277
   * @param int|null $number
2278
   *
2279
   * @return static <p>(Immutable)</p>
2280
   */
2281 13
  public function lastsImmutable(int $number = null)
2282
  {
2283 13
    if ($this->isEmpty()) {
2284 1
      return static::create();
2285
    }
2286
2287 12
    if ($number === null) {
2288 8
      $poppedValue = $this->pop();
2289
2290 8
      if ($poppedValue === null) {
2291 1
        $poppedValue = [$poppedValue];
2292
      } else {
2293 7
        $poppedValue = (array)$poppedValue;
2294
      }
2295
2296 8
      $arrayy = static::create($poppedValue);
2297
    } else {
2298 4
      $number = (int)$number;
2299 4
      $arrayy = $this->rest(-$number);
2300
    }
2301
2302 12
    return $arrayy;
2303
  }
2304
2305
  /**
2306
   * Get the last value(s) from the current array.
2307
   *
2308
   * @param int|null $number
2309
   *
2310
   * @return static <p>(Mutable)</p>
2311
   */
2312 13
  public function lastsMutable(int $number = null)
2313
  {
2314 13
    if ($this->isEmpty()) {
2315 1
      return $this;
2316
    }
2317
2318 12
    if ($number === null) {
2319 8
      $poppedValue = $this->pop();
2320
2321 8
      if ($poppedValue === null) {
2322 1
        $poppedValue = [$poppedValue];
2323
      } else {
2324 7
        $poppedValue = (array)$poppedValue;
2325
      }
2326
2327 8
      $this->array = static::create($poppedValue)->array;
2328
    } else {
2329 4
      $number = (int)$number;
2330 4
      $this->array = $this->rest(-$number)->array;
2331
    }
2332
2333 12
    return $this;
2334
  }
2335
2336
  /**
2337
   * Count the values from the current array.
2338
   *
2339
   * alias: for "Arrayy->count()"
2340
   *
2341
   * @see Arrayy::count()
2342
   *
2343
   * @param int $mode
2344
   *
2345
   * @return int
2346
   */
2347 20
  public function length(int $mode = COUNT_NORMAL): int
2348
  {
2349 20
    return $this->count($mode);
2350
  }
2351
2352
  /**
2353
   * Apply the given function to the every element of the array,
2354
   * collecting the results.
2355
   *
2356
   * @param \callable $callable
2357
   *
2358
   * @return static <p>(Immutable) Arrayy object with modified elements.</p>
2359
   */
2360 4
  public function map($callable)
2361
  {
2362 4
    $result = \array_map($callable, $this->array);
2363
2364 4
    return static::create($result);
2365
  }
2366
2367
  /**
2368
   * Check if all items in current array match a truth test.
2369
   *
2370
   * @param \Closure $closure
2371
   *
2372
   * @return bool
2373
   */
2374 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...
2375
  {
2376 15
    if (\count($this->array, COUNT_NORMAL) === 0) {
2377 2
      return false;
2378
    }
2379
2380
    // init
2381 13
    $array = $this->array;
2382
2383 13
    foreach ($array as $key => $value) {
2384 13
      $value = $closure($value, $key);
2385
2386 13
      if ($value === false) {
2387 13
        return false;
2388
      }
2389
    }
2390
2391 7
    return true;
2392
  }
2393
2394
  /**
2395
   * Check if any item in the current array matches a truth test.
2396
   *
2397
   * @param \Closure $closure
2398
   *
2399
   * @return bool
2400
   */
2401 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...
2402
  {
2403 14
    if (\count($this->array, COUNT_NORMAL) === 0) {
2404 2
      return false;
2405
    }
2406
2407
    // init
2408 12
    $array = $this->array;
2409
2410 12
    foreach ($array as $key => $value) {
2411 12
      $value = $closure($value, $key);
2412
2413 12
      if ($value === true) {
2414 12
        return true;
2415
      }
2416
    }
2417
2418 4
    return false;
2419
  }
2420
2421
  /**
2422
   * Get the max value from an array.
2423
   *
2424
   * @return mixed
2425
   */
2426 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...
2427
  {
2428 10
    if (\count($this->array, COUNT_NORMAL) === 0) {
2429 1
      return false;
2430
    }
2431
2432 9
    return max($this->array);
2433
  }
2434
2435
  /**
2436
   * Merge the new $array into the current array.
2437
   *
2438
   * - keep key,value from the current array, also if the index is in the new $array
2439
   *
2440
   * @param array $array
2441
   * @param bool  $recursive
2442
   *
2443
   * @return static <p>(Immutable)</p>
2444
   */
2445 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...
2446
  {
2447 25
    if (true === $recursive) {
2448 4
      $result = \array_replace_recursive($this->array, $array);
2449
    } else {
2450 21
      $result = \array_replace($this->array, $array);
2451
    }
2452
2453 25
    return static::create($result);
2454
  }
2455
2456
  /**
2457
   * Merge the new $array into the current array.
2458
   *
2459
   * - replace duplicate assoc-keys from the current array with the key,values from the new $array
2460
   * - create new indexes
2461
   *
2462
   * @param array $array
2463
   * @param bool  $recursive
2464
   *
2465
   * @return static <p>(Immutable)</p>
2466
   */
2467 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...
2468
  {
2469 16
    if (true === $recursive) {
2470 4
      $result = \array_merge_recursive($this->array, $array);
2471
    } else {
2472 12
      $result = \array_merge($this->array, $array);
2473
    }
2474
2475 16
    return static::create($result);
2476
  }
2477
2478
  /**
2479
   * Merge the the current array into the $array.
2480
   *
2481
   * - use key,value from the new $array, also if the index is in the current array
2482
   *
2483
   * @param array $array
2484
   * @param bool  $recursive
2485
   *
2486
   * @return static <p>(Immutable)</p>
2487
   */
2488 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...
2489
  {
2490 16
    if (true === $recursive) {
2491 4
      $result = \array_replace_recursive($array, $this->array);
2492
    } else {
2493 12
      $result = \array_replace($array, $this->array);
2494
    }
2495
2496 16
    return static::create($result);
2497
  }
2498
2499
  /**
2500
   * Merge the current array into the new $array.
2501
   *
2502
   * - replace duplicate assoc-keys from new $array with the key,values from the current array
2503
   * - create new indexes
2504
   *
2505
   * @param array $array
2506
   * @param bool  $recursive
2507
   *
2508
   * @return static <p>(Immutable)</p>
2509
   */
2510 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...
2511
  {
2512 17
    if (true === $recursive) {
2513 4
      $result = \array_merge_recursive($array, $this->array);
2514
    } else {
2515 13
      $result = \array_merge($array, $this->array);
2516
    }
2517
2518 17
    return static::create($result);
2519
  }
2520
2521
  /**
2522
   * Get the min value from an array.
2523
   *
2524
   * @return mixed
2525
   */
2526 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...
2527
  {
2528 10
    if (\count($this->array, COUNT_NORMAL) === 0) {
2529 1
      return false;
2530
    }
2531
2532 9
    return min($this->array);
2533
  }
2534
2535
  /**
2536
   * Move an array element to a new index.
2537
   *
2538
   * cherry-picked from: http://stackoverflow.com/questions/12624153/move-an-array-element-to-a-new-index-in-php
2539
   *
2540
   * @param int|string $from
2541
   * @param int|string $to
2542
   *
2543
   * @return static <p>(Immutable)</p>
2544
   */
2545 1
  public function moveElement($from, $to)
2546
  {
2547 1
    $array = $this->array;
2548
2549 1
    if (\is_int($from)) {
2550 1
      $tmp = \array_splice($array, $from, 1);
2551 1
      \array_splice($array, $to, 0, $tmp);
2552 1
      $output = $array;
2553 1
    } elseif (\is_string($from)) {
2554 1
      $indexToMove = \array_search($from, \array_keys($array), true);
2555 1
      $itemToMove = $array[$from];
2556 1
      \array_splice($array, $indexToMove, 1);
2557 1
      $i = 0;
2558 1
      $output = [];
2559 1
      foreach ($array as $key => $item) {
2560 1
        if ($i == $to) {
2561 1
          $output[$from] = $itemToMove;
2562
        }
2563 1
        $output[$key] = $item;
2564 1
        $i++;
2565
      }
2566
    } else {
2567
      $output = [];
2568
    }
2569
2570 1
    return static::create($output);
2571
  }
2572
2573
  /**
2574
   * Convert a object into an array.
2575
   *
2576
   * @param object $object
2577
   *
2578
   * @return mixed
2579
   */
2580 5
  protected static function objectToArray($object)
2581
  {
2582 5
    if (!\is_object($object)) {
2583 4
      return $object;
2584
    }
2585
2586 5
    if (\is_object($object)) {
2587 5
      $object = \get_object_vars($object);
2588
    }
2589
2590 5
    return \array_map(['self', 'objectToArray'], $object);
2591
  }
2592
2593
  /**
2594
   * Get a subset of the items from the given array.
2595
   *
2596
   * @param mixed[] $keys
2597
   *
2598
   * @return static <p>(Immutable)</p>
2599
   */
2600
  public function only(array $keys)
2601
  {
2602
    $array = $this->array;
2603
2604
    return static::create(\array_intersect_key($array, \array_flip($keys)));
2605
  }
2606
2607
  /**
2608
   * Pad array to the specified size with a given value.
2609
   *
2610
   * @param int   $size  <p>Size of the result array.</p>
2611
   * @param mixed $value <p>Empty value by default.</p>
2612
   *
2613
   * @return static <p>(Immutable) Arrayy object padded to $size with $value.</p>
2614
   */
2615 4
  public function pad(int $size, $value)
2616
  {
2617 4
    $result = \array_pad($this->array, $size, $value);
2618
2619 4
    return static::create($result);
2620
  }
2621
2622
  /**
2623
   * Pop a specified value off the end of the current array.
2624
   *
2625
   * @return mixed <p>(Mutable) The popped element from the current array.</p>
2626
   */
2627 16
  public function pop()
2628
  {
2629 16
    return \array_pop($this->array);
2630
  }
2631
2632
  /**
2633
   * Prepend a (key) + value to the current array.
2634
   *
2635
   * @param mixed $value
2636
   * @param mixed $key
2637
   *
2638
   * @return static <p>(Mutable) Return this Arrayy object, with the prepended value.</p>
2639
   */
2640 8
  public function prepend($value, $key = null)
2641
  {
2642 8
    if ($key === null) {
2643 8
      \array_unshift($this->array, $value);
2644
    } else {
2645
      /** @noinspection AdditionOperationOnArraysInspection */
2646 1
      $this->array = [$key => $value] + $this->array;
2647
    }
2648
2649 8
    return $this;
2650
  }
2651
2652
  /**
2653
   * Add a suffix to each key.
2654
   *
2655
   * @param mixed $suffix
2656
   *
2657
   * @return static <p>(Immutable) Return an Arrayy object, with the prepended keys.</p>
2658
   */
2659 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...
2660
  {
2661 10
    $result = [];
2662 10
    foreach ($this->array as $key => $item) {
2663 9
      if ($item instanceof self) {
2664
        $result[$key] = $item->prependToEachKey($suffix);
2665 9
      } elseif (\is_array($item)) {
2666
        $result[$key] = self::create($item)->prependToEachKey($suffix)->toArray();
2667
      } else {
2668 9
        $result[$key . $suffix] = $item;
2669
      }
2670
2671
    }
2672
2673 10
    return self::create($result);
2674
  }
2675
2676
  /**
2677
   * Add a suffix to each value.
2678
   *
2679
   * @param mixed $suffix
2680
   *
2681
   * @return static <p>(Immutable) Return an Arrayy object, with the prepended values.</p>
2682
   */
2683 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...
2684
  {
2685 10
    $result = [];
2686 10
    foreach ($this->array as $key => $item) {
2687 9
      if ($item instanceof self) {
2688
        $result[$key] = $item->prependToEachValue($suffix);
2689 9
      } elseif (\is_array($item)) {
2690
        $result[$key] = self::create($item)->prependToEachValue($suffix)->toArray();
2691 9
      } elseif (\is_object($item)) {
2692 1
        $result[$key] = $item;
2693
      } else {
2694 9
        $result[$key] = $item . $suffix;
2695
      }
2696
    }
2697
2698 10
    return self::create($result);
2699
  }
2700
2701
  /**
2702
   * Push one or more values onto the end of array at once.
2703
   *
2704
   * @return static <p>(Mutable) Return this Arrayy object, with pushed elements to the end of array.</p>
2705
   */
2706 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...
2707
  {
2708 4
    if (\func_num_args()) {
2709 4
      $args = \array_merge([&$this->array], \func_get_args());
2710 4
      \array_push(...$args);
2711
    }
2712
2713 4
    return $this;
2714
  }
2715
2716
  /**
2717
   * Get a random value from the current array.
2718
   *
2719
   * @param null|int $number <p>How many values you will take?</p>
2720
   *
2721
   * @return static <p>(Immutable)</p>
2722
   */
2723 18
  public function randomImmutable(int $number = null)
2724
  {
2725 18
    if (\count($this->array, COUNT_NORMAL) === 0) {
2726 1
      return static::create();
2727
    }
2728
2729 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...
2730 14
      $arrayRandValue = [$this->array[\array_rand($this->array)]];
2731
2732 14
      return static::create($arrayRandValue);
2733
    }
2734
2735 5
    $arrayTmp = $this->array;
2736 5
    \shuffle($arrayTmp);
2737
2738 5
    return static::create($arrayTmp)->firstsImmutable($number);
2739
  }
2740
2741
  /**
2742
   * Pick a random key/index from the keys of this array.
2743
   *
2744
   * @return mixed <p>Get a key/index or null if there wasn't a key/index.</p>
2745
   *
2746
   * @throws \RangeException If array is empty
2747
   */
2748 4
  public function randomKey()
2749
  {
2750 4
    $result = $this->randomKeys(1);
2751
2752 4
    if (!isset($result[0])) {
2753
      $result[0] = null;
2754
    }
2755
2756 4
    return $result[0];
2757
  }
2758
2759
  /**
2760
   * Pick a given number of random keys/indexes out of this array.
2761
   *
2762
   * @param int $number <p>The number of keys/indexes (should be <= \count($this->array))</p>
2763
   *
2764
   * @return static <p>(Immutable)</p>
2765
   *
2766
   * @throws \RangeException If array is empty
2767
   */
2768 13
  public function randomKeys(int $number)
2769
  {
2770 13
    $count = \count($this->array, COUNT_NORMAL);
2771
2772 13
    if ($number === 0 || $number > $count) {
2773 2
      throw new \RangeException(
2774 2
          \sprintf(
2775 2
              'Number of requested keys (%s) must be equal or lower than number of elements in this array (%s)',
2776 2
              $number,
2777 2
              $count
2778
          )
2779
      );
2780
    }
2781
2782 11
    $result = (array)\array_rand($this->array, $number);
2783
2784 11
    return static::create($result);
2785
  }
2786
2787
  /**
2788
   * Get a random value from the current array.
2789
   *
2790
   * @param null|int $number <p>How many values you will take?</p>
2791
   *
2792
   * @return static <p>(Mutable)</p>
2793
   */
2794 17
  public function randomMutable(int $number = null)
2795
  {
2796 17
    if (\count($this->array, COUNT_NORMAL) === 0) {
2797
      return static::create();
2798
    }
2799
2800 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...
2801 7
      $arrayRandValue = [$this->array[\array_rand($this->array)]];
2802 7
      $this->array = $arrayRandValue;
2803
2804 7
      return $this;
2805
    }
2806
2807 11
    \shuffle($this->array);
2808
2809 11
    return $this->firstsMutable($number);
2810
  }
2811
2812
  /**
2813
   * Pick a random value from the values of this array.
2814
   *
2815
   * @return mixed <p>Get a random value or null if there wasn't a value.</p>
2816
   */
2817 4
  public function randomValue()
2818
  {
2819 4
    $result = $this->randomImmutable();
2820
2821 4
    if (!isset($result[0])) {
2822
      $result[0] = null;
2823
    }
2824
2825 4
    return $result[0];
2826
  }
2827
2828
  /**
2829
   * Pick a given number of random values out of this array.
2830
   *
2831
   * @param int $number
2832
   *
2833
   * @return static <p>(Mutable)</p>
2834
   */
2835 7
  public function randomValues(int $number)
2836
  {
2837 7
    return $this->randomMutable($number);
2838
  }
2839
2840
  /**
2841
   * Get a random value from an array, with the ability to skew the results.
2842
   *
2843
   * Example: randomWeighted(['foo' => 1, 'bar' => 2]) has a 66% chance of returning bar.
2844
   *
2845
   * @param array    $array
2846
   * @param null|int $number <p>How many values you will take?</p>
2847
   *
2848
   * @return static <p>(Immutable)</p>
2849
   */
2850 9
  public function randomWeighted(array $array, int $number = null)
2851
  {
2852 9
    $options = [];
2853 9
    foreach ($array as $option => $weight) {
2854 9
      if ($this->searchIndex($option) !== false) {
2855 9
        for ($i = 0; $i < $weight; ++$i) {
2856 1
          $options[] = $option;
2857
        }
2858
      }
2859
    }
2860
2861 9
    return $this->mergeAppendKeepIndex($options)->randomImmutable($number);
2862
  }
2863
2864
  /**
2865
   * Reduce the current array via callable e.g. anonymous-function.
2866
   *
2867
   * @param \callable $callable
2868
   * @param array     $init
2869
   *
2870
   * @return static <p>(Immutable)</p>
2871
   */
2872 4
  public function reduce($callable, array $init = [])
2873
  {
2874 4
    $result = \array_reduce($this->array, $callable, $init);
2875
2876 4
    if ($result === null) {
2877
      $this->array = [];
2878
    } else {
2879 4
      $this->array = (array)$result;
2880
    }
2881
2882 4
    return static::create($this->array);
2883
  }
2884
2885
  /**
2886
   * Create a numerically re-indexed Arrayy object.
2887
   *
2888
   * @return static <p>(Mutable) Return this Arrayy object, with re-indexed array-elements.</p>
2889
   */
2890 9
  public function reindex()
2891
  {
2892 9
    $this->array = \array_values($this->array);
2893
2894 9
    return $this;
2895
  }
2896
2897
  /**
2898
   * Return all items that fail the truth test.
2899
   *
2900
   * @param \Closure $closure
2901
   *
2902
   * @return static <p>(Immutable)</p>
2903
   */
2904 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...
2905
  {
2906 1
    $filtered = [];
2907
2908 1
    foreach ($this->array as $key => $value) {
2909 1
      if (!$closure($value, $key)) {
2910 1
        $filtered[$key] = $value;
2911
      }
2912
    }
2913
2914 1
    return static::create($filtered);
2915
  }
2916
2917
  /**
2918
   * Remove a value from the current array (optional using dot-notation).
2919
   *
2920
   * @param mixed $key
2921
   *
2922
   * @return static <p>(Immutable)</p>
2923
   */
2924 18
  public function remove($key)
2925
  {
2926
    // recursive call
2927 18
    if (\is_array($key)) {
2928
      foreach ($key as $k) {
2929
        $this->internalRemove($k);
2930
      }
2931
2932
      return static::create($this->array);
2933
    }
2934
2935 18
    $this->internalRemove($key);
2936
2937 18
    return static::create($this->array);
2938
  }
2939
2940
  /**
2941
   * Remove the first value from the current array.
2942
   *
2943
   * @return static <p>(Immutable)</p>
2944
   */
2945 7
  public function removeFirst()
2946
  {
2947 7
    $tmpArray = $this->array;
2948 7
    \array_shift($tmpArray);
2949
2950 7
    return static::create($tmpArray);
2951
  }
2952
2953
  /**
2954
   * Remove the last value from the current array.
2955
   *
2956
   * @return static <p>(Immutable)</p>
2957
   */
2958 7
  public function removeLast()
2959
  {
2960 7
    $tmpArray = $this->array;
2961 7
    \array_pop($tmpArray);
2962
2963 7
    return static::create($tmpArray);
2964
  }
2965
2966
  /**
2967
   * Removes a particular value from an array (numeric or associative).
2968
   *
2969
   * @param mixed $value
2970
   *
2971
   * @return static <p>(Immutable)</p>
2972
   */
2973 7
  public function removeValue($value)
2974
  {
2975 7
    $isNumericArray = true;
2976 7
    foreach ($this->array as $key => $item) {
2977 6
      if ($item === $value) {
2978 6
        if (!\is_int($key)) {
2979
          $isNumericArray = false;
2980
        }
2981 6
        unset($this->array[$key]);
2982
      }
2983
    }
2984
2985 7
    if ($isNumericArray) {
2986 7
      $this->array = \array_values($this->array);
2987
    }
2988
2989 7
    return static::create($this->array);
2990
  }
2991
2992
  /**
2993
   * Generate array of repeated arrays.
2994
   *
2995
   * @param int $times <p>How many times has to be repeated.</p>
2996
   *
2997
   * @return Arrayy
2998
   */
2999 1
  public function repeat($times): self
3000
  {
3001 1
    if ($times === 0) {
3002 1
      return new static();
3003
    }
3004
3005 1
    return static::create(\array_fill(0, (int)$times, $this->array));
3006
  }
3007
3008
  /**
3009
   * Replace a key with a new key/value pair.
3010
   *
3011
   * @param mixed $replace
3012
   * @param mixed $key
3013
   * @param mixed $value
3014
   *
3015
   * @return static <p>(Immutable)</p>
3016
   */
3017 2
  public function replace($replace, $key, $value)
3018
  {
3019 2
    $this->remove($replace);
3020
3021 2
    return $this->set($key, $value);
3022
  }
3023
3024
  /**
3025
   * Create an array using the current array as values and the other array as keys.
3026
   *
3027
   * @param array $keys <p>An array of keys.</p>
3028
   *
3029
   * @return static <p>(Immutable) Arrayy object with keys from the other array.</p>
3030
   */
3031 2
  public function replaceAllKeys(array $keys)
3032
  {
3033 2
    $result = \array_combine($keys, $this->array);
3034
3035 2
    return static::create($result);
3036
  }
3037
3038
  /**
3039
   * Create an array using the current array as keys and the other array as values.
3040
   *
3041
   * @param array $array <p>An array o values.</p>
3042
   *
3043
   * @return static <p>(Immutable) Arrayy object with values from the other array.</p>
3044
   */
3045 2
  public function replaceAllValues(array $array)
3046
  {
3047 2
    $result = \array_combine($this->array, $array);
3048
3049 2
    return static::create($result);
3050
  }
3051
3052
  /**
3053
   * Replace the keys in an array with another set.
3054
   *
3055
   * @param array $keys <p>An array of keys matching the array's size</p>
3056
   *
3057
   * @return static <p>(Immutable)</p>
3058
   */
3059 1
  public function replaceKeys(array $keys)
3060
  {
3061 1
    $values = \array_values($this->array);
3062 1
    $result = \array_combine($keys, $values);
3063
3064 1
    return static::create($result);
3065
  }
3066
3067
  /**
3068
   * Replace the first matched value in an array.
3069
   *
3070
   * @param mixed $search      <p>The value to replace.</p>
3071
   * @param mixed $replacement <p>The value to replace.</p>
3072
   *
3073
   * @return static <p>(Immutable)</p>
3074
   */
3075 3
  public function replaceOneValue($search, $replacement = '')
3076
  {
3077 3
    $array = $this->array;
3078 3
    $key = \array_search($search, $array, true);
3079
3080 3
    if ($key !== false) {
3081 3
      $array[$key] = $replacement;
3082
    }
3083
3084 3
    return static::create($array);
3085
  }
3086
3087
  /**
3088
   * Replace values in the current array.
3089
   *
3090
   * @param mixed $search      <p>The value to replace.</p>
3091
   * @param mixed $replacement <p>What to replace it with.</p>
3092
   *
3093
   * @return static <p>(Immutable)</p>
3094
   */
3095 1
  public function replaceValues($search, $replacement = '')
3096
  {
3097 1
    $array = $this->each(
3098 1
        function ($value) use ($search, $replacement) {
3099 1
          return UTF8::str_replace($search, $replacement, $value);
3100 1
        }
3101
    );
3102
3103 1
    return $array;
3104
  }
3105
3106
  /**
3107
   * Get the last elements from index $from until the end of this array.
3108
   *
3109
   * @param int $from
3110
   *
3111
   * @return static <p>(Immutable)</p>
3112
   */
3113 15
  public function rest(int $from = 1)
3114
  {
3115 15
    $tmpArray = $this->array;
3116
3117 15
    return static::create(\array_splice($tmpArray, $from));
3118
  }
3119
3120
  /**
3121
   * Return the array in the reverse order.
3122
   *
3123
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3124
   */
3125 8
  public function reverse()
3126
  {
3127 8
    $this->array = \array_reverse($this->array);
3128
3129 8
    return $this;
3130
  }
3131
3132
  /**
3133
   * Sort an array in reverse order.
3134
   *
3135
   * @param int $sort_flags [optional] <p>
3136
   *                        You may modify the behavior of the sort using the optional
3137
   *                        parameter sort_flags, for details
3138
   *                        see sort.
3139
   *                        </p>
3140
   *
3141
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3142
   */
3143 4
  public function rsort(int $sort_flags = 0)
3144
  {
3145 4
    \rsort($this->array, $sort_flags);
3146
3147 4
    return $this;
3148
  }
3149
3150
  /**
3151
   * Search for the first index of the current array via $value.
3152
   *
3153
   * @param mixed $value
3154
   *
3155
   * @return int|float|string
3156
   */
3157 20
  public function searchIndex($value)
3158
  {
3159 20
    return \array_search($value, $this->array, true);
3160
  }
3161
3162
  /**
3163
   * Search for the value of the current array via $index.
3164
   *
3165
   * @param mixed $index
3166
   *
3167
   * @return static <p>(Immutable) Will return a empty Arrayy if the value wasn't found.</p>
3168
   */
3169 9
  public function searchValue($index)
3170
  {
3171
    // init
3172 9
    $return = [];
3173
3174 9
    if ($this->isEmpty()) {
3175
      return static::create();
3176
    }
3177
3178
    // php cast "bool"-index into "int"-index
3179 9
    if ((bool)$index === $index) {
3180 1
      $index = (int)$index;
3181
    }
3182
3183 9
    if (\array_key_exists($index, $this->array) === true) {
3184 7
      $return = [$this->array[$index]];
3185
    }
3186
3187
3188 9
    return static::create($return);
3189
  }
3190
3191
  /**
3192
   * Set a value for the current array (optional using dot-notation).
3193
   *
3194
   * @param mixed $key   <p>The key to set.</p>
3195
   * @param mixed $value <p>Its value.</p>
3196
   *
3197
   * @return static <p>(Immutable)</p>
3198
   */
3199 17
  public function set($key, $value)
3200
  {
3201 17
    $this->internalSet($key, $value);
3202
3203 17
    return static::create($this->array);
3204
  }
3205
3206
  /**
3207
   * Get a value from a array and set it if it was not.
3208
   *
3209
   * WARNING: this method only set the value, if the $key is not already set
3210
   *
3211
   * @param mixed $key      <p>The key</p>
3212
   * @param mixed $fallback <p>The default value to set if it isn't.</p>
3213
   *
3214
   * @return mixed <p>(Mutable)</p>
3215
   */
3216 11
  public function setAndGet($key, $fallback = null)
3217
  {
3218
    // If the key doesn't exist, set it.
3219 11
    if (!$this->has($key)) {
3220 4
      $this->array = $this->set($key, $fallback)->getArray();
3221
    }
3222
3223 11
    return $this->get($key);
3224
  }
3225
3226
  /**
3227
   * Shifts a specified value off the beginning of array.
3228
   *
3229
   * @return mixed <p>(Mutable) A shifted element from the current array.</p>
3230
   */
3231 4
  public function shift()
3232
  {
3233 4
    return \array_shift($this->array);
3234
  }
3235
3236
  /**
3237
   * Shuffle the current array.
3238
   *
3239
   * @param bool  $secure <p>using a CSPRNG | @link https://paragonie.com/b/JvICXzh_jhLyt4y3</p>
3240
   * @param array $array  [optional]
3241
   *
3242
   * @return static <p>(Immutable)</p>
3243
   */
3244 1
  public function shuffle(bool $secure = false, array $array = null)
3245
  {
3246 1
    if ($array === null) {
3247 1
      $array = $this->array;
3248
    }
3249
3250 1
    if ($secure !== true) {
3251 1
      \shuffle($array);
3252
    } else {
3253 1
      $size = \count($array, COUNT_NORMAL);
3254 1
      $keys = \array_keys($array);
3255 1
      for ($i = $size - 1; $i > 0; --$i) {
3256
        try {
3257 1
          $r = \random_int(0, $i);
3258
        } catch (\Exception $e) {
3259
          $r = \mt_rand();
3260
        }
3261 1
        if ($r !== $i) {
3262 1
          $temp = $array[$keys[$r]];
3263 1
          $array[$keys[$r]] = $array[$keys[$i]];
3264 1
          $array[$keys[$i]] = $temp;
3265
        }
3266
      }
3267
3268
      // reset indices
3269 1
      $array = \array_values($array);
3270
    }
3271
3272 1
    foreach ($array as $key => $value) {
3273
      // check if recursive is needed
3274 1
      if (\is_array($value) === true) {
3275 1
        $array[$key] = $this->shuffle($secure, $value);
3276
      }
3277
    }
3278
3279 1
    return static::create($array);
3280
  }
3281
3282
  /**
3283
   * Count the values from the current array.
3284
   *
3285
   * alias: for "Arrayy->count()"
3286
   *
3287
   * @param int $mode
3288
   *
3289
   * @return int
3290
   */
3291 20
  public function size(int $mode = COUNT_NORMAL): int
3292
  {
3293 20
    return $this->count($mode);
3294
  }
3295
3296
  /**
3297
   * Counts all elements in an array, or something in an object.
3298
   * <p>For objects, if you have SPL installed, you can hook into count() by implementing interface {@see Countable}.
3299
   * The interface has exactly one method, {@see Countable::count()}, which returns the return value for the count()
3300
   * function. Please see the {@see Array} section of the manual for a detailed explanation of how arrays are
3301
   * implemented and used in PHP.
3302
   *
3303
   * @return int the number of elements in var, which is
3304
   * typically an array, since anything else will have one
3305
   * element.
3306
   * </p>
3307
   * <p>
3308
   * If var is not an array or an object with
3309
   * implemented Countable interface,
3310
   * 1 will be returned.
3311
   * There is one exception, if var is &null;,
3312
   * 0 will be returned.
3313
   * </p>
3314
   * <p>
3315
   * Caution: count may return 0 for a variable that isn't set,
3316
   * but it may also return 0 for a variable that has been initialized with an
3317
   * empty array. Use isset to test if a variable is set.
3318
   *
3319
   * @return int
3320
   */
3321 10
  public function sizeRecursive(): int
3322
  {
3323 10
    return \count($this->array, COUNT_RECURSIVE);
3324
  }
3325
3326
  /**
3327
   * Extract a slice of the array.
3328
   *
3329
   * @param int      $offset       <p>Slice begin index.</p>
3330
   * @param int|null $length       <p>Length of the slice.</p>
3331
   * @param bool     $preserveKeys <p>Whether array keys are preserved or no.</p>
3332
   *
3333
   * @return static <p>A slice of the original array with length $length.</p>
3334
   */
3335 4
  public function slice(int $offset, int $length = null, bool $preserveKeys = false)
3336
  {
3337 4
    $result = \array_slice($this->array, $offset, $length, $preserveKeys);
3338
3339 4
    return static::create($result);
3340
  }
3341
3342
  /**
3343
   * Sort the current array and optional you can keep the keys.
3344
   *
3345
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3346
   * @param int        $strategy  <p>sort_flags => use e.g.: <strong>SORT_REGULAR</strong> (default) or
3347
   *                              <strong>SORT_NATURAL</strong></p>
3348
   * @param bool       $keepKeys
3349
   *
3350
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3351
   */
3352 19
  public function sort($direction = SORT_ASC, int $strategy = SORT_REGULAR, bool $keepKeys = false)
3353
  {
3354 19
    $this->sorting($this->array, $direction, $strategy, $keepKeys);
3355
3356 19
    return $this;
3357
  }
3358
3359
  /**
3360
   * Sort the current array by key.
3361
   *
3362
   * @link http://php.net/manual/en/function.ksort.php
3363
   * @link http://php.net/manual/en/function.krsort.php
3364
   *
3365
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3366
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3367
   *                              <strong>SORT_NATURAL</strong></p>
3368
   *
3369
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3370
   */
3371 18
  public function sortKeys($direction = SORT_ASC, int $strategy = SORT_REGULAR)
3372
  {
3373 18
    $this->sorterKeys($this->array, $direction, $strategy);
3374
3375 18
    return $this;
3376
  }
3377
3378
  /**
3379
   * Sort the current array by value.
3380
   *
3381
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3382
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3383
   *                              <strong>SORT_NATURAL</strong></p>
3384
   *
3385
   * @return static <p>(Mutable)</p>
3386
   */
3387 1
  public function sortValueKeepIndex($direction = SORT_ASC, int $strategy = SORT_REGULAR)
3388
  {
3389 1
    return $this->sort($direction, $strategy, true);
3390
  }
3391
3392
  /**
3393
   * Sort the current array by value.
3394
   *
3395
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3396
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3397
   *                              <strong>SORT_NATURAL</strong></p>
3398
   *
3399
   * @return static <p>(Mutable)</p>
3400
   */
3401 1
  public function sortValueNewIndex($direction = SORT_ASC, int $strategy = SORT_REGULAR)
3402
  {
3403 1
    return $this->sort($direction, $strategy, false);
3404
  }
3405
3406
  /**
3407
   * Sort a array by value, by a closure or by a property.
3408
   *
3409
   * - If the sorter is null, the array is sorted naturally.
3410
   * - Associative (string) keys will be maintained, but numeric keys will be re-indexed.
3411
   *
3412
   * @param \callable|null $sorter
3413
   * @param string|int     $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3414
   * @param int            $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3415
   *                                  <strong>SORT_NATURAL</strong></p>
3416
   *
3417
   * @return static <p>(Immutable)</p>
3418
   */
3419 1
  public function sorter($sorter = null, $direction = SORT_ASC, int $strategy = SORT_REGULAR)
3420
  {
3421 1
    $array = (array)$this->array;
3422 1
    $direction = $this->getDirection($direction);
3423
3424
    // Transform all values into their results.
3425 1
    if ($sorter) {
3426 1
      $arrayy = static::create($array);
3427
3428 1
      $that = $this;
3429 1
      $results = $arrayy->each(
3430 1
          function ($value) use ($sorter, $that) {
3431 1
            return \is_callable($sorter) ? $sorter($value) : $that->get($sorter, null, $value);
3432 1
          }
3433
      );
3434
3435 1
      $results = $results->getArray();
3436
    } else {
3437 1
      $results = $array;
3438
    }
3439
3440
    // Sort by the results and replace by original values
3441 1
    \array_multisort($results, $direction, $strategy, $array);
3442
3443 1
    return static::create($array);
3444
  }
3445
3446
  /**
3447
   * sorting keys
3448
   *
3449
   * @param array      $elements
3450
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3451
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3452
   *                              <strong>SORT_NATURAL</strong></p>
3453
   *
3454
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3455
   */
3456 18
  protected function sorterKeys(array &$elements, $direction = SORT_ASC, int $strategy = SORT_REGULAR)
3457
  {
3458 18
    $direction = $this->getDirection($direction);
3459
3460
    switch ($direction) {
3461 18
      case 'desc':
3462 18
      case SORT_DESC:
3463 6
        \krsort($elements, $strategy);
3464 6
        break;
3465 13
      case 'asc':
3466 13
      case SORT_ASC:
3467
      default:
3468 13
        \ksort($elements, $strategy);
3469
    }
3470
3471 18
    return $this;
3472
  }
3473
3474
  /**
3475
   * @param array      &$elements
3476
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3477
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3478
   *                              <strong>SORT_NATURAL</strong></p>
3479
   * @param bool       $keepKeys
3480
   *
3481
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3482
   */
3483 19
  protected function sorting(array &$elements, $direction = SORT_ASC, int $strategy = SORT_REGULAR, bool $keepKeys = false)
3484
  {
3485 19
    $direction = $this->getDirection($direction);
3486
3487 19
    if (!$strategy) {
3488 19
      $strategy = SORT_REGULAR;
3489
    }
3490
3491
    switch ($direction) {
3492 19
      case 'desc':
3493 19
      case SORT_DESC:
3494 9
        if ($keepKeys) {
3495 5
          arsort($elements, $strategy);
3496
        } else {
3497 4
          \rsort($elements, $strategy);
3498
        }
3499 9
        break;
3500 10
      case 'asc':
3501 10
      case SORT_ASC:
3502
      default:
3503 10
        if ($keepKeys) {
3504 4
          \asort($elements, $strategy);
3505
        } else {
3506 6
          \sort($elements, $strategy);
3507
        }
3508
    }
3509
3510 19
    return $this;
3511
  }
3512
3513
  /**
3514
   * Split an array in the given amount of pieces.
3515
   *
3516
   * @param int  $numberOfPieces
3517
   * @param bool $keepKeys
3518
   *
3519
   * @return static <p>(Immutable)</p>
3520
   */
3521 1
  public function split(int $numberOfPieces = 2, bool $keepKeys = false)
3522
  {
3523 1
    $arrayCount = \count($this->array, COUNT_NORMAL);
3524
3525 1
    if ($arrayCount === 0) {
3526 1
      $result = [];
3527
    } else {
3528 1
      $splitSize = (int)\ceil($arrayCount / $numberOfPieces);
3529 1
      $result = \array_chunk($this->array, $splitSize, $keepKeys);
3530
    }
3531
3532 1
    return static::create($result);
3533
  }
3534
3535
  /**
3536
   * Stripe all empty items.
3537
   *
3538
   * @return static <p>(Immutable)</p>
3539
   */
3540 1
  public function stripEmpty()
3541
  {
3542 1
    return $this->filter(
3543 1
        function ($item) {
3544 1
          if ($item === null) {
3545 1
            return false;
3546
          }
3547
3548 1
          return (bool)\trim((string)$item);
3549 1
        }
3550
    );
3551
  }
3552
3553
  /**
3554
   * Swap two values between positions by key.
3555
   *
3556
   * @param string|int $swapA <p>a key in the array</p>
3557
   * @param string|int $swapB <p>a key in the array</p>
3558
   *
3559
   * @return static <p>(Immutable)</p>
3560
   */
3561 1
  public function swap($swapA, $swapB)
3562
  {
3563 1
    $array = $this->array;
3564
3565 1
    list($array[$swapA], $array[$swapB]) = [$array[$swapB], $array[$swapA]];
3566
3567 1
    return static::create($array);
3568
  }
3569
3570
  /**
3571
   * alias: for "Arrayy->getArray()"
3572
   *
3573
   * @see Arrayy::getArray()
3574
   */
3575 186
  public function toArray()
3576
  {
3577 186
    return $this->getArray();
3578
  }
3579
3580
  /**
3581
   * Convert the current array to JSON.
3582
   *
3583
   * @param int $options [optional] <p>e.g. JSON_PRETTY_PRINT</p>
3584
   * @param int $depth   [optional] <p>Set the maximum depth. Must be greater than zero.</p>
3585
   *
3586
   * @return string
3587
   */
3588 6
  public function toJson(int $options = 0, int $depth = 512): string
3589
  {
3590 6
    return UTF8::json_encode($this->array, $options, $depth);
3591
  }
3592
3593
  /**
3594
   * Implodes array to a string with specified separator.
3595
   *
3596
   * @param string $separator [optional] <p>The element's separator.</p>
3597
   *
3598
   * @return string <p>The string representation of array, separated by ",".</p>
3599
   */
3600 19
  public function toString(string $separator = ','): string
3601
  {
3602 19
    return $this->implode($separator);
3603
  }
3604
3605
  /**
3606
   * Return a duplicate free copy of the current array.
3607
   *
3608
   * @return static <p>(Mutable)</p>
3609
   */
3610 9
  public function unique()
3611
  {
3612
    // INFO: \array_unique() can't handle e.g. "stdClass"-values in an array
3613
3614 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...
3615 9
        $this->array,
3616 9
        function ($resultArray, $value) {
3617 8
          if (!\in_array($value, $resultArray, true)) {
3618 8
            $resultArray[] = $value;
3619
          }
3620
3621 8
          return $resultArray;
3622 9
        },
3623 9
        []
3624
    );
3625
3626 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...
3627
      $this->array = [];
3628
    } else {
3629 9
      $this->array = (array)$this->array;
3630
    }
3631
3632 9
    return $this;
3633
  }
3634
3635
  /**
3636
   * Return a duplicate free copy of the current array. (with the old keys)
3637
   *
3638
   * @return static <p>(Mutable)</p>
3639
   */
3640 9
  public function uniqueKeepIndex()
3641
  {
3642
    // INFO: \array_unique() can't handle e.g. "stdClass"-values in an array
3643
3644
    // init
3645 9
    $array = $this->array;
3646
3647 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...
3648 9
        \array_keys($array),
3649 9
        function ($resultArray, $key) use ($array) {
3650 8
          if (!\in_array($array[$key], $resultArray, true)) {
3651 8
            $resultArray[$key] = $array[$key];
3652
          }
3653
3654 8
          return $resultArray;
3655 9
        },
3656 9
        []
3657
    );
3658
3659 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...
3660
      $this->array = [];
3661
    } else {
3662 9
      $this->array = (array)$this->array;
3663
    }
3664
3665 9
    return $this;
3666
  }
3667
3668
  /**
3669
   * alias: for "Arrayy->unique()"
3670
   *
3671
   * @see Arrayy::unique()
3672
   *
3673
   * @return static <p>(Mutable) Return this Arrayy object, with the appended values.</p>
3674
   */
3675 9
  public function uniqueNewIndex()
3676
  {
3677 9
    return $this->unique();
3678
  }
3679
3680
  /**
3681
   * Prepends one or more values to the beginning of array at once.
3682
   *
3683
   * @return static <p>(Mutable) Return this Arrayy object, with prepended elements to the beginning of array.</p>
3684
   */
3685 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...
3686
  {
3687 4
    if (\func_num_args()) {
3688 4
      $args = \array_merge([&$this->array], \func_get_args());
3689 4
      \array_unshift(...$args);
3690
    }
3691
3692 4
    return $this;
3693
  }
3694
3695
  /**
3696
   * Get all values from a array.
3697
   *
3698
   * @return static <p>(Immutable)</p>
3699
   */
3700 2
  public function values()
3701
  {
3702 2
    return static::create(\array_values((array)$this->array));
3703
  }
3704
3705
  /**
3706
   * Apply the given function to every element in the array, discarding the results.
3707
   *
3708
   * @param \callable $callable
3709
   * @param bool      $recursive <p>Whether array will be walked recursively or no</p>
3710
   *
3711
   * @return static <p>(Mutable) Return this Arrayy object, with modified elements.</p>
3712
   */
3713 35
  public function walk($callable, bool $recursive = false)
3714
  {
3715 35
    if (true === $recursive) {
3716 30
      \array_walk_recursive($this->array, $callable);
3717
    } else {
3718 18
      \array_walk($this->array, $callable);
3719
    }
3720
3721 35
    return $this;
3722
  }
3723
}
3724