Completed
Push — master ( acf765...9d7f2b )
by Lars
03:05
created

Arrayy::createFromString()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4.0072

Importance

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