Completed
Push — master ( 5d5508...88c4b3 )
by Lars
02:35
created

Arrayy::createFromObjectVars()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Arrayy;
4
5
use voku\helper\Bootup;
6
use voku\helper\UTF8;
7
8
/** @noinspection ClassReImplementsParentInterfaceInspection */
9
10
/**
11
 * Methods to manage arrays.
12
 *
13
 * For the full copyright and license information, please view the LICENSE
14
 * file that was distributed with this source code.
15
 */
16
class Arrayy extends \ArrayObject implements \IteratorAggregate, \ArrayAccess, \Serializable, \Countable
17
{
18
  /**
19
   * @var array
20
   */
21
  protected $array = array();
22
23
  /**
24
   * @var string
25
   */
26
  protected $iteratorClass;
27
28
  /**
29
   * @var string
30
   */
31
  protected $pathSeparator = '.';
32
33
  /** @noinspection MagicMethodsValidityInspection */
34
  /**
35
   * Initializes
36
   *
37
   * @param array  $array
38
   * @param string $iteratorClass
39
   */
40 769
  public function __construct($array = array(), $iteratorClass = '\\Arrayy\\ArrayyIterator')
41
  {
42 769
    $array = $this->fallbackForArray($array);
43 767
    $this->array = $array;
44
45 767
    $this->setIteratorClass($iteratorClass);
46 767
  }
47
48
  /**
49
   * Get a value by key.
50
   *
51
   * @param $key
52
   *
53
   * @return mixed <p>Get a Value from the current array.</p>
54
   */
55 2
  public function &__get($key)
56
  {
57 2
    $return = $this->get($key);
58
59 2
    if (is_array($return)) {
60
      return static::create($return);
61
    }
62
63 2
    return $return;
64
  }
65
66
  /**
67
   * Call object as function.
68
   *
69
   * @param mixed $key
70
   *
71
   * @return mixed
72
   */
73 1
  public function __invoke($key = null)
74
  {
75 1
    if ($key !== null) {
76 1
      if (isset($this->array[$key])) {
77 1
        return $this->array[$key];
78
      }
79
80
      return false;
81
    }
82
83
    return (array)$this->array;
84
  }
85
86
  /**
87
   * Whether or not an element exists by key.
88
   *
89
   * @param mixed $key
90
   *
91
   * @return bool <p>True is the key/index exists, otherwise false.</p>
92
   */
93
  public function __isset($key)
94
  {
95
    return $this->offsetExists($key);
96
  }
97
98
  /**
99
   * Assigns a value to the specified element.
100
   *
101
   * @param mixed $key
102
   * @param mixed $value
103
   */
104 2
  public function __set($key, $value)
105
  {
106 2
    $this->internalSet($key, $value);
107 2
  }
108
109
  /**
110
   * magic to string
111
   *
112
   * @return string
113
   */
114 16
  public function __toString()
115
  {
116 16
    return $this->toString();
117
  }
118
119
  /**
120
   * Unset element by key.
121
   *
122
   * @param mixed $key
123
   */
124
  public function __unset($key)
125
  {
126
    $this->internalRemove($key);
127
  }
128
129
  /**
130
   * alias: for "Arrayy->append()"
131
   *
132
   * @see Arrayy::append()
133
   *
134
   * @param mixed $value
135
   *
136
   * @return static <p>(Mutable) Return this Arrayy object, with the appended values.</p>
137
   */
138 1
  public function add($value)
139
  {
140 1
    return $this->append($value);
141
  }
142
143
  /**
144
   * Append a value to the current array.
145
   *
146
   * @param mixed $value
147
   *
148
   * @return static <p>(Mutable) Return this Arrayy object, with the appended values.</p>
149
   */
150 9
  public function append($value)
151
  {
152 9
    $this->array[] = $value;
153
154 9
    return $this;
155
  }
156
157
  /**
158
   * Sort the entries by value.
159
   *
160
   * @param int $sort_flags [optional] <p>
161
   *                        You may modify the behavior of the sort using the optional
162
   *                        parameter sort_flags, for details
163
   *                        see sort.
164
   *                        </p>
165
   *
166
   * @return static <p>(Mutable) Return this Arrayy object.</p>
167
   */
168 4
  public function asort($sort_flags = null)
169
  {
170 4
    asort($this->array, $sort_flags);
171
172 4
    return $this;
173
  }
174
175
  /**
176
   * Count the values from the current array.
177
   *
178
   * alias: for "Arrayy->size()"
179
   *
180
   * @see Arrayy::size()
181
   *
182
   * @return int
183
   */
184 93
  public function count()
185
  {
186 93
    return $this->size();
187
  }
188
189
  /**
190
   * Counts all the values of an array
191
   *
192
   * @link http://php.net/manual/en/function.array-count-values.php
193
   *
194
   * @return static <p>
195
   *                (Immutable)
196
   *                An associative Arrayy-object of values from input as
197
   *                keys and their count as value.
198
   *                </p>
199
   */
200 1
  public function countValues()
201
  {
202 1
    return new static(\array_count_values($this->array));
203
  }
204
205
  /**
206
   * Exchange the array for another one.
207
   *
208
   * @param array|Arrayy $data
209
   *
210
   * @return array
211
   */
212 1
  public function exchangeArray($data)
213
  {
214 1
    $this->array = $this->fallbackForArray($data);
215
216 1
    return $this->array;
217
  }
218
219
  /**
220
   * Creates a copy of the ArrayyObject.
221
   *
222
   * @return array
223
   */
224 1
  public function getArrayCopy()
225
  {
226 1
    return $this->array;
227
  }
228
229
  /**
230
   * Returns a new ArrayyIterator, thus implementing the IteratorAggregate interface.
231
   *
232
   * @return ArrayyIterator <p>An iterator for the values in the array.</p>
233
   */
234 20
  public function getIterator()
235
  {
236 20
    $iterator = $this->getIteratorClass();
237
238 20
    return new $iterator($this->array);
239
  }
240
241
  /**
242
   * Gets the iterator classname for the ArrayObject.
243
   *
244
   * @return string
245
   */
246 20
  public function getIteratorClass()
247
  {
248 20
    return $this->iteratorClass;
249
  }
250
251
  /**
252
   * Sort the entries by key
253
   *
254
   * @param int $sort_flags [optional] <p>
255
   *                        You may modify the behavior of the sort using the optional
256
   *                        parameter sort_flags, for details
257
   *                        see sort.
258
   *                        </p>
259
   *
260
   * @return static <p>(Mutable) Return this Arrayy object.</p>
261
   */
262 4
  public function ksort($sort_flags = null)
263
  {
264 4
    ksort($this->array, $sort_flags);
265
266 4
    return $this;
267
  }
268
269
  /**
270
   * Sort an array using a case insensitive "natural order" algorithm
271
   *
272
   * @return static <p>(Mutable) Return this Arrayy object.</p>
273
   */
274
  public function natcasesort()
275
  {
276
    natcasesort($this->array);
277
278
    return $this;
279
  }
280
281
  /**
282
   * Sort entries using a "natural order" algorithm
283
   *
284
   * @return static <p>(Mutable) Return this Arrayy object.</p>
285
   */
286 1
  public function natsort()
287
  {
288 1
    natsort($this->array);
289
290 1
    return $this;
291
  }
292
293
  /**
294
   * Whether or not an offset exists.
295
   *
296
   * @param int|float|string $offset
297
   *
298
   * @return bool
299
   */
300 40
  public function offsetExists($offset)
301
  {
302 40
    if ($this->isEmpty()) {
303 4
      return false;
304
    }
305
306
    // php cast "bool"-index into "int"-index
307 36
    if ((bool)$offset === $offset) {
308 1
      $offset = (int)$offset;
309 1
    }
310
311 36
    $tmpReturn = \array_key_exists($offset, $this->array);
312
313
    if (
314
        $tmpReturn === true
315 36
        ||
316
        (
317
            $tmpReturn === false
318 12
            &&
319 12
            strpos((string)$offset, $this->pathSeparator) === false
320 12
        )
321 36
    ) {
322 34
      return $tmpReturn;
323
    }
324
325 3
    $offsetExists = false;
326
327 3
    if (strpos((string)$offset, $this->pathSeparator) !== false) {
328
329 3
      $offsetExists = false;
330 3
      $explodedPath = explode($this->pathSeparator, (string)$offset);
331 3
      $lastOffset = \array_pop($explodedPath);
332 3
      $containerPath = implode($this->pathSeparator, $explodedPath);
333
334 3
      $this->callAtPath(
335 3
          $containerPath,
336
          function ($container) use ($lastOffset, &$offsetExists) {
337 3
            $offsetExists = \array_key_exists($lastOffset, $container);
338 3
          }
339 3
      );
340 3
    }
341
342 3
    return $offsetExists;
343
  }
344
345
  /**
346
   * Returns the value at specified offset.
347
   *
348
   * @param mixed $offset
349
   *
350
   * @return mixed <p>Will return null if the offset did not exists.</p>
351
   */
352 26
  public function offsetGet($offset)
353
  {
354 26
    return $this->offsetExists($offset) ? $this->get($offset) : null;
355
  }
356
357
  /**
358
   * Assigns a value to the specified offset.
359
   *
360
   * @param mixed $offset
361
   * @param mixed $value
362
   */
363 17
  public function offsetSet($offset, $value)
364
  {
365 17
    if ($offset === null) {
366 4
      $this->array[] = $value;
367 4
    } else {
368 13
      $this->internalSet($offset, $value);
369
    }
370 17
  }
371
372
  /**
373
   * Unset an offset.
374
   *
375
   * @param mixed $offset
376
   */
377 7
  public function offsetUnset($offset)
378
  {
379 7
    if ($this->isEmpty()) {
380 1
      return;
381
    }
382
383 6
    if (\array_key_exists($offset, $this->array)) {
384 4
      unset($this->array[$offset]);
385
386 4
      return;
387
    }
388
389 3
    if (strpos((string)$offset, $this->pathSeparator) !== false) {
390
391 2
      $path = explode($this->pathSeparator, (string)$offset);
392 2
      $pathToUnset = \array_pop($path);
393
394 2
      $this->callAtPath(
395 2
          implode($this->pathSeparator, $path),
396
          function (&$offset) use ($pathToUnset) {
397 2
            unset($offset[$pathToUnset]);
398 2
          }
399 2
      );
400
401 2
    }
402 3
  }
403
404
  /**
405
   * Serialize the current "Arrayy"-object.
406
   *
407
   * @return string
408
   */
409 1
  public function serialize()
410
  {
411 1
    return parent::serialize();
412
  }
413
414
  /**
415
   * Sets the iterator classname for the current "Arrayy"-object.
416
   *
417
   * @param  string $class
418
   *
419
   * @return void
420
   *
421
   * @throws \InvalidArgumentException
422
   */
423 767
  public function setIteratorClass($class)
424
  {
425 767
    if (class_exists($class)) {
426 767
      $this->iteratorClass = $class;
427
428 767
      return;
429
    }
430
431
    if (strpos($class, '\\') === 0) {
432
      $class = '\\' . $class;
433
      if (class_exists($class)) {
434
        $this->iteratorClass = $class;
435
436
        return;
437
      }
438
    }
439
440
    throw new \InvalidArgumentException('The iterator class does not exist: ' . $class);
441
  }
442
443
  /**
444
   * Sort the entries with a user-defined comparison function and maintain key association.
445
   *
446
   * @param callable $function
447
   *
448
   * @return static <p>(Mutable) Return this Arrayy object.</p>
449
   *
450
   * @throws \InvalidArgumentException
451
   */
452 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...
453
  {
454
    if (!is_callable($function)) {
455
      throw new \InvalidArgumentException(
456
          'Passed function must be callable'
457
      );
458
    }
459
460
    uasort($this->array, $function);
461
462
    return $this;
463
  }
464
465
  /**
466
   * Sort the entries by keys using a user-defined comparison function.
467
   *
468
   * @param callable $function
469
   *
470
   * @return static <p>(Mutable) Return this Arrayy object.</p>
471
   *
472
   * @throws \InvalidArgumentException
473
   */
474 5
  public function uksort($function)
475
  {
476 5
    return $this->customSortKeys($function);
477
  }
478
479
  /**
480
   * Unserialize an string and return this object.
481
   *
482
   * @param string $string
483
   *
484
   * @return static <p>(Mutable)</p>
485
   */
486 1
  public function unserialize($string)
487
  {
488 1
    parent::unserialize($string);
489
490 1
    return $this;
491
  }
492
493
  /**
494
   * Sort an array in reverse order and maintain index association.
495
   *
496
   * @return static <p>(Mutable) Return this Arrayy object.</p>
497
   */
498 4
  public function arsort()
499
  {
500 4
    arsort($this->array);
501
502 4
    return $this;
503
  }
504
505
  /**
506
   * Iterate over the current array and execute a callback for each loop.
507
   *
508
   * @param \Closure $closure
509
   *
510
   * @return static <p>(Immutable)</p>
511
   */
512 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...
513
  {
514 2
    $array = $this->array;
515
516 2
    foreach ($array as $key => $value) {
517 2
      $closure($value, $key);
518 2
    }
519
520 2
    return static::create($array);
521
  }
522
523
  /**
524
   * Returns the average value of the current array.
525
   *
526
   * @param int $decimals <p>The number of decimal-numbers to return.</p>
527
   *
528
   * @return int|double <p>The average value.</p>
529
   */
530 10
  public function average($decimals = 0)
531
  {
532 10
    $count = $this->count();
533
534 10
    if (!$count) {
535 2
      return 0;
536
    }
537
538 8
    if (!is_int($decimals)) {
539 3
      $decimals = 0;
540 3
    }
541
542 8
    return round(\array_sum($this->array) / $count, $decimals);
543
  }
544
545
  /**
546
   * @param mixed      $path
547
   * @param callable   $callable
548
   * @param null|array $currentOffset
549
   */
550 4
  protected function callAtPath($path, $callable, &$currentOffset = null)
551
  {
552 4
    if ($currentOffset === null) {
553 4
      $currentOffset = &$this->array;
554 4
    }
555
556 4
    $explodedPath = explode($this->pathSeparator, $path);
557 4
    $nextPath = \array_shift($explodedPath);
558
559 4
    if (!isset($currentOffset[$nextPath])) {
560
      return;
561
    }
562
563 4
    if (!empty($explodedPath)) {
564 1
      $this->callAtPath(
565 1
          implode($this->pathSeparator, $explodedPath),
566 1
          $callable,
567 1
          $currentOffset[$nextPath]
568 1
      );
569 1
    } else {
570 4
      $callable($currentOffset[$nextPath]);
571
    }
572 4
  }
573
574
  /**
575
   * Changes all keys in an array.
576
   *
577
   * @param int $case [optional] <p> Either <strong>CASE_UPPER</strong><br />
578
   *                  or <strong>CASE_LOWER</strong> (default)</p>
579
   *
580
   * @return static <p>(Immutable)</p>
581
   */
582 1
  public function changeKeyCase($case = CASE_LOWER)
583
  {
584 1
    return static::create(UTF8::array_change_key_case($this->array, $case));
0 ignored issues
show
Security Bug introduced by
It seems like \voku\helper\UTF8::array...se($this->array, $case) targeting voku\helper\UTF8::array_change_key_case() can also be of type false; however, Arrayy\Arrayy::create() does only seem to accept array, did you maybe forget to handle an error condition?
Loading history...
585
  }
586
587
  /**
588
   * Change the path separator of the array wrapper.
589
   *
590
   * By default, the separator is: "."
591
   *
592
   * @param string $separator <p>Separator to set.</p>
593
   *
594
   * @return static <p>Mutable</p>
595
   */
596 1
  public function changeSeparator($separator)
597
  {
598 1
    $this->pathSeparator = $separator;
599
600 1
    return $this;
601
  }
602
603
  /**
604
   * Create a chunked version of the current array.
605
   *
606
   * @param int  $size         <p>Size of each chunk.</p>
607
   * @param bool $preserveKeys <p>Whether array keys are preserved or no.</p>
608
   *
609
   * @return static <p>(Immutable) A new array of chunks from the original array.</p>
610
   */
611 4
  public function chunk($size, $preserveKeys = false)
612
  {
613 4
    $result = \array_chunk($this->array, $size, $preserveKeys);
614
615 4
    return static::create($result);
616
  }
617
618
  /**
619
   * Clean all falsy values from the current array.
620
   *
621
   * @return static <p>(Immutable)</p>
622
   */
623 8
  public function clean()
624
  {
625 8
    return $this->filter(
626
        function ($value) {
627 7
          return (bool)$value;
628
        }
629 8
    );
630
  }
631
632
  /**
633
   * WARNING!!! -> Clear the current array.
634
   *
635
   * @return static <p>(Mutable) Return this Arrayy object, with an empty array.</p>
636
   */
637 4
  public function clear()
638
  {
639 4
    $this->array = array();
640
641 4
    return $this;
642
  }
643
644
  /**
645
   * Check if an item is in the current array.
646
   *
647
   * @param string|int|float $value
648
   *
649
   * @return bool
650
   */
651 13
  public function contains($value)
652
  {
653 13
    return in_array($value, $this->array, true);
654
  }
655
656
  /**
657
   * Check if an (case-insensitive) string is in the current array.
658
   *
659
   * @param string $value
660
   *
661
   * @return bool
662
   */
663 13
  public function containsCaseInsensitive($value)
664
  {
665 13
    return in_array(
666 13
        UTF8::strtolower($value),
667 13
        \array_map(
668
            array(
669 13
                new UTF8(),
670 13
                'strtolower',
671 13
            ),
672 13
            $this->array
673 13
        ),
674
        true
675 13
    );
676
  }
677
678
  /**
679
   * Check if the given key/index exists in the array.
680
   *
681
   * @param string|int|float $key <p>key/index to search for</p>
682
   *
683
   * @return bool <p>Returns true if the given key/index exists in the array, false otherwise.</p>
684
   */
685 4
  public function containsKey($key)
686
  {
687 4
    return $this->offsetExists($key);
688
  }
689
690
  /**
691
   * Check if all given needles are present in the array as key/index.
692
   *
693
   * @param array $needles
694
   *
695
   * @return bool <p>Returns true if the given keys/indexes exists in the array, false otherwise.</p>
696
   */
697 1
  public function containsKeys(array $needles)
698
  {
699 1
    return count(\array_intersect($needles, $this->keys()->getArray())) === count($needles);
700
  }
701
702
  /**
703
   * alias: for "Arrayy->contains()"
704
   *
705
   * @see Arrayy::contains()
706
   *
707
   * @param string|int|float $value
708
   *
709
   * @return bool
710
   */
711 9
  public function containsValue($value)
712
  {
713 9
    return $this->contains($value);
714
  }
715
716
  /**
717
   * Check if all given needles are present in the array.
718
   *
719
   * @param array $needles
720
   *
721
   * @return bool <p>Returns true if the given values exists in the array, false otherwise.</p>
722
   */
723 1
  public function containsValues(array $needles)
724
  {
725 1
    return count(\array_intersect($needles, $this->array)) === count($needles);
726
  }
727
728
  /**
729
   * Creates an Arrayy object.
730
   *
731
   * @param array $array
732
   *
733
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
734
   */
735 480
  public static function create($array = array())
736
  {
737 480
    return new static($array);
738
  }
739
740
  /**
741
   * WARNING: Creates an Arrayy object by reference.
742
   *
743
   * @param array $array
744
   *
745
   * @return static <p>(Mutable) Return this Arrayy object.</p>
746
   */
747 1
  public function createByReference(&$array = array())
748
  {
749 1
    $array = $this->fallbackForArray($array);
750
751 1
    $this->array = &$array;
752
753 1
    return $this;
754
  }
755
756
  /**
757
   * Create an new Arrayy object via JSON.
758
   *
759
   * @param string $json
760
   *
761
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
762
   */
763 5
  public static function createFromJson($json)
764
  {
765 5
    $array = UTF8::json_decode($json, true);
766
767 5
    return static::create($array);
768
  }
769
770
  /**
771
   * Create an new instance filled with values from an object that have implemented ArrayAccess.
772
   *
773
   * @param \ArrayAccess $object <p>Object that implements ArrayAccess</p>
774
   *
775
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
776
   */
777 4
  public static function createFromObject(\ArrayAccess $object)
778
  {
779 4
    $array = new static();
780 4
    foreach ($object as $key => $value) {
781
      /** @noinspection OffsetOperationsInspection */
782 3
      $array[$key] = $value;
783 4
    }
784
785 4
    return $array;
786
  }
787
788
  /**
789
   * Create an new instance filled with values from an object.
790
   *
791
   * @param object $object
792
   *
793
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
794
   */
795
  public static function createFromObjectVars($object)
796
  {
797
    return new static(self::objectToArray($object));
798 8
  }
799
800 8
  /**
801 1
   * Convert a object into an array.
802
   *
803 1
   * @param object $object
804 1
   *
805 1
   * @return mixed
806
   */
807 1
  protected static function objectToArray($object)
808 7
  {
809
    if (!is_object($object)) {
810
      return $object;
811
    }
812 8
813
    if (is_object($object)) {
814
      $object = get_object_vars($object);
815
    }
816 8
    return array_map(array('self', 'objectToArray'), $object);
817 8
  }
818 8
819 8
  /**
820 8
   * Create an new Arrayy object via string.
821
   *
822 8
   * @param string      $str       <p>The input string.</p>
823
   * @param string|null $delimiter <p>The boundary string.</p>
824
   * @param string|null $regEx     <p>Use the $delimiter or the $regEx, so if $pattern is null, $delimiter will be
825
   *                               used.</p>
826
   *
827
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
828
   */
829
  public static function createFromString($str, $delimiter, $regEx = null)
830
  {
831
    if ($regEx) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $regEx of type string|null 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...
832
      preg_match_all($regEx, $str, $array);
833
834 1
      if (!empty($array)) {
835
        $array = $array[0];
836 1
      }
837
838
    } else {
839
      $array = explode($delimiter, $str);
840
    }
841
842
    // trim all string in the array
843
    \array_walk(
844
        $array,
845
        function (&$val) {
846
          /** @noinspection ReferenceMismatchInspection */
847
          if (is_string($val)) {
848
            $val = trim($val);
849
          }
850 5
        }
851
    );
852 5
853
    return static::create($array);
854
  }
855
856
  /**
857
   * Create an new instance containing a range of elements.
858 5
   *
859
   * @param mixed $low  <p>First value of the sequence.</p>
860 5
   * @param mixed $high <p>The sequence is ended upon reaching the end value.</p>
861
   * @param int   $step <p>Used as the increment between elements in the sequence.</p>
862
   *
863
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
864
   */
865
  public static function createWithRange($low, $high, $step = 1)
866
  {
867
    return static::create(range($low, $high, $step));
868
  }
869
870
  /**
871
   * Custom sort by index via "uksort".
872
   *
873
   * @link http://php.net/manual/en/function.uksort.php
874 5
   *
875
   * @param callable $function
876 5
   *
877
   * @return static <p>(Mutable) Return this Arrayy object.</p>
878
   *
879
   * @throws \InvalidArgumentException
880
   */
881 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...
882 5
  {
883
    if (!is_callable($function)) {
884 5
      throw new \InvalidArgumentException(
885
          'Passed function must be callable'
886
      );
887
    }
888
889
    uksort($this->array, $function);
890
891
    return $this;
892
  }
893
894 12
  /**
895
   * Custom sort by value via "usort".
896 12
   *
897
   * @link http://php.net/manual/en/function.usort.php
898 12
   *
899
   * @param callable $function
900
   *
901
   * @return static <p>(Mutable) Return this Arrayy object.</p>
902
   *
903
   * @throws \InvalidArgumentException
904
   */
905 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...
906
  {
907
    if (!is_callable($function)) {
908
      throw new \InvalidArgumentException(
909 1
          'Passed function must be callable'
910
      );
911 1
    }
912
913
    usort($this->array, $function);
914
915 1
    return $this;
916 1
  }
917 1
918 1
  /**
919 1
   * Return values that are only in the current array.
920 1
   *
921
   * @param array $array
922
   *
923 1
   * @return static <p>(Immutable)</p>
924 1
   */
925 1
  public function diff(array $array = array())
926 1
  {
927 1
    $result = \array_diff($this->array, $array);
928 1
929 1
    return static::create($result);
930 1
  }
931 1
932 1
  /**
933 1
   * Return values that are only in the current multi-dimensional array.
934
   *
935 1
   * @param array      $array
936 1
   * @param null|array $helperVariableForRecursion <p>(only for internal usage)</p>
937
   *
938 1
   * @return static <p>(Immutable)</p>
939
   */
940 1
  public function diffRecursive(array $array = array(), $helperVariableForRecursion = null)
941
  {
942
    $result = array();
943
944
    if (
945
        $helperVariableForRecursion !== null
946
        &&
947
        is_array($helperVariableForRecursion)
948
    ) {
949
      $arrayForTheLoop = $helperVariableForRecursion;
950 8
    } else {
951
      $arrayForTheLoop = $this->array;
952 8
    }
953
954 8
    foreach ($arrayForTheLoop as $key => $value) {
955
      if (\array_key_exists($key, $array)) {
956
        if (is_array($value)) {
957
          $recursiveDiff = $this->diffRecursive($array[$key], $value);
958
          if (!empty($recursiveDiff)) {
959
            $result[$key] = $recursiveDiff;
960
          }
961
        } else {
962 1
          if ($value != $array[$key]) {
963
            $result[$key] = $value;
964 1
          }
965
        }
966 1
      } else {
967 1
        $result[$key] = $value;
968
      }
969 1
    }
970
971
    return static::create($result);
972
  }
973
974
  /**
975
   * Return values that are only in the new $array.
976
   *
977
   * @param array $array
978
   *
979 4
   * @return static <p>(Immutable)</p>
980
   */
981 4
  public function diffReverse(array $array = array())
982
  {
983 4
    $result = \array_diff($array, $this->array);
984 4
985 4
    return static::create($result);
986
  }
987 4
988
  /**
989
   * Divide an array into two arrays. One with keys and the other with values.
990
   *
991
   * @return static <p>(Immutable)</p>
992
   */
993
  public function divide()
994
  {
995
    return static::create(
996
        array(
997 4
            $this->keys(),
998
            $this->values(),
999 4
        )
1000 4
    );
1001 3
  }
1002 1
1003 1
  /**
1004
   * Iterate over the current array and modify the array's value.
1005 4
   *
1006
   * @param \Closure $closure
1007 4
   *
1008
   * @return static <p>(Immutable)</p>
1009
   */
1010 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...
1011
  {
1012
    $array = $this->array;
1013
1014
    foreach ($array as $key => $value) {
1015
      $array[$key] = $closure($value, $key);
1016
    }
1017
1018
    return static::create($array);
1019
  }
1020
1021
  /**
1022
   * Check if a value is in the current array using a closure.
1023
   *
1024
   * @param \Closure $closure
1025
   *
1026
   * @return bool <p>Returns true if the given value is found, false otherwise.</p>
1027 769
   */
1028
  public function exists(\Closure $closure)
1029 769
  {
1030 766
    $isExists = false;
1031
    foreach ($this->array as $key => $value) {
1032
      if ($closure($value, $key)) {
1033 11
        $isExists = true;
1034 1
        break;
1035
      }
1036
    }
1037 10
1038 6
    return $isExists;
1039
  }
1040
1041 9
  /**
1042
   * create a fallback for array
1043 9
   *
1044
   * 1. use the current array, if it's a array
1045
   * 2. call "getArray()" on object, if there is a "Arrayy"-object
1046
   * 3. fallback to empty array, if there is nothing
1047
   * 4. call "createFromObject()" on object, if there is a "\ArrayAccess"-object
1048 9
   * 5. call "__toArray()" on object, if the method exists
1049
   * 6. cast a string or object with "__toString()" into an array
1050
   * 7. throw a "InvalidArgumentException"-Exception
1051
   *
1052 9
   * @param $array
1053
   *
1054
   * @return array
1055
   *
1056
   * @throws \InvalidArgumentException
1057
   */
1058 9
  protected function fallbackForArray(&$array)
1059
  {
1060 2
    if (is_array($array)) {
1061 9
      return $array;
1062 7
    }
1063
1064
    if ($array instanceof self) {
1065 2
      return $array->getArray();
1066
    }
1067 2
1068
    if (!$array) {
1069
      return array();
1070
    }
1071
1072
    $isObject = is_object($array);
1073
1074
    if ($isObject && $array instanceof \ArrayAccess) {
1075
      /** @noinspection ReferenceMismatchInspection */
1076
      return static::createFromObject($array)->getArray();
1077
    }
1078
1079
    if ($isObject && $array instanceof \ArrayObject) {
1080
      return $array->getArrayCopy();
1081
    }
1082
1083
    if ($isObject && method_exists($array, '__toArray')) {
1084
      return (array)$array->__toArray();
1085
    }
1086
1087
    /** @noinspection ReferenceMismatchInspection */
1088
    if (
1089
        is_string($array)
1090
        ||
1091
        ($isObject && method_exists($array, '__toString'))
1092
    ) {
1093
      return array((string)$array);
1094
    }
1095
1096
    throw new \InvalidArgumentException(
1097
        'Passed value should be a array'
1098 9
    );
1099
  }
1100 9
1101 1
  /**
1102
   * Find all items in an array that pass the truth test.
1103
   *
1104 9
   * @param \Closure|null $closure [optional] <p>
1105
   *                               The callback function to use
1106
   *                               </p>
1107
   *                               <p>
1108 9
   *                               If no callback is supplied, all entries of
1109
   *                               input equal to false (see
1110 9
   *                               converting to
1111
   *                               boolean) will be removed.
1112
   *                               </p>
1113
   *
1114
   *  * @param int $flag [optional] <p>
1115
   *                               Flag determining what arguments are sent to <i>callback</i>:
1116
   *                               </p><ul>
1117
   *                               <li>
1118
   *                               <b>ARRAY_FILTER_USE_KEY</b> [1] - pass key as the only argument
1119
   *                               to <i>callback</i> instead of the value</span>
1120 1
   *                               </li>
1121
   *                               <li>
1122 1
   *                               <b>ARRAY_FILTER_USE_BOTH</b> [2] - pass both value and key as
1123 1
   *                               arguments to <i>callback</i> instead of the value</span>
1124 1
   *                               </li>
1125 1
   *                               </ul>
1126 1
   *
1127 1
   * @return static <p>(Immutable)</p>
1128 1
   */
1129 1
  public function filter($closure = null, $flag = 0)
1130 1
  {
1131 1
    if (!$closure) {
1132 1
      return $this->clean();
1133 1
    }
1134 1
1135
    if ($flag === 0) {
1136
1137 9
      // working for all php-versions
1138
1139
      $array = \array_filter($this->array, $closure);
1140
1141
    } elseif ($flag !== 0 && defined('HHVM_VERSION') === false && Bootup::is_php('5.6')) {
1142
1143
      // working only with php >= 5.6 and not via HHVM
1144
1145
      $array = \array_filter($this->array, $closure, $flag);
1146
1147
    } else {
1148
1149
      // fallback for old php-versions
1150
1151
      $array = $this->array;
1152
1153
      if ($flag === 2 /* ARRAY_FILTER_USE_KEY */) {
1154
        foreach ($array as $key => $value) {
1155
          if (!call_user_func($closure, $key)) {
1156
            unset($array[$key]);
1157
          }
1158
        }
1159
      } elseif ($flag === 1 /* ARRAY_FILTER_USE_BOTH */) {
1160
        foreach ($array as $key => $value) {
1161
          if (!call_user_func($closure, $key, $value)) {
1162 1
            unset($array[$key]);
1163
          }
1164 1
        }
1165 1
      }
1166 1
    }
1167
1168
    return static::create($array);
1169
  }
1170 1
1171 1
  /**
1172
   * Filters an array of objects (or a numeric array of associative arrays) based on the value of a particular property
1173
   * within that.
1174 1
   *
1175
   * @param string $property
1176
   * @param string $value
1177 1
   * @param string $comparisonOp
1178
   *                            <p>
1179
   *                            'eq' (equals),<br />
1180 1
   *                            'gt' (greater),<br />
1181
   *                            'gte' || 'ge' (greater or equals),<br />
1182 1
   *                            'lt' (less),<br />
1183 1
   *                            'lte' || 'le' (less or equals),<br />
1184
   *                            'ne' (not equals),<br />
1185
   *                            'contains',<br />
1186 1
   *                            'notContains',<br />
1187
   *                            'newer' (via strtotime),<br />
1188
   *                            'older' (via strtotime),<br />
1189 1
   *                            </p>
1190
   *
1191
   * @return static <p>(Immutable)</p>
1192 1
   */
1193
  public function filterBy($property, $value, $comparisonOp = null)
1194 1
  {
1195 1
    if (!$comparisonOp) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $comparisonOp of type string|null 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...
1196
      $comparisonOp = is_array($value) ? 'contains' : 'eq';
1197
    }
1198 1
1199
    $ops = array(
1200
        'eq'          => function ($item, $prop, $value) {
1201 1
          return $item[$prop] === $value;
1202
        },
1203
        'gt'          => function ($item, $prop, $value) {
1204 1
          return $item[$prop] > $value;
1205 1
        },
1206
        'ge'          => function ($item, $prop, $value) {
1207 1
          return $item[$prop] >= $value;
1208 1
        },
1209 1
        'gte'         => function ($item, $prop, $value) {
1210
          return $item[$prop] >= $value;
1211 1
        },
1212 1
        'lt'          => function ($item, $prop, $value) {
1213 1
          return $item[$prop] < $value;
1214 1
        },
1215
        'le'          => function ($item, $prop, $value) {
1216 1
          return $item[$prop] <= $value;
1217 1
        },
1218 1
        'lte'         => function ($item, $prop, $value) {
1219
          return $item[$prop] <= $value;
1220 1
        },
1221
        'ne'          => function ($item, $prop, $value) {
1222 1
          return $item[$prop] !== $value;
1223 1
        },
1224
        'contains'    => function ($item, $prop, $value) {
1225 1
          return in_array($item[$prop], (array)$value, true);
1226
        },
1227
        'notContains' => function ($item, $prop, $value) {
1228
          return !in_array($item[$prop], (array)$value, true);
1229
        },
1230
        'newer'       => function ($item, $prop, $value) {
1231
          return strtotime($item[$prop]) > strtotime($value);
1232
        },
1233
        'older'       => function ($item, $prop, $value) {
1234
          return strtotime($item[$prop]) < strtotime($value);
1235
        },
1236 8
    );
1237
1238 8
    $result = \array_values(
1239 6
        \array_filter(
1240 5
            (array)$this->array,
1241
            function ($item) use (
1242 5
                $property,
1243
                $value,
1244 3
                $ops,
1245
                $comparisonOp
1246
            ) {
1247
              $item = (array)$item;
1248
              $itemArrayy = new Arrayy($item);
1249
              $item[$property] = $itemArrayy->get($property, array());
1250
1251
              return $ops[$comparisonOp]($item, $property, $value);
1252
            }
1253
        )
1254
    );
1255
1256
    return static::create($result);
1257
  }
1258
1259
  /**
1260
   * Find the first item in an array that passes the truth test,
1261
   *  otherwise return false
1262
   *
1263
   * @param \Closure $closure
1264
   *
1265
   * @return mixed|false <p>Return false if we did not find the value.</p>
1266 13
   */
1267
  public function find(\Closure $closure)
1268 13
  {
1269 13
    foreach ($this->array as $key => $value) {
1270
      if ($closure($value, $key)) {
1271 13
        return $value;
1272 3
      }
1273
    }
1274
1275 10
    return false;
1276
  }
1277
1278
  /**
1279
   * find by ...
1280
   *
1281
   * @param string $property
1282
   * @param string $value
1283
   * @param string $comparisonOp
1284
   *
1285 28
   * @return static <p>(Immutable)</p>
1286
   */
1287 28
  public function findBy($property, $value, $comparisonOp = 'eq')
1288 7
  {
1289 7
    return $this->filterBy($property, $value, $comparisonOp);
1290 7
  }
1291 21
1292 21
  /**
1293 21
   * Get the first value from the current array.
1294
   *
1295
   * @return mixed <p>Return null if there wasn't a element.</p>
1296 28
   */
1297
  public function first()
1298
  {
1299
    $tmpArray = $this->array;
1300
    $result = \array_shift($tmpArray);
1301
1302
    if ($result === null) {
1303
      return null;
1304
    }
1305
1306 26
    return $result;
1307
  }
1308 26
1309 11
  /**
1310 11
   * Get the first value(s) from the current array.
1311 15
   *
1312 15
   * @param int|null $number <p>How many values you will take?</p>
1313
   *
1314
   * @return static <p>(Immutable)</p>
1315 26
   */
1316
  public function firstsImmutable($number = null)
1317
  {
1318
    if ($number === null) {
1319
      $arrayTmp = $this->array;
1320
      $array = (array)\array_shift($arrayTmp);
1321
    } else {
1322
      $number = (int)$number;
1323 1
      $arrayTmp = $this->array;
1324
      $array = \array_splice($arrayTmp, 0, $number, true);
1325 1
    }
1326
1327 1
    return static::create($array);
1328
  }
1329
1330
  /**
1331
   * Get the first value(s) from the current array.
1332
   *
1333
   * @param int|null $number <p>How many values you will take?</p>
1334
   *
1335
   * @return static <p>(Mutable)</p>
1336
   */
1337
  public function firstsMutable($number = null)
1338
  {
1339
    if ($number === null) {
1340 61
      $this->array = (array)\array_shift($this->array);
1341
    } else {
1342
      $number = (int)$number;
1343
      $this->array = \array_splice($this->array, 0, $number, true);
1344 61
    }
1345 3
1346 61
    return $this;
1347 3
  }
1348 3
1349 59
  /**
1350
   * Exchanges all keys with their associated values in an array.
1351
   *
1352 61
   * @return static <p>(Immutable)</p>
1353 1
   */
1354
  public function flip()
1355
  {
1356
    $result = \array_flip($this->array);
1357 61
1358 2
    return static::create($result);
1359 2
  }
1360
1361 61
  /**
1362 51
   * Get a value from an array (optional using dot-notation).
1363 6
   *
1364
   * @param string $key      <p>The key to look for.</p>
1365
   * @param mixed  $fallback <p>Value to fallback to.</p>
1366 47
   * @param array  $array    <p>The array to get from, if it's set to "null" we use the current array from the
1367
   *                         class.</p>
1368
   *
1369
   * @return mixed
1370 20
   */
1371 20
  public function get($key, $fallback = null, $array = null)
1372 19
  {
1373
    if (
1374
        $array !== null
1375 5
        &&
1376 5
        is_array($array)
1377
    ) {
1378 5
      $usedArray = $array;
1379
    } else {
1380
      $usedArray = $this->array;
1381
    }
1382 5
1383
    if ($key === null) {
1384
      return static::create($usedArray);
1385
    }
1386
1387
    // php cast "bool"-index into "int"-index
1388
    if ((bool)$key === $key) {
1389
      $key = (int)$key;
1390 491
    }
1391
1392 491
    if (\array_key_exists($key, $usedArray) === true) {
1393
      if (is_array($usedArray[$key])) {
1394 491
        return static::create($usedArray[$key]);
1395
      }
1396
1397
      return $usedArray[$key];
1398
    }
1399
1400
    // Crawl through array, get key according to object or not
1401
    foreach (explode($this->pathSeparator, (string)$key) as $segment) {
1402
      if (!isset($usedArray[$segment])) {
1403
        return $fallback instanceof \Closure ? $fallback() : $fallback;
1404
      }
1405
1406
      $usedArray = $usedArray[$segment];
1407
    }
1408
1409 1
    if (is_array($usedArray)) {
1410
      return static::create($usedArray);
1411 1
    }
1412
1413 1
    return $usedArray;
1414
  }
1415
1416
  /**
1417
   * Get the current array from the "Arrayy"-object.
1418
   *
1419
   * @return array
1420
   */
1421
  public function getArray()
1422
  {
1423 38
    \array_map(array('self', 'internalGetArray'), $this->array);
1424
1425 38
    return $this->array;
1426 10
  }
1427
1428 10
  /**
1429 2
   * Get the current array from the "Arrayy"-object as object.
1430 2
   *
1431 8
   * @return \stdClass (object)
1432
   */
1433 10
  public function getObject()
1434
  {
1435
    return self::arrayToObject($this->getArray());
1436
  }
1437 38
1438
  /**
1439 38
   * Convert an array into a object.
1440
   *
1441
   * @param array $array PHP array
1442
   *
1443 38
   * @return \stdClass (object)
1444
   */
1445
  protected static function arrayToObject(array $array = array())
1446
  {
1447
    $object = new \stdClass();
1448
1449
    if (!is_array($array) || count($array) < 1) {
1450
      return $object;
1451
    }
1452
1453 1
    foreach ($array as $name => $value) {
1454
      if (is_array($value)) {
1455 1
        $object->$name = self::arrayToObject($value);
1456
        continue;
1457
      }
1458
      $object->{$name} = $value;
1459
    }
1460
1461
    return $object;
1462
  }
1463
1464
  /**
1465 3
   * Returns the values from a single column of the input array, identified by
1466
   * the $columnKey, can be used to extract data-columns from multi-arrays.
1467 3
   *
1468
   * Info: Optionally, you may provide an $indexKey to index the values in the returned
1469
   * array by the values from the $indexKey column in the input array.
1470
   *
1471
   * @param mixed $columnKey
1472
   * @param mixed $indexKey
1473
   *
1474
   * @return static <p>(Immutable)</p>
1475
   */
1476
  public function getColumn($columnKey = null, $indexKey = null)
1477 3
  {
1478
    $result = \array_column($this->array, $columnKey, $indexKey);
1479 3
1480
    return static::create($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by \array_column($this->arr... $columnKey, $indexKey) on line 1478 can also be of type false or null; however, Arrayy\Arrayy::create() does only seem to accept array, maybe add an additional type check?

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

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

    return array();
}

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

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

Loading history...
1481
  }
1482
1483
  /**
1484
   * Get correct PHP constant for direction.
1485
   *
1486
   * @param int|string $direction
1487
   *
1488
   * @return int
1489
   */
1490
  protected function getDirection($direction)
1491 9
  {
1492
    if (is_string($direction)) {
1493 9
      $direction = strtolower($direction);
1494
1495
      if ($direction === 'desc') {
1496
        $direction = SORT_DESC;
1497
      } else {
1498
        $direction = SORT_ASC;
1499
      }
1500
    }
1501
1502
    if (
1503 3
        $direction !== SORT_DESC
1504
        &&
1505 3
        $direction !== SORT_ASC
1506
    ) {
1507
      $direction = SORT_ASC;
1508
    }
1509
1510
    return $direction;
1511
  }
1512
1513
  /**
1514
   * alias: for "Arrayy->keys()"
1515
   *
1516
   * @see Arrayy::keys()
1517 6
   *
1518
   * @return static <p>(Immutable)</p>
1519 6
   */
1520
  public function getKeys()
1521
  {
1522
    return $this->keys();
1523
  }
1524
1525
  /**
1526
   * alias: for "Arrayy->randomImmutable()"
1527
   *
1528
   * @see Arrayy::randomImmutable()
1529
   *
1530 3
   * @return static <p>(Immutable)</p>
1531
   */
1532 3
  public function getRandom()
1533 3
  {
1534
    return $this->randomImmutable();
1535
  }
1536 3
1537
  /**
1538 3
   * alias: for "Arrayy->randomKey()"
1539 3
   *
1540
   * @see Arrayy::randomKey()
1541 3
   *
1542
   * @return mixed <p>Get a key/index or null if there wasn't a key/index.</p>
1543
   */
1544
  public function getRandomKey()
1545 3
  {
1546 3
    return $this->randomKey();
1547 3
  }
1548
1549
  /**
1550 3
   * alias: for "Arrayy->randomKeys()"
1551 2
   *
1552 1
   * @see Arrayy::randomKeys()
1553 1
   *
1554 1
   * @param int $number
1555 1
   *
1556 1
   * @return static <p>(Immutable)</p>
1557
   */
1558 2
  public function getRandomKeys($number)
1559
  {
1560 3
    return $this->randomKeys($number);
1561
  }
1562 3
1563
  /**
1564
   * alias: for "Arrayy->randomValue()"
1565
   *
1566
   * @see Arrayy::randomValue()
1567
   *
1568
   * @return mixed <p>get a random value or null if there wasn't a value.</p>
1569
   */
1570
  public function getRandomValue()
1571
  {
1572 22
    return $this->randomValue();
1573
  }
1574
1575 22
  /**
1576
   * alias: for "Arrayy->randomValues()"
1577 22
   *
1578
   * @see Arrayy::randomValues()
1579
   *
1580
   * @param int $number
1581
   *
1582
   * @return static <p>(Immutable)</p>
1583
   */
1584
  public function getRandomValues($number)
1585
  {
1586
    return $this->randomValues($number);
1587 27
  }
1588
1589 27
  /**
1590
   * Group values from a array according to the results of a closure.
1591
   *
1592
   * @param string $grouper <p>A callable function name.</p>
1593
   * @param bool   $saveKeys
1594
   *
1595
   * @return static <p>(Immutable)</p>
1596
   */
1597
  public function group($grouper, $saveKeys = false)
1598
  {
1599
    $array = (array)$this->array;
1600
    $result = array();
1601
1602
    // Iterate over values, group by property/results from closure
1603 3
    foreach ($array as $key => $value) {
1604
1605 3
      $groupKey = is_callable($grouper) ? $grouper($value, $key) : $this->get($grouper, null, $value);
1606
      $newValue = $this->get($groupKey, null, $result);
1607 3
1608 3
      if ($groupKey instanceof self) {
1609 2
        $groupKey = $groupKey->getArray();
1610 2
      }
1611 3
1612
      if ($newValue instanceof self) {
1613 3
        $newValue = $newValue->getArray();
1614
      }
1615
1616
      // Add to results
1617
      if ($groupKey !== null) {
1618
        if ($saveKeys) {
1619
          $result[$groupKey] = $newValue;
1620
          $result[$groupKey][$key] = $value;
1621
        } else {
1622
          $result[$groupKey] = $newValue;
1623
          $result[$groupKey][] = $value;
1624
        }
1625 4
      }
1626
1627 4
    }
1628
1629
    return static::create($result);
1630
  }
1631
1632
  /**
1633
   * Check if an array has a given key.
1634
   *
1635
   * @param mixed $key
1636
   *
1637 12
   * @return bool
1638
   */
1639 12
  public function has($key)
1640
  {
1641 12
    // Generate unique string to use as marker.
1642
    $unFound = (string)uniqid('arrayy', true);
1643
1644
    return $this->get($key, $unFound) !== $unFound;
1645
  }
1646
1647 406
  /**
1648
   * Implodes an array.
1649 406
   *
1650
   * @param string $glue
1651 406
   *
1652
   * @return string
1653
   */
1654 406
  public function implode($glue = '')
1655
  {
1656
    return self::implode_recursive($glue, $this->array);
1657
  }
1658
1659
  /**
1660
   * @param string $glue
1661
   * @param string|array $pieces
1662
   *
1663 18
   * @return string
1664
   */
1665 18
  protected static function implode_recursive($glue = '', $pieces) {
1666
    if (is_array($pieces)) {
1667
      return implode(
1668 18
          $glue,
1669
          array_map(
1670
              array('self', 'implode_recursive'),
1671
              array_fill(0, count($pieces), $glue),
1672
              $pieces
1673
          )
1674
      );
1675
    }
1676
1677
    return $pieces;
1678 18
  }
1679
1680 18
  /**
1681
   * Given a list and an iterate-function that returns
1682 18
   * a key for each element in the list (or a property name),
1683
   * returns an object with an index of each item.
1684
   *
1685
   * Just like groupBy, but for when you know your keys are unique.
1686
   *
1687
   * @param mixed $key
1688
   *
1689
   * @return static <p>(Immutable)</p>
1690
   */
1691
  public function indexBy($key)
1692
  {
1693 30
    $results = array();
1694
1695 30
    foreach ($this->array as $a) {
1696
      if (\array_key_exists($key, $a) === true) {
1697
        $results[$a[$key]] = $a;
1698
      }
1699
    }
1700 30
1701 30
    return static::create($results);
1702
  }
1703
1704 30
  /**
1705 3
   * alias: for "Arrayy->searchIndex()"
1706
   *
1707
   * @see Arrayy::searchIndex()
1708
   *
1709
   * @param mixed $value <p>The value to search for.</p>
1710 3
   *
1711
   * @return mixed
1712
   */
1713
  public function indexOf($value)
1714 3
  {
1715 3
    return $this->searchIndex($value);
1716
  }
1717 30
1718
  /**
1719 30
   * Get everything but the last..$to items.
1720
   *
1721
   * @param int $to
1722
   *
1723
   * @return static <p>(Immutable)</p>
1724
   */
1725
  public function initial($to = 1)
1726
  {
1727
    $slice = count($this->array) - $to;
1728
1729 2
    return $this->firstsImmutable($slice);
1730
  }
1731 2
1732
  /**
1733
   * @param mixed $value
1734
   */
1735
  protected function internalGetArray(&$value)
1736
  {
1737
    if ($value instanceof self) {
1738
1739
      $valueTmp = $value->getArray();
1740
      if (count($valueTmp) === 0) {
1741 1
        $value = array();
1742
      } else {
1743 1
        $value &= $valueTmp;
1744
      }
1745
1746
    } 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...
1747
      $value &= $value->jsonSerialize();
1748
    }
1749
  }
1750
1751
  /**
1752
   * Internal mechanics of remove method.
1753
   *
1754 1
   * @param string $key
1755
   *
1756
   * @return boolean
1757 1
   */
1758 1
  protected function internalRemove($key)
1759 1
  {
1760
    $path = explode($this->pathSeparator, (string)$key);
1761
1762 1
    // Crawl though the keys
1763 1
    while (count($path) > 1) {
1764 1
      $key = \array_shift($path);
1765 1
1766
      if (!$this->has($key)) {
1767
        return false;
1768 1
      }
1769
1770
      $this->array = &$this->array[$key];
1771
    }
1772
1773
    $key = \array_shift($path);
1774
1775
    unset($this->array[$key]);
1776 15
1777
    return true;
1778 15
  }
1779 3
1780
  /**
1781
   * Internal mechanic of set method.
1782 13
   *
1783 13
   * @param string $key
1784 11
   * @param mixed  $value
1785
   *
1786 3
   * @return bool
1787
   */
1788 3
  protected function internalSet($key, $value)
1789
  {
1790
    if ($key === null) {
1791
      return false;
1792
    }
1793
1794
    // init
1795
    $array =& $this->array;
1796 88
    $path = explode($this->pathSeparator, (string)$key);
1797
1798 88
    // Crawl through the keys
1799
    while (count($path) > 1) {
1800
      $key = \array_shift($path);
1801
1802
      // If the key doesn't exist at this depth, we will just create an empty array
1803
      // to hold the next value, allowing us to create the arrays to hold final
1804
      // values at the correct depth. Then we'll keep digging into the array.
1805
      if (!isset($array[$key]) || !is_array($array[$key])) {
1806
        $array[$key] = static::create(array());
1807
      }
1808
1809
      $array =& $array[$key];
1810
    }
1811
1812
    $array[\array_shift($path)] = $value;
1813
1814
    return true;
1815
  }
1816
1817
  /**
1818 14
   * Return an array with all elements found in input array.
1819
   *
1820 14
   * @param array $search
1821
   *
1822
   * @return static <p>(Immutable)</p>
1823
   */
1824
  public function intersection(array $search)
1825
  {
1826
    return static::create(\array_values(\array_intersect($this->array, $search)));
1827
  }
1828 5
1829
  /**
1830 5
   * Return a boolean flag which indicates whether the two input arrays have any common elements.
1831 2
   *
1832
   * @param array $search
1833
   *
1834 4
   * @return bool
1835 4
   */
1836 2
  public function intersects(array $search)
1837
  {
1838 3
    return count($this->intersection($search)->array) > 0;
1839
  }
1840 2
1841
  /**
1842
   * Invoke a function on all of an array's values.
1843
   *
1844
   * @param mixed $callable
1845
   * @param mixed $arguments
1846
   *
1847
   * @return static <p>(Immutable)</p>
1848 1
   */
1849
  public function invoke($callable, $arguments = array())
1850 1
  {
1851
    // If one argument given for each iteration, create an array for it.
1852
    if (!is_array($arguments)) {
1853
      $arguments = StaticArrayy::repeat($arguments, count($this->array))->getArray();
1854
    }
1855
1856
    // If the callable has arguments, pass them.
1857
    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...
1858
      $array = \array_map($callable, $this->array, $arguments);
1859
    } else {
1860
      $array = \array_map($callable, $this->array);
1861
    }
1862
1863
    return static::create($array);
1864
  }
1865
1866 25
  /**
1867
   * Check whether array is associative or not.
1868 25
   *
1869
   * @return bool <p>Returns true if associative, false otherwise.</p>
1870
   */
1871
  public function isAssoc()
1872
  {
1873
    if ($this->isEmpty()) {
1874
      return false;
1875
    }
1876
1877
    foreach ($this->keys()->getArray() as $key) {
1878
      if (!is_string($key)) {
1879
        return false;
1880
      }
1881
    }
1882 4
1883
    return true;
1884 4
  }
1885
1886 4
  /**
1887
   * Check whether the array is empty or not.
1888
   *
1889
   * @return bool <p>Returns true if empty, false otherwise.</p>
1890
   */
1891
  public function isEmpty()
1892
  {
1893
    return !$this->array;
1894 4
  }
1895
1896 4
  /**
1897
   * Check if the current array is equal to the given "$array" or not.
1898
   *
1899
   * @param array $array
1900
   *
1901
   * @return bool
1902
   */
1903
  public function isEqual(array $array)
1904
  {
1905
    return ($this->array === $array);
1906 13
  }
1907
1908 13
  /**
1909 1
   * Check if the current array is a multi-array.
1910
   *
1911
   * @return bool
1912 12
   */
1913 8
  public function isMultiArray()
1914
  {
1915 8
    return !(count($this->array) === count($this->array, COUNT_RECURSIVE));
1916 1
  }
1917 1
1918 7
  /**
1919
   * Check whether array is numeric or not.
1920
   *
1921 8
   * @return bool <p>Returns true if numeric, false otherwise.</p>
1922 8
   */
1923 4
  public function isNumeric()
1924 4
  {
1925
    if ($this->isEmpty()) {
1926
      return false;
1927 12
    }
1928
1929
    foreach ($this->keys() as $key) {
1930
      if (!is_int($key)) {
1931
        return false;
1932
      }
1933
    }
1934
1935
    return true;
1936
  }
1937 13
1938
  /**
1939 13
   * Check if the current array is sequential [0, 1, 2, 3, 4, 5 ...] or not.
1940 1
   *
1941
   * @return bool
1942
   */
1943 12
  public function isSequential()
1944 8
  {
1945
    return \array_keys($this->array) === range(0, count($this->array) - 1);
1946 8
  }
1947 1
1948 1
  /**
1949 7
   * @return array
1950
   */
1951
  public function jsonSerialize()
1952 8
  {
1953 8
    return $this->getArray();
1954 4
  }
1955 4
1956
  /**
1957
   * Get all keys from the current array.
1958 12
   *
1959
   * @return static <p>(Immutable)</p>
1960
   */
1961
  public function keys()
1962
  {
1963
    return static::create(\array_keys($this->array));
1964
  }
1965
1966
  /**
1967
   * Sort an array by key in reverse order.
1968
   *
1969
   * @param int $sort_flags [optional] <p>
1970 10
   *                        You may modify the behavior of the sort using the optional
1971
   *                        parameter sort_flags, for details
1972 10
   *                        see sort.
1973
   *                        </p>
1974
   *
1975
   * @return static <p>(Mutable) Return this Arrayy object.</p>
1976
   */
1977
  public function krsort($sort_flags = null)
1978
  {
1979
    krsort($this->array, $sort_flags);
1980
1981
    return $this;
1982
  }
1983 4
1984
  /**
1985 4
   * Get the last value from the current array.
1986
   *
1987 4
   * @return mixed <p>Return null if there wasn't a element.</p>
1988
   */
1989
  public function last()
1990
  {
1991
    return $this->pop();
1992
  }
1993
1994
  /**
1995
   * Get the last value(s) from the current array.
1996
   *
1997 15
   * @param int|null $number
1998
   *
1999 15
   * @return static <p>(Immutable)</p>
2000 2
   */
2001
  public function lastsImmutable($number = null)
2002
  {
2003
    if ($this->isEmpty()) {
2004 13
      return static::create();
2005
    }
2006 13
2007 13
    if ($number === null) {
2008
      $poppedValue = $this->pop();
2009 13
2010 7
      if ($poppedValue === null) {
2011
        $poppedValue = array($poppedValue);
2012 9
      } else {
2013
        $poppedValue = (array)$poppedValue;
2014 7
      }
2015
2016
      $arrayy = static::create($poppedValue);
2017
    } else {
2018
      $number = (int)$number;
2019
      $arrayy = $this->rest(-$number);
2020
    }
2021
2022
    return $arrayy;
2023
  }
2024 14
2025
  /**
2026 14
   * Get the last value(s) from the current array.
2027 2
   *
2028
   * @param int|null $number
2029
   *
2030
   * @return static <p>(Mutable)</p>
2031 12
   */
2032
  public function lastsMutable($number = null)
2033 12
  {
2034 12
    if ($this->isEmpty()) {
2035
      return $this;
2036 12
    }
2037 9
2038
    if ($number === null) {
2039 5
      $poppedValue = $this->pop();
2040
2041 4
      if ($poppedValue === null) {
2042
        $poppedValue = array($poppedValue);
2043
      } else {
2044
        $poppedValue = (array)$poppedValue;
2045
      }
2046
2047
      $this->array = static::create($poppedValue)->array;
2048
    } else {
2049 10
      $number = (int)$number;
2050
      $this->array = $this->rest(-$number)->array;
2051 10
    }
2052 1
2053
    return $this;
2054
  }
2055 9
2056
  /**
2057
   * Count the values from the current array.
2058
   *
2059
   * alias: for "Arrayy->size()"
2060
   *
2061
   * @see Arrayy::size()
2062
   *
2063
   * @return int
2064
   */
2065
  public function length()
2066
  {
2067
    return $this->size();
2068 25
  }
2069
2070 25
  /**
2071 4
   * Apply the given function to the every element of the array,
2072 4
   * collecting the results.
2073 21
   *
2074
   * @param callable $callable
2075
   *
2076 25
   * @return static <p>(Immutable) Arrayy object with modified elements.</p>
2077
   */
2078
  public function map($callable)
2079
  {
2080
    $result = \array_map($callable, $this->array);
2081
2082
    return static::create($result);
2083
  }
2084
2085
  /**
2086
   * Check if all items in current array match a truth test.
2087
   *
2088
   * @param \Closure $closure
2089
   *
2090 16
   * @return bool
2091
   */
2092 16 View Code Duplication
  public function matches(\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...
2093 4
  {
2094 4
    if (count($this->array) === 0) {
2095 12
      return false;
2096
    }
2097
2098 16
    // init
2099
    $array = $this->array;
2100
2101
    foreach ($array as $key => $value) {
2102
      $value = $closure($value, $key);
2103
2104
      if ($value === false) {
2105
        return false;
2106
      }
2107
    }
2108
2109
    return true;
2110
  }
2111 16
2112
  /**
2113 16
   * Check if any item in the current array matches a truth test.
2114 4
   *
2115 4
   * @param \Closure $closure
2116 12
   *
2117
   * @return bool
2118
   */
2119 16 View Code Duplication
  public function matchesAny(\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...
2120
  {
2121
    if (count($this->array) === 0) {
2122
      return false;
2123
    }
2124
2125
    // init
2126
    $array = $this->array;
2127
2128
    foreach ($array as $key => $value) {
2129
      $value = $closure($value, $key);
2130
2131
      if ($value === true) {
2132
        return true;
2133 17
      }
2134
    }
2135 17
2136 4
    return false;
2137 4
  }
2138 13
2139
  /**
2140
   * Get the max value from an array.
2141 17
   *
2142
   * @return mixed
2143
   */
2144
  public function max()
2145
  {
2146
    if ($this->count() === 0) {
2147
      return false;
2148
    }
2149 10
2150
    return max($this->array);
2151 10
  }
2152 1
2153
  /**
2154
   * Merge the new $array into the current array.
2155 9
   *
2156
   * - keep key,value from the current array, also if the index is in the new $array
2157
   *
2158
   * @param array $array
2159
   * @param bool  $recursive
2160
   *
2161
   * @return static <p>(Immutable)</p>
2162
   */
2163 View Code Duplication
  public function mergeAppendKeepIndex(array $array = array(), $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...
2164
  {
2165
    if (true === $recursive) {
2166
      $result = \array_replace_recursive($this->array, $array);
2167
    } else {
2168 1
      $result = \array_replace($this->array, $array);
2169
    }
2170 1
2171
    return static::create($result);
2172 1
  }
2173 1
2174 1
  /**
2175 1
   * Merge the new $array into the current array.
2176 1
   *
2177 1
   * - replace duplicate assoc-keys from the current array with the key,values from the new $array
2178 1
   * - create new indexes
2179 1
   *
2180 1
   * @param array $array
2181 1
   * @param bool  $recursive
2182 1
   *
2183 1
   * @return static <p>(Immutable)</p>
2184 1
   */
2185 1 View Code Duplication
  public function mergeAppendNewIndex(array $array = array(), $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...
2186 1
  {
2187 1
    if (true === $recursive) {
2188 1
      $result = \array_merge_recursive($this->array, $array);
2189 1
    } else {
2190
      $result = \array_merge($this->array, $array);
2191
    }
2192
2193 1
    return static::create($result);
2194
  }
2195
2196
  /**
2197
   * Merge the the current array into the $array.
2198
   *
2199
   * - use key,value from the new $array, also if the index is in the current array
2200
   *
2201
   * @param array $array
2202
   * @param bool  $recursive
2203
   *
2204
   * @return static <p>(Immutable)</p>
2205
   */
2206 View Code Duplication
  public function mergePrependKeepIndex(array $array = array(), $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...
2207
  {
2208
    if (true === $recursive) {
2209
      $result = \array_replace_recursive($array, $this->array);
2210
    } else {
2211
      $result = \array_replace($array, $this->array);
2212
    }
2213
2214
    return static::create($result);
2215
  }
2216
2217
  /**
2218 4
   * Merge the current array into the new $array.
2219
   *
2220 4
   * - replace duplicate assoc-keys from new $array with the key,values from the current array
2221
   * - create new indexes
2222 4
   *
2223
   * @param array $array
2224
   * @param bool  $recursive
2225
   *
2226
   * @return static <p>(Immutable)</p>
2227
   */
2228 View Code Duplication
  public function mergePrependNewIndex(array $array = array(), $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...
2229
  {
2230 16
    if (true === $recursive) {
2231
      $result = \array_merge_recursive($array, $this->array);
2232 16
    } else {
2233
      $result = \array_merge($array, $this->array);
2234
    }
2235
2236
    return static::create($result);
2237
  }
2238
2239
  /**
2240
   * Get the min value from an array.
2241
   *
2242
   * @return mixed
2243 8
   */
2244
  public function min()
2245 8
  {
2246 8
    if ($this->count() === 0) {
2247 8
      return false;
2248
    }
2249 1
2250
    return min($this->array);
2251
  }
2252 8
2253
  /**
2254
   * Move an array element to a new index.
2255
   *
2256
   * cherry-picked from: http://stackoverflow.com/questions/12624153/move-an-array-element-to-a-new-index-in-php
2257
   *
2258
   * @param int|string $from
2259
   * @param int|string $to
2260 4
   *
2261
   * @return static <p>(Immutable)</p>
2262 4
   */
2263 4
  public function moveElement($from, $to)
2264 4
  {
2265 4
    $array = $this->array;
2266
2267 4
    if (is_int($from)) {
2268
      $tmp = \array_splice($array, $from, 1);
2269
      \array_splice($array, $to, 0, $tmp);
2270
      $output = $array;
2271
    } elseif (is_string($from)) {
2272
      $indexToMove = \array_search($from, \array_keys($array), true);
2273
      $itemToMove = $array[$from];
2274
      \array_splice($array, $indexToMove, 1);
2275
      $i = 0;
2276
      $output = array();
2277 17
      foreach ($array as $key => $item) {
2278
        if ($i == $to) {
2279 17
          $output[$from] = $itemToMove;
2280
        }
2281
        $output[$key] = $item;
2282
        $i++;
2283 17
      }
2284 14
    } else {
2285
      $output = array();
2286 14
    }
2287
2288
    return static::create($output);
2289 5
  }
2290 5
2291
  /**
2292 5
   * Get a subset of the items from the given array.
2293
   *
2294
   * @param mixed[] $keys
2295
   *
2296
   * @return static <p>(Immutable)</p>
2297
   */
2298
  public function only(array $keys)
2299
  {
2300
    $array = $this->array;
2301
2302 4
    return static::create(\array_intersect_key($array, \array_flip($keys)));
2303
  }
2304 4
2305
  /**
2306 4
   * Pad array to the specified size with a given value.
2307
   *
2308
   * @param int   $size  <p>Size of the result array.</p>
2309
   * @param mixed $value <p>Empty value by default.</p>
2310 4
   *
2311
   * @return static <p>(Immutable) Arrayy object padded to $size with $value.</p>
2312
   */
2313
  public function pad($size, $value)
2314
  {
2315
    $result = \array_pad($this->array, $size, $value);
2316
2317
    return static::create($result);
2318
  }
2319
2320
  /**
2321
   * Pop a specified value off the end of the current array.
2322 14
   *
2323
   * @return mixed <p>(Mutable) The popped element from the current array.</p>
2324 14
   */
2325 14
  public function pop()
2326
  {
2327 14
    return \array_pop($this->array);
2328 3
  }
2329 3
2330 3
  /**
2331 3
   * Prepend a value to the current array.
2332
   *
2333 3
   * @param mixed $value
2334 3
   * @param mixed $key
2335
   *
2336
   * @return static <p>(Mutable) Return this Arrayy object, with the prepended value.</p>
2337 11
   */
2338
  public function prepend($value, $key = null)
2339 11
  {
2340
    if ($key === null) {
2341
      \array_unshift($this->array, $value);
2342
    } else {
2343
      /** @noinspection AdditionOperationOnArraysInspection */
2344
      $this->array = array($key => $value) + $this->array;
2345
    }
2346
2347
    return $this;
2348
  }
2349 17
2350
  /**
2351 17
   * Push one or more values onto the end of array at once.
2352
   *
2353
   * @return static <p>(Mutable) Return this Arrayy object, with pushed elements to the end of array.</p>
2354
   */
2355 17 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...
2356 7
  {
2357 7
    if (func_num_args()) {
2358
      $args = \array_merge(array(&$this->array), func_get_args());
2359 7
      if (Bootup::is_php('5.6')) {
2360
        /** @noinspection PhpLanguageLevelInspection */
2361
        array_push(...$args);
2362 11
      } else {
2363
        /** @noinspection ArgumentUnpackingCanBeUsedInspection */
2364 11
        call_user_func_array('array_push', $args);
2365
      }
2366
    }
2367
2368
    return $this;
2369
  }
2370
2371
  /**
2372 4
   * Get a random value from the current array.
2373
   *
2374 4
   * @param null|int $number <p>How many values you will take?</p>
2375
   *
2376 4
   * @return static <p>(Immutable)</p>
2377
   */
2378
  public function randomImmutable($number = null)
2379
  {
2380 4
    if ($this->count() === 0) {
2381
      return static::create();
2382
    }
2383
2384 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...
2385
      $arrayRandValue = array($this->array[\array_rand($this->array)]);
2386
2387
      return static::create($arrayRandValue);
2388
    }
2389
2390 7
    $arrayTmp = $this->array;
2391
    shuffle($arrayTmp);
2392 7
2393
    return static::create($arrayTmp)->firstsImmutable($number);
2394 7
  }
2395
2396
  /**
2397
   * Pick a random key/index from the keys of this array.
2398
   *
2399
   * @return mixed <p>Get a key/index or null if there wasn't a key/index.</p>
2400
   *
2401
   * @throws \RangeException If array is empty
2402
   */
2403
  public function randomKey()
2404
  {
2405
    $result = $this->randomKeys(1);
2406
2407 9
    if (!isset($result[0])) {
2408
      $result[0] = null;
2409 9
    }
2410 9
2411 9
    return $result[0];
2412 2
  }
2413 1
2414 1
  /**
2415 2
   * Pick a given number of random keys/indexes out of this array.
2416 9
   *
2417
   * @param int $number <p>The number of keys/indexes (should be <= $this->count())</p>
2418 9
   *
2419
   * @return static <p>(Immutable)</p>
2420
   *
2421
   * @throws \RangeException If array is empty
2422
   */
2423
  public function randomKeys($number)
2424
  {
2425
    $number = (int)$number;
2426
    $count = $this->count();
2427
2428
    if ($number === 0 || $number > $count) {
2429 4
      throw new \RangeException(
2430
          sprintf(
2431 4
              'Number of requested keys (%s) must be equal or lower than number of elements in this array (%s)',
2432
              $number,
2433 4
              $count
2434
          )
2435
      );
2436 4
    }
2437
2438
    $result = (array)\array_rand($this->array, $number);
2439 4
2440
    return static::create($result);
2441
  }
2442
2443
  /**
2444
   * Get a random value from the current array.
2445
   *
2446
   * @param null|int $number <p>How many values you will take?</p>
2447 9
   *
2448
   * @return static <p>(Mutable)</p>
2449 9
   */
2450
  public function randomMutable($number = null)
2451 9
  {
2452
    if ($this->count() === 0) {
2453
      return static::create();
2454
    }
2455
2456 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...
2457
      $arrayRandValue = array($this->array[\array_rand($this->array)]);
2458
      $this->array = $arrayRandValue;
2459
2460
      return $this;
2461 1
    }
2462
2463 1
    shuffle($this->array);
2464
2465 1
    return $this->firstsMutable($number);
2466 1
  }
2467 1
2468 1
  /**
2469 1
   * Pick a random value from the values of this array.
2470
   *
2471 1
   * @return mixed <p>Get a random value or null if there wasn't a value.</p>
2472
   */
2473
  public function randomValue()
2474
  {
2475
    $result = $this->randomImmutable();
2476
2477
    if (!isset($result[0])) {
2478
      $result[0] = null;
2479
    }
2480
2481 18
    return $result[0];
2482
  }
2483
2484 18
  /**
2485
   * Pick a given number of random values out of this array.
2486
   *
2487
   * @param int $number
2488
   *
2489
   * @return static <p>(Mutable)</p>
2490
   */
2491
  public function randomValues($number)
2492 18
  {
2493
    $number = (int)$number;
2494 18
2495
    return $this->randomMutable($number);
2496
  }
2497
2498
  /**
2499
   * Get a random value from an array, with the ability to skew the results.
2500
   *
2501
   * Example: randomWeighted(['foo' => 1, 'bar' => 2]) has a 66% chance of returning bar.
2502 7
   *
2503
   * @param array    $array
2504 7
   * @param null|int $number <p>How many values you will take?</p>
2505 7
   *
2506
   * @return static <p>(Immutable)</p>
2507 7
   */
2508
  public function randomWeighted(array $array, $number = null)
2509
  {
2510
    $options = array();
2511
    foreach ($array as $option => $weight) {
2512
      if ($this->searchIndex($option) !== false) {
2513
        for ($i = 0; $i < $weight; ++$i) {
2514
          $options[] = $option;
2515 7
        }
2516
      }
2517 7
    }
2518 7
2519
    return $this->mergeAppendKeepIndex($options)->randomImmutable($number);
2520 7
  }
2521
2522
  /**
2523
   * Reduce the current array via callable e.g. anonymous-function.
2524
   *
2525
   * @param mixed $callable
2526
   * @param array $init
2527
   *
2528
   * @return static <p>(Immutable)</p>
2529
   */
2530 7
  public function reduce($callable, array $init = array())
2531
  {
2532 7
    $result = \array_reduce($this->array, $callable, $init);
2533 7
2534 6
    if ($result === null) {
2535 6
      $this->array = array();
2536
    } else {
2537
      $this->array = (array)$result;
2538 6
    }
2539 6
2540 7
    return static::create($this->array);
2541
  }
2542 7
2543 7
  /**
2544 7
   * Create a numerically re-indexed Arrayy object.
2545
   *
2546 7
   * @return static <p>(Mutable) Return this Arrayy object, with re-indexed array-elements.</p>
2547
   */
2548
  public function reindex()
2549
  {
2550
    $this->array = \array_values($this->array);
2551
2552
    return $this;
2553
  }
2554
2555
  /**
2556 1
   * Return all items that fail the truth test.
2557
   *
2558 1
   * @param \Closure $closure
2559 1
   *
2560
   * @return static <p>(Immutable)</p>
2561
   */
2562 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...
2563
  {
2564
    $filtered = array();
2565
2566
    foreach ($this->array as $key => $value) {
2567
      if (!$closure($value, $key)) {
2568
        $filtered[$key] = $value;
2569
      }
2570
    }
2571
2572
    return static::create($filtered);
2573
  }
2574 2
2575
  /**
2576 2
   * Remove a value from the current array (optional using dot-notation).
2577
   *
2578 2
   * @param mixed $key
2579
   *
2580
   * @return static <p>(Immutable)</p>
2581
   */
2582
  public function remove($key)
2583
  {
2584
    // Recursive call
2585
    if (is_array($key)) {
2586
      foreach ($key as $k) {
2587
        $this->internalRemove($k);
2588 2
      }
2589
2590 2
      return static::create($this->array);
2591
    }
2592 2
2593
    $this->internalRemove($key);
2594
2595
    return static::create($this->array);
2596
  }
2597
2598
  /**
2599
   * Remove the first value from the current array.
2600
   *
2601
   * @return static <p>(Immutable)</p>
2602 2
   */
2603
  public function removeFirst()
2604 2
  {
2605
    $tmpArray = $this->array;
2606 2
    \array_shift($tmpArray);
2607
2608
    return static::create($tmpArray);
2609
  }
2610
2611
  /**
2612
   * Remove the last value from the current array.
2613
   *
2614
   * @return static <p>(Immutable)</p>
2615
   */
2616 1
  public function removeLast()
2617
  {
2618 1
    $tmpArray = $this->array;
2619 1
    \array_pop($tmpArray);
2620
2621 1
    return static::create($tmpArray);
2622
  }
2623
2624
  /**
2625
   * Removes a particular value from an array (numeric or associative).
2626
   *
2627
   * @param mixed $value
2628
   *
2629
   * @return static <p>(Immutable)</p>
2630
   */
2631
  public function removeValue($value)
2632 3
  {
2633
    $isNumericArray = true;
2634 3
    foreach ($this->array as $key => $item) {
2635 3
      if ($item === $value) {
2636
        if (!is_int($key)) {
2637 3
          $isNumericArray = false;
2638 3
        }
2639 3
        unset($this->array[$key]);
2640
      }
2641 3
    }
2642
2643
    if ($isNumericArray) {
2644
      $this->array = \array_values($this->array);
2645
    }
2646
2647
    return static::create($this->array);
2648
  }
2649
2650
  /**
2651
   * Generate array of repeated arrays.
2652 1
   *
2653
   * @param int $times <p>How many times has to be repeated.</p>
2654 1
   *
2655
   * @return Arrayy
2656 1
   */
2657
  public function repeat($times)
2658 1
  {
2659
    if ($times === 0) {
2660 1
      return new static();
2661
    }
2662
2663
    return static::create(\array_fill(0, (int)$times, $this->array));
2664
  }
2665
2666
  /**
2667
   * Replace a key with a new key/value pair.
2668
   *
2669
   * @param $replace
2670 15
   * @param $key
2671
   * @param $value
2672 15
   *
2673
   * @return static <p>(Immutable)</p>
2674 15
   */
2675
  public function replace($replace, $key, $value)
2676
  {
2677
    $this->remove($replace);
2678
2679
    return $this->set($key, $value);
2680
  }
2681
2682 8
  /**
2683
   * Create an array using the current array as values and the other array as keys.
2684 8
   *
2685
   * @param array $keys <p>An array of keys.</p>
2686 8
   *
2687
   * @return static <p>(Immutable) Arrayy object with keys from the other array.</p>
2688
   */
2689
  public function replaceAllKeys(array $keys)
2690
  {
2691
    $result = \array_combine($keys, $this->array);
2692
2693
    return static::create($result);
2694
  }
2695
2696
  /**
2697
   * Create an array using the current array as keys and the other array as values.
2698
   *
2699
   * @param array $array <p>An array o values.</p>
2700 4
   *
2701
   * @return static <p>(Immutable) Arrayy object with values from the other array.</p>
2702 4
   */
2703
  public function replaceAllValues(array $array)
2704 4
  {
2705
    $result = \array_combine($this->array, $array);
2706
2707
    return static::create($result);
2708
  }
2709
2710
  /**
2711
   * Replace the keys in an array with another set.
2712
   *
2713
   * @param array $keys <p>An array of keys matching the array's size</p>
2714 20
   *
2715
   * @return static <p>(Immutable)</p>
2716 20
   */
2717
  public function replaceKeys(array $keys)
2718
  {
2719
    $values = \array_values($this->array);
2720
    $result = \array_combine($keys, $values);
2721
2722
    return static::create($result);
2723
  }
2724
2725
  /**
2726 9
   * Replace the first matched value in an array.
2727
   *
2728
   * @param mixed $search
2729 9
   * @param mixed $replacement
2730
   *
2731 9
   * @return static <p>(Immutable)</p>
2732
   */
2733
  public function replaceOneValue($search, $replacement = '')
2734
  {
2735
    $array = $this->array;
2736 9
    $key = \array_search($search, $array, true);
2737 1
2738 1
    if ($key !== false) {
2739
      $array[$key] = $replacement;
2740 9
    }
2741 7
2742 7
    return static::create($array);
2743
  }
2744
2745 9
  /**
2746
   * Replace values in the current array.
2747
   *
2748
   * @param string $search      <p>The string to replace.</p>
2749
   * @param string $replacement <p>What to replace it with.</p>
2750
   *
2751
   * @return static <p>(Immutable)</p>
2752
   */
2753
  public function replaceValues($search, $replacement = '')
2754
  {
2755
    $array = $this->each(
2756 17
        function ($value) use ($search, $replacement) {
2757
          return UTF8::str_replace($search, $replacement, $value);
2758 17
        }
2759
    );
2760 17
2761
    return $array;
2762
  }
2763
2764
  /**
2765
   * Get the last elements from index $from until the end of this array.
2766
   *
2767
   * @param int $from
2768
   *
2769
   * @return static <p>(Immutable)</p>
2770
   */
2771
  public function rest($from = 1)
2772
  {
2773 11
    $tmpArray = $this->array;
2774
2775
    return static::create(\array_splice($tmpArray, $from));
2776 11
  }
2777 4
2778 4
  /**
2779
   * Return the array in the reverse order.
2780 11
   *
2781
   * @return static <p>(Mutable) Return this Arrayy object.</p>
2782
   */
2783
  public function reverse()
2784
  {
2785
    $this->array = \array_reverse($this->array);
2786
2787
    return $this;
2788 4
  }
2789
2790 4
  /**
2791
   * Sort an array in reverse order.
2792
   *
2793
   * @param int $sort_flags [optional] <p>
2794
   *                        You may modify the behavior of the sort using the optional
2795
   *                        parameter sort_flags, for details
2796
   *                        see sort.
2797
   *                        </p>
2798 1
   *
2799
   * @return static <p>(Mutable) Return this Arrayy object.</p>
2800 1
   */
2801
  public function rsort($sort_flags = null)
2802 1
  {
2803
    rsort($this->array, $sort_flags);
2804 1
2805
    return $this;
2806
  }
2807
2808
  /**
2809
   * Search for the first index of the current array via $value.
2810
   *
2811
   * @param mixed $value
2812 93
   *
2813
   * @return int|float|string
2814 93
   */
2815
  public function searchIndex($value)
2816
  {
2817
    return \array_search($value, $this->array, true);
2818
  }
2819
2820
  /**
2821
   * Search for the value of the current array via $index.
2822
   *
2823
   * @param mixed $index
2824
   *
2825
   * @return static <p>(Immutable) Will return a empty Arrayy if the value wasn't found.</p>
2826 4
   */
2827
  public function searchValue($index)
2828 4
  {
2829
    // init
2830 4
    $return = array();
2831
2832
    if ($this->isEmpty()) {
2833
      return static::create();
2834
    }
2835
2836
    // php cast "bool"-index into "int"-index
2837
    if ((bool)$index === $index) {
2838
      $index = (int)$index;
2839
    }
2840
2841
    if (\array_key_exists($index, $this->array) === true) {
2842
      $return = array($this->array[$index]);
2843 19
    }
2844
2845 19
2846
    return static::create($return);
2847 19
  }
2848
2849
  /**
2850
   * Set a value for the current array (optional using dot-notation).
2851
   *
2852
   * @param string $key   <p>The key to set.</p>
2853
   * @param mixed  $value <p>Its value.</p>
2854
   *
2855
   * @return static <p>(Immutable)</p>
2856
   */
2857
  public function set($key, $value)
2858
  {
2859
    $this->internalSet($key, $value);
2860
2861
    return static::create($this->array);
2862 18
  }
2863
2864 18
  /**
2865
   * Get a value from a array and set it if it was not.
2866 18
   *
2867
   * WARNING: this method only set the value, if the $key is not already set
2868
   *
2869
   * @param string $key      <p>The key</p>
2870
   * @param mixed  $fallback <p>The default value to set if it isn't.</p>
2871
   *
2872
   * @return mixed <p>(Mutable)</p>
2873
   */
2874
  public function setAndGet($key, $fallback = null)
2875
  {
2876
    // If the key doesn't exist, set it.
2877 1
    if (!$this->has($key)) {
2878
      $this->array = $this->set($key, $fallback)->getArray();
2879 1
    }
2880
2881
    return $this->get($key);
2882
  }
2883
2884
  /**
2885
   * Shifts a specified value off the beginning of array.
2886
   *
2887
   * @return mixed <p>(Mutable) A shifted element from the current array.</p>
2888
   */
2889
  public function shift()
2890 1
  {
2891
    return \array_shift($this->array);
2892 1
  }
2893
2894
  /**
2895
   * Shuffle the current array.
2896
   *
2897
   * @return static <p>(Immutable)</p>
2898
   */
2899
  public function shuffle()
2900
  {
2901
    $array = $this->array;
2902
2903
    shuffle($array);
2904
2905
    return static::create($array);
2906
  }
2907
2908 1
  /**
2909
   * Get the size of an array.
2910 1
   *
2911 1
   * @return int
2912
   */
2913
  public function size()
2914 1
  {
2915 1
    return count($this->array);
2916
  }
2917 1
2918 1
  /**
2919
   * Extract a slice of the array.
2920 1
   *
2921
   * @param int      $offset       <p>Slice begin index.</p>
2922 1
   * @param int|null $length       <p>Length of the slice.</p>
2923
   * @param bool     $preserveKeys <p>Whether array keys are preserved or no.</p>
2924 1
   *
2925 1
   * @return static <p>A slice of the original array with length $length.</p>
2926 1
   */
2927
  public function slice($offset, $length = null, $preserveKeys = false)
2928
  {
2929
    $result = \array_slice($this->array, $offset, $length, $preserveKeys);
2930 1
2931
    return static::create($result);
2932 1
  }
2933
2934
  /**
2935
   * Sort the current array and optional you can keep the keys.
2936
   *
2937
   * @param integer $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
2938
   * @param integer $strategy  <p>sort_flags => use e.g.: <strong>SORT_REGULAR</strong> (default) or
2939
   *                           <strong>SORT_NATURAL</strong></p>
2940
   * @param bool    $keepKeys
2941
   *
2942
   * @return static <p>(Mutable) Return this Arrayy object.</p>
2943
   */
2944 18
  public function sort($direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
2945
  {
2946 18
    $this->sorting($this->array, $direction, $strategy, $keepKeys);
2947
2948
    return $this;
2949 18
  }
2950 18
2951 6
  /**
2952 6
   * Sort the current array by key.
2953 13
   *
2954 13
   * @link http://php.net/manual/en/function.ksort.php
2955 13
   * @link http://php.net/manual/en/function.krsort.php
2956 13
   *
2957 13
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
2958
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
2959 18
   *                              <strong>SORT_NATURAL</strong></p>
2960
   *
2961
   * @return static <p>(Mutable) Return this Arrayy object.</p>
2962
   */
2963
  public function sortKeys($direction = SORT_ASC, $strategy = SORT_REGULAR)
2964
  {
2965
    $this->sorterKeys($this->array, $direction, $strategy);
2966
2967
    return $this;
2968
  }
2969
2970
  /**
2971 19
   * Sort the current array by value.
2972
   *
2973 19
   * @param int $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
2974
   * @param int $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or <strong>SORT_NATURAL</strong></p>
2975 19
   *
2976 19
   * @return static <p>(Mutable)</p>
2977 19
   */
2978
  public function sortValueKeepIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
2979
  {
2980 19
    return $this->sort($direction, $strategy, true);
2981 19
  }
2982 9
2983 5
  /**
2984 5
   * Sort the current array by value.
2985 4
   *
2986
   * @param int $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
2987 9
   * @param int $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or <strong>SORT_NATURAL</strong></p>
2988 10
   *
2989 10
   * @return static <p>(Mutable)</p>
2990 10
   */
2991 10
  public function sortValueNewIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
2992 4
  {
2993 4
    return $this->sort($direction, $strategy, false);
2994 6
  }
2995
2996 10
  /**
2997
   * Sort a array by value, by a closure or by a property.
2998 19
   *
2999
   * - If the sorter is null, the array is sorted naturally.
3000
   * - Associative (string) keys will be maintained, but numeric keys will be re-indexed.
3001
   *
3002
   * @param null       $sorter
3003
   * @param string|int $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3004
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3005
   *                              <strong>SORT_NATURAL</strong></p>
3006
   *
3007
   * @return static <p>(Immutable)</p>
3008
   */
3009 1
  public function sorter($sorter = null, $direction = SORT_ASC, $strategy = SORT_REGULAR)
3010
  {
3011 1
    $array = (array)$this->array;
3012
    $direction = $this->getDirection($direction);
3013 1
3014 1
    // Transform all values into their results.
3015 1
    if ($sorter) {
3016 1
      $arrayy = static::create($array);
3017 1
3018 1
      $that = $this;
3019
      $results = $arrayy->each(
3020
          function ($value) use ($sorter, $that) {
3021 1
            return is_callable($sorter) ? $sorter($value) : $that->get($sorter, null, $value);
3022
          }
3023
      );
3024
3025
      $results = $results->getArray();
3026
    } else {
3027
      $results = $array;
3028
    }
3029 1
3030
    // Sort by the results and replace by original values
3031 1
    \array_multisort($results, $direction, $strategy, $array);
3032
3033 1
    return static::create($array);
3034 1
  }
3035
3036
  /**
3037 1
   * sorting keys
3038
   *
3039 1
   * @param array $elements
3040
   * @param int   $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3041
   * @param int   $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or <strong>SORT_NATURAL</strong></p>
3042
   *
3043
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3044
   */
3045
  protected function sorterKeys(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR)
3046
  {
3047
    $direction = $this->getDirection($direction);
3048
3049
    switch ($direction) {
3050 1
      case 'desc':
3051
      case SORT_DESC:
3052 1
        krsort($elements, $strategy);
3053
        break;
3054 1
      case 'asc':
3055
      case SORT_ASC:
3056 1
      default:
3057
        ksort($elements, $strategy);
3058
    }
3059
3060
    return $this;
3061
  }
3062
3063
  /**
3064 142
   * @param array      &$elements
3065
   * @param int|string $direction <p>use <strong>SORT_ASC</strong> (default) or <strong>SORT_DESC</strong></p>
3066 142
   * @param int        $strategy  <p>use e.g.: <strong>SORT_REGULAR</strong> (default) or
3067
   *                              <strong>SORT_NATURAL</strong></p>
3068
   * @param bool       $keepKeys
3069
   *
3070
   * @return static <p>(Mutable) Return this Arrayy object.</p>
3071
   */
3072
  protected function sorting(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
3073
  {
3074
    $direction = $this->getDirection($direction);
3075
3076
    if (!$strategy) {
3077 6
      $strategy = SORT_REGULAR;
3078
    }
3079 6
3080
    switch ($direction) {
3081
      case 'desc':
3082
      case SORT_DESC:
3083
        if ($keepKeys) {
3084
          arsort($elements, $strategy);
3085
        } else {
3086
          rsort($elements, $strategy);
3087
        }
3088
        break;
3089 19
      case 'asc':
3090
      case SORT_ASC:
3091 19
      default:
3092
        if ($keepKeys) {
3093
          asort($elements, $strategy);
3094
        } else {
3095
          sort($elements, $strategy);
3096
        }
3097
    }
3098
3099 9
    return $this;
3100
  }
3101
3102
  /**
3103 9
   * Split an array in the given amount of pieces.
3104 9
   *
3105
   * @param int  $numberOfPieces
3106 8
   * @param bool $keepKeys
3107 8
   *
3108 8
   * @return static <p>(Immutable)</p>
3109
   */
3110 8
  public function split($numberOfPieces = 2, $keepKeys = false)
3111 9
  {
3112 9
    $arrayCount = $this->count();
3113 9
3114
    if ($arrayCount === 0) {
3115 9
      $result = array();
3116
    } else {
3117
      $numberOfPieces = (int)$numberOfPieces;
3118 9
      $splitSize = (int)ceil($arrayCount / $numberOfPieces);
3119
      $result = \array_chunk($this->array, $splitSize, $keepKeys);
3120
    }
3121 9
3122
    return static::create($result);
3123
  }
3124
3125
  /**
3126
   * Stripe all empty items.
3127
   *
3128
   * @return static <p>(Immutable)</p>
3129 9
   */
3130
  public function stripEmpty()
3131
  {
3132
    return $this->filter(
3133
        function ($item) {
3134 9
          if ($item === null) {
3135
            return false;
3136 9
          }
3137 9
3138 9
          return (bool)trim((string)$item);
3139 8
        }
3140 8
    );
3141 8
  }
3142
3143 8
  /**
3144 9
   * Swap two values between positions by key.
3145 9
   *
3146 9
   * @param string|int $swapA <p>a key in the array</p>
3147
   * @param string|int $swapB <p>a key in the array</p>
3148 9
   *
3149
   * @return static <p>(Immutable)</p>
3150
   */
3151 9
  public function swap($swapA, $swapB)
3152
  {
3153
    $array = $this->array;
3154 9
3155
    list($array[$swapA], $array[$swapB]) = array($array[$swapB], $array[$swapA]);
3156
3157
    return static::create($array);
3158
  }
3159
3160
  /**
3161
   * alias: for "Arrayy->getArray()"
3162
   *
3163
   * @see Arrayy::getArray()
3164 9
   */
3165
  public function toArray()
3166 9
  {
3167
    return $this->getArray();
3168
  }
3169
3170
  /**
3171
   * Convert the current array to JSON.
3172
   *
3173
   * @param null|int $options [optional] <p>e.g. JSON_PRETTY_PRINT</p>
3174 4
   * @param int      $depth   [optional] <p>Set the maximum depth. Must be greater than zero.</p>
3175
   *
3176 4
   * @return string
3177 4
   */
3178 4
  public function toJson($options = null, $depth = 512)
3179 4
  {
3180
    return UTF8::json_encode($this->array, $options, $depth);
3181 4
  }
3182
3183
  /**
3184
   * Implodes array to a string with specified separator.
3185
   *
3186
   * @param string $separator [optional] <p>The element's separator.</p>
3187
   *
3188
   * @return string <p>The string representation of array, separated by ",".</p>
3189 2
   */
3190
  public function toString($separator = ',')
3191 2
  {
3192
    return $this->implode($separator);
3193
  }
3194
3195
  /**
3196
   * Return a duplicate free copy of the current array.
3197
   *
3198
   * @return static <p>(Mutable)</p>
3199
   */
3200
  public function unique()
3201
  {
3202 9
    // INFO: \array_unique() can't handle e.g. "stdClass"-values in an array
3203
3204 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...
3205 4
        $this->array,
3206 4
        function ($resultArray, $value) {
3207 5
          if (!in_array($value, $resultArray, true)) {
3208
            $resultArray[] = $value;
3209
          }
3210 9
3211
          return $resultArray;
3212
        },
3213
        array()
3214
    );
3215
3216 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...
3217
      $this->array = array();
3218
    } else {
3219
      $this->array = (array)$this->array;
3220
    }
3221
3222
    return $this;
3223
  }
3224
3225
  /**
3226
   * Return a duplicate free copy of the current array. (with the old keys)
3227
   *
3228
   * @return static <p>(Mutable)</p>
3229
   */
3230
  public function uniqueKeepIndex()
3231
  {
3232
    // INFO: \array_unique() can't handle e.g. "stdClass"-values in an array
3233
3234
    // init
3235
    $array = $this->array;
3236
3237
    $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...
3238
        \array_keys($array),
3239
        function ($resultArray, $key) use ($array) {
3240
          if (!in_array($array[$key], $resultArray, true)) {
3241
            $resultArray[$key] = $array[$key];
3242
          }
3243
3244
          return $resultArray;
3245
        },
3246
        array()
3247
    );
3248
3249 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...
3250
      $this->array = array();
3251
    } else {
3252
      $this->array = (array)$this->array;
3253
    }
3254
3255
    return $this;
3256
  }
3257
3258
  /**
3259
   * alias: for "Arrayy->unique()"
3260
   *
3261
   * @see Arrayy::unique()
3262
   *
3263
   * @return static <p>(Mutable) Return this Arrayy object, with the appended values.</p>
3264
   */
3265
  public function uniqueNewIndex()
3266
  {
3267
    return $this->unique();
3268
  }
3269
3270
  /**
3271
   * Prepends one or more values to the beginning of array at once.
3272
   *
3273
   * @return static <p>(Mutable) Return this Arrayy object, with prepended elements to the beginning of array.</p>
3274
   */
3275 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...
3276
  {
3277
    if (func_num_args()) {
3278
      $args = \array_merge(array(&$this->array), func_get_args());
3279
      if (Bootup::is_php('5.6')) {
3280
        /** @noinspection PhpLanguageLevelInspection */
3281
        array_unshift(...$args);
3282
      } else {
3283
        /** @noinspection ArgumentUnpackingCanBeUsedInspection */
3284
        call_user_func_array('array_unshift', $args);
3285
      }
3286
    }
3287
3288
    return $this;
3289
  }
3290
3291
  /**
3292
   * Get all values from a array.
3293
   *
3294
   * @return static <p>(Immutable)</p>
3295
   */
3296
  public function values()
3297
  {
3298
    return static::create(\array_values((array)$this->array));
3299
  }
3300
3301
  /**
3302
   * Apply the given function to every element in the array, discarding the results.
3303
   *
3304
   * @param callable $callable
3305
   * @param bool     $recursive <p>Whether array will be walked recursively or no</p>
3306
   *
3307
   * @return static <p>(Mutable) Return this Arrayy object, with modified elements.</p>
3308
   */
3309
  public function walk($callable, $recursive = false)
3310
  {
3311
    if (true === $recursive) {
3312
      \array_walk_recursive($this->array, $callable);
3313
    } else {
3314
      \array_walk($this->array, $callable);
3315
    }
3316
3317
    return $this;
3318
  }
3319
}
3320