Completed
Push — master ( 095c19...b0d5fb )
by Lars
03:02
created

Arrayy::changeSeparator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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

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

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

Loading history...
1401 1
      $array = array_map($callable, $this->array, $arguments);
1402 1
    } else {
1403 1
      $array = array_map($callable, $this->array);
1404
    }
1405
1406 1
    return static::create($array);
1407
  }
1408
1409
  /**
1410
   * Check whether array is associative or not.
1411
   *
1412
   * @return bool Returns true if associative, false otherwise
1413
   */
1414 15
  public function isAssoc()
1415
  {
1416 15
    if ($this->isEmpty()) {
1417 3
      return false;
1418
    }
1419
1420 13
    foreach ($this->keys()->getArray() as $key) {
1421 13
      if (!is_string($key)) {
1422 11
        return false;
1423
      }
1424 3
    }
1425
1426 3
    return true;
1427
  }
1428
1429
  /**
1430
   * Check whether the array is empty or not.
1431
   *
1432
   * @return bool Returns true if empty, false otherwise
1433
   */
1434 25
  public function isEmpty()
1435
  {
1436 25
    return !$this->array;
1437
  }
1438
1439
  /**
1440
   * Check if the current array is equal to the given "$array" or not.
1441
   *
1442
   * @param array $array
1443
   *
1444
   * @return bool
1445
   */
1446
  public function isEqual(array $array)
1447
  {
1448
    return ($this->array === $array);
1449
  }
1450
1451
  /**
1452
   * Check if the current array is a multi-array.
1453
   *
1454
   * @return bool
1455
   */
1456 14
  public function isMultiArray()
1457
  {
1458 14
    return !(count($this->array) === count($this->array, COUNT_RECURSIVE));
1459
  }
1460
1461
  /**
1462
   * Check whether array is numeric or not.
1463
   *
1464
   * @return bool Returns true if numeric, false otherwise
1465
   */
1466 5
  public function isNumeric()
1467
  {
1468 5
    if ($this->isEmpty()) {
1469 2
      return false;
1470
    }
1471
1472 4
    foreach ($this->keys() as $key) {
1473 4
      if (!is_int($key)) {
1474 2
        return false;
1475
      }
1476 3
    }
1477
1478 2
    return true;
1479
  }
1480
1481
  /**
1482
   * Check if the current array is sequential [0, 1, 2, 3, 4, 5 ...] or not.
1483
   *
1484
   * @return bool
1485
   */
1486 1
  public function isSequential()
1487
  {
1488 1
    return array_keys($this->array) === range(0, count($this->array) - 1);
1489
  }
1490
1491
  /**
1492
   * Get all keys from the current array.
1493
   *
1494
   * @return Arrayy (Immutable)
1495
   */
1496 24
  public function keys()
1497
  {
1498 24
    return static::create(array_keys($this->array));
1499
  }
1500
1501
  /**
1502
   * Get the last value from the current array.
1503
   *
1504
   * @return mixed Return null if there wasn't a element.
1505
   */
1506 4
  public function last()
1507
  {
1508 4
    $result = $this->pop();
1509
1510 4
    if (null === $result) {
1511 1
      return null;
1512
    } else {
1513 3
      return $result;
1514
    }
1515
  }
1516
1517
  /**
1518
   * Get the last value(s) from the current array.
1519
   *
1520
   * @param int|null $number
1521
   *
1522
   * @return Arrayy (Immutable)
1523
   */
1524 12
  public function lastsImmutable($number = null)
1525
  {
1526 12
    if ($number === null) {
1527 8
      $poppedValue = (array)$this->pop();
1528 8
      $arrayy = static::create($poppedValue);
1529 8
    } else {
1530 4
      $number = (int)$number;
1531 4
      $arrayy = $this->rest(-$number);
1532
    }
1533
1534 12
    return $arrayy;
1535
  }
1536
1537
  /**
1538
   * Get the last value(s) from the current array.
1539
   *
1540
   * @param int|null $number
1541
   *
1542
   * @return self (Mutable)
1543
   */
1544 12
  public function lastsMutable($number = null)
1545
  {
1546 12
    if ($number === null) {
1547 8
      $poppedValue = (array)$this->pop();
1548 8
      $this->array = static::create($poppedValue)->array;
1549 8
    } else {
1550 4
      $number = (int)$number;
1551 4
      $this->array = $this->rest(-$number)->array;
1552
    }
1553
1554 12
    return $this;
1555
  }
1556
1557
  /**
1558
   * Count the values from the current array.
1559
   *
1560
   * alias: for "Arrayy->size()"
1561
   *
1562
   * @see Arrayy::size()
1563
   *
1564
   * @return int
1565
   */
1566 10
  public function length()
1567
  {
1568 10
    return $this->size();
1569
  }
1570
1571
  /**
1572
   * Apply the given function to the every element of the array,
1573
   * collecting the results.
1574
   *
1575
   * @param callable $callable
1576
   *
1577
   * @return Arrayy (Immutable) Arrayy object with modified elements
1578
   */
1579 4
  public function map($callable)
1580
  {
1581 4
    $result = array_map($callable, $this->array);
1582
1583 4
    return static::create($result);
1584
  }
1585
1586
  /**
1587
   * Check if all items in current array match a truth test.
1588
   *
1589
   * @param \Closure $closure
1590
   *
1591
   * @return bool
1592
   */
1593 9 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...
1594
  {
1595
    // Reduce the array to only booleans
1596 9
    $array = $this->each($closure);
1597
1598
    // Check the results
1599 9
    if (count($array) === 0) {
1600 2
      return true;
1601
    }
1602
1603 7
    $array = array_search(false, $array->toArray(), false);
1604
1605 7
    return is_bool($array);
1606
  }
1607
1608
  /**
1609
   * Check if any item in the current array matches a truth test.
1610
   *
1611
   * @param \Closure $closure
1612
   *
1613
   * @return bool
1614
   */
1615 9 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...
1616
  {
1617
    // Reduce the array to only booleans
1618 9
    $array = $this->each($closure);
1619
1620
    // Check the results
1621 9
    if (count($array) === 0) {
1622 2
      return true;
1623
    }
1624
1625 7
    $array = array_search(true, $array->toArray(), false);
1626
1627 7
    return is_int($array);
1628
  }
1629
1630
  /**
1631
   * Get the max value from an array.
1632
   *
1633
   * @return mixed
1634
   */
1635 10
  public function max()
1636
  {
1637 10
    if ($this->count() === 0) {
1638 1
      return false;
1639
    }
1640
1641 9
    return max($this->array);
1642
  }
1643
1644
  /**
1645
   * Merge the new $array into the current array.
1646
   *
1647
   * - keep key,value from the current array, also if the index is in the new $array
1648
   *
1649
   * @param array $array
1650
   * @param bool  $recursive
1651
   *
1652
   * @return Arrayy (Immutable)
1653
   */
1654 25 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...
1655
  {
1656 25
    if (true === $recursive) {
1657 4
      $result = array_replace_recursive($this->array, $array);
1658 4
    } else {
1659 21
      $result = array_replace($this->array, $array);
1660
    }
1661
1662 25
    return static::create($result);
1663
  }
1664
1665
  /**
1666
   * Merge the new $array into the current array.
1667
   *
1668
   * - replace duplicate assoc-keys from the current array with the key,values from the new $array
1669
   * - create new indexes
1670
   *
1671
   * @param array $array
1672
   * @param bool  $recursive
1673
   *
1674
   * @return Arrayy (Immutable)
1675
   */
1676 16 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...
1677
  {
1678 16
    if (true === $recursive) {
1679 4
      $result = array_merge_recursive($this->array, $array);
1680 4
    } else {
1681 12
      $result = array_merge($this->array, $array);
1682
    }
1683
1684 16
    return static::create($result);
1685
  }
1686
1687
  /**
1688
   * Merge the the current array into the $array.
1689
   *
1690
   * - use key,value from the new $array, also if the index is in the current array
1691
   *
1692
   * @param array $array
1693
   * @param bool  $recursive
1694
   *
1695
   * @return Arrayy (Immutable)
1696
   */
1697 16 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...
1698
  {
1699 16
    if (true === $recursive) {
1700 4
      $result = array_replace_recursive($array, $this->array);
1701 4
    } else {
1702 12
      $result = array_replace($array, $this->array);
1703
    }
1704
1705 16
    return static::create($result);
1706
  }
1707
1708
  /**
1709
   * Merge the current array into the new $array.
1710
   *
1711
   * - replace duplicate assoc-keys from new $array with the key,values from the current array
1712
   * - create new indexes
1713
   *
1714
   * @param array $array
1715
   * @param bool  $recursive
1716
   *
1717
   * @return Arrayy (Immutable)
1718
   */
1719 16 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...
1720
  {
1721 16
    if (true === $recursive) {
1722 4
      $result = array_merge_recursive($array, $this->array);
1723 4
    } else {
1724 12
      $result = array_merge($array, $this->array);
1725
    }
1726
1727 16
    return static::create($result);
1728
  }
1729
1730
  /**
1731
   * Get the min value from an array.
1732
   *
1733
   * @return mixed
1734
   */
1735 10
  public function min()
1736
  {
1737 10
    if ($this->count() === 0) {
1738 1
      return false;
1739
    }
1740
1741 9
    return min($this->array);
1742
  }
1743
1744
  /**
1745
   * Get a subset of the items from the given array.
1746
   *
1747
   * @param mixed[] $keys
1748
   *
1749
   * @return Arrayy (Immutable)
1750
   */
1751
  public function only(array $keys)
1752
  {
1753
    $array = $this->array;
1754
1755
    return static::create(array_intersect_key($array, array_flip($keys)));
1756
  }
1757
1758
  /**
1759
   * Pad array to the specified size with a given value.
1760
   *
1761
   * @param int   $size  Size of the result array
1762
   * @param mixed $value Empty value by default
1763
   *
1764
   * @return Arrayy (Immutable) Arrayy object padded to $size with $value
1765
   */
1766 4
  public function pad($size, $value)
1767
  {
1768 4
    $result = array_pad($this->array, $size, $value);
1769
1770 4
    return static::create($result);
1771
  }
1772
1773
  /**
1774
   * Pop a specified value off the end of the current array.
1775
   *
1776
   * @return mixed The popped element from the current array.
1777
   */
1778 16
  public function pop()
1779
  {
1780 16
    return array_pop($this->array);
1781
  }
1782
1783
  /**
1784
   * Prepend a value to the current array.
1785
   *
1786
   * @param mixed $value
1787
   * @param mixed $key
1788
   *
1789
   * @return self (Mutable) Return this Arrayy object, with the prepended value.
1790
   */
1791 8
  public function prepend($value, $key = null)
1792
  {
1793 8
    if ($key === null) {
1794 8
      array_unshift($this->array, $value);
1795 8
    } else {
1796
      /** @noinspection AdditionOperationOnArraysInspection */
1797 1
      $this->array = array($key => $value) + $this->array;
1798
    }
1799
1800 8
    return $this;
1801
  }
1802
1803
  /**
1804
   * Push one or more values onto the end of array at once.
1805
   *
1806
   * @return self (Mutable) Return this Arrayy object, with pushed elements to the end of array.
1807
   */
1808 4 View Code Duplication
  public function push(/* variadic arguments allowed */)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1809
  {
1810 4
    if (func_num_args()) {
1811 4
      $args = array_merge(array(&$this->array), func_get_args());
1812 4
      call_user_func_array('array_push', $args);
1813 4
    }
1814
1815 4
    return $this;
1816
  }
1817
1818
  /**
1819
   * Get a random value from the current array.
1820
   *
1821
   * @param null|int $number how many values you will take?
1822
   *
1823
   * @return Arrayy (Immutable)
1824
   */
1825 17
  public function randomImmutable($number = null)
1826
  {
1827 17
    if ($this->count() === 0) {
1828
      return static::create();
1829
    }
1830
1831 17 View Code Duplication
    if ($number === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1832 14
      $arrayRandValue = (array)$this->array[array_rand($this->array)];
1833
1834 14
      return static::create($arrayRandValue);
1835
    }
1836
1837 5
    $arrayTmp = $this->array;
1838 5
    shuffle($arrayTmp);
1839
1840 5
    return self::create($arrayTmp)->firstsImmutable($number);
1841
  }
1842
1843
  /**
1844
   * Pick a random key/index from the keys of this array.
1845
   *
1846
   *
1847
   * @return mixed get a key/index or null if there wasn't a key/index
1848
   *
1849
   * @throws \RangeException If array is empty
1850
   */
1851 4
  public function randomKey()
1852
  {
1853 4
    $result = $this->randomKeys(1);
1854
1855 4
    if (!isset($result[0])) {
1856
      $result[0] = null;
1857
    }
1858
1859 4
    return $result[0];
1860
  }
1861
1862
  /**
1863
   * Pick a given number of random keys/indexes out of this array.
1864
   *
1865
   * @param int $number The number of keys/indexes (should be <= $this->count())
1866
   *
1867
   * @return Arrayy (Immutable)
1868
   *
1869
   * @throws \RangeException If array is empty
1870
   */
1871 14
  public function randomKeys($number)
1872
  {
1873 14
    $number = (int)$number;
1874 14
    $count = $this->count();
1875
1876 14
    if ($number === 0 || $number > $count) {
1877 3
      throw new \RangeException(
1878 3
          sprintf(
1879 3
              'Number of requested keys (%s) must be equal or lower than number of elements in this array (%s)',
1880 3
              $number,
1881
              $count
1882 3
          )
1883 3
      );
1884
    }
1885
1886 11
    $result = (array)array_rand($this->array, $number);
1887
1888 11
    return static::create($result);
1889
  }
1890
1891
  /**
1892
   * Get a random value from the current array.
1893
   *
1894
   * @param null|int $number how many values you will take?
1895
   *
1896
   * @return Arrayy (Mutable)
1897
   */
1898 16
  public function randomMutable($number = null)
1899
  {
1900 16
    if ($this->count() === 0) {
1901
      return static::create();
1902
    }
1903
1904 16 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...
1905 6
      $arrayRandValue = (array)$this->array[array_rand($this->array)];
1906 6
      $this->array = $arrayRandValue;
1907
1908 6
      return $this;
1909
    }
1910
1911 11
    shuffle($this->array);
1912
1913 11
    return $this->firstsMutable($number);
1914
  }
1915
1916
  /**
1917
   * Pick a random value from the values of this array.
1918
   *
1919
   * @return mixed get a random value or null if there wasn't a value
1920
   */
1921 4
  public function randomValue()
1922
  {
1923 4
    $result = $this->randomImmutable();
1924
1925 4
    if (!isset($result[0])) {
1926
      $result[0] = null;
1927
    }
1928
1929 4
    return $result[0];
1930
  }
1931
1932
  /**
1933
   * Pick a given number of random values out of this array.
1934
   *
1935
   * @param int $number
1936
   *
1937
   * @return Arrayy (Mutable)
1938
   */
1939 7
  public function randomValues($number)
1940
  {
1941 7
    $number = (int)$number;
1942
1943 7
    return $this->randomMutable($number);
1944
  }
1945
1946
  /**
1947
   * Get a random value from an array, with the ability to skew the results.
1948
   *
1949
   * Example: randomWeighted(['foo' => 1, 'bar' => 2]) has a 66% chance of returning bar.
1950
   *
1951
   * @param array    $array
1952
   * @param null|int $number how many values you will take?
1953
   *
1954
   * @return Arrayy (Immutable)
1955
   */
1956 9
  public function randomWeighted(array $array, $number = null)
1957
  {
1958 9
    $options = array();
1959 9
    foreach ($array as $option => $weight) {
1960 9
      if ($this->searchIndex($option) !== false) {
1961 2
        for ($i = 0; $i < $weight; ++$i) {
1962 1
          $options[] = $option;
1963 1
        }
1964 2
      }
1965 9
    }
1966
1967 9
    return $this->mergeAppendKeepIndex($options)->randomImmutable($number);
1968
  }
1969
1970
  /**
1971
   * Reduce the current array via callable e.g. anonymous-function.
1972
   *
1973
   * @param mixed $callable
1974
   * @param array $init
1975
   *
1976
   * @return Arrayy (Immutable)
1977
   */
1978 3
  public function reduce($callable, array $init = array())
1979
  {
1980 3
    $result = array_reduce($this->array, $callable, $init);
1981
1982 3
    if ($result === null) {
1983
      $this->array = array();
1984
    } else {
1985 3
      $this->array = (array)$result;
1986
    }
1987
1988 3
    return static::create($this->array);
1989
  }
1990
1991
  /**
1992
   * Create a numerically re-indexed Arrayy object.
1993
   *
1994
   * @return self (Mutable) Return this Arrayy object, with re-indexed array-elements.
1995
   */
1996 9
  public function reindex()
1997
  {
1998 9
    $this->array = array_values($this->array);
1999
2000 9
    return $this;
2001
  }
2002
2003
  /**
2004
   * Return all items that fail the truth test.
2005
   *
2006
   * @param \Closure $closure
2007
   *
2008
   * @return Arrayy (Immutable)
2009
   */
2010 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...
2011
  {
2012 1
    $filtered = array();
2013
2014 1
    foreach ($this->array as $key => $value) {
2015 1
      if (!$closure($value, $key)) {
2016 1
        $filtered[$key] = $value;
2017 1
      }
2018 1
    }
2019
2020 1
    return static::create($filtered);
2021
  }
2022
2023
  /**
2024
   * Remove a value from the current array (optional using dot-notation).
2025
   *
2026
   * @param mixed $key
2027
   *
2028
   * @return Arrayy (Immutable)
2029
   */
2030 18
  public function remove($key)
2031
  {
2032
    // Recursive call
2033 18
    if (is_array($key)) {
2034
      foreach ($key as $k) {
2035
        $this->internalRemove($k);
2036
      }
2037
2038
      return static::create($this->array);
2039
    }
2040
2041 18
    $this->internalRemove($key);
2042
2043 18
    return static::create($this->array);
2044
  }
2045
2046
  /**
2047
   * Remove the first value from the current array.
2048
   *
2049
   * @return Arrayy (Immutable)
2050
   */
2051 7
  public function removeFirst()
2052
  {
2053 7
    array_shift($this->array);
2054
2055 7
    return static::create($this->array);
2056
  }
2057
2058
  /**
2059
   * Remove the last value from the current array.
2060
   *
2061
   * @return Arrayy (Immutable)
2062
   */
2063 7
  public function removeLast()
2064
  {
2065 7
    array_pop($this->array);
2066
2067 7
    return static::create($this->array);
2068
  }
2069
2070
  /**
2071
   * Removes a particular value from an array (numeric or associative).
2072
   *
2073
   * @param mixed $value
2074
   *
2075
   * @return Arrayy (Immutable)
2076
   */
2077 7
  public function removeValue($value)
2078
  {
2079 7
    $isNumericArray = true;
2080 7
    foreach ($this->array as $key => $item) {
2081 6
      if ($item === $value) {
2082 6
        if (!is_int($key)) {
2083
          $isNumericArray = false;
2084
        }
2085 6
        unset($this->array[$key]);
2086 6
      }
2087 7
    }
2088
2089 7
    if ($isNumericArray) {
2090 7
      $this->array = array_values($this->array);
2091 7
    }
2092
2093 7
    return static::create($this->array);
2094
  }
2095
2096
  /**
2097
   * Replace a key with a new key/value pair.
2098
   *
2099
   * @param $replace
2100
   * @param $key
2101
   * @param $value
2102
   *
2103
   * @return Arrayy (Immutable)
2104
   */
2105 2
  public function replace($replace, $key, $value)
2106
  {
2107 2
    $this->remove($replace);
2108
2109 2
    return $this->set($key, $value);
2110
  }
2111
2112
  /**
2113
   * Create an array using the current array as values and the other array as keys.
2114
   *
2115
   * @param array $keys Keys array
2116
   *
2117
   * @return Arrayy (Immutable) Arrayy object with keys from the other array.
2118
   */
2119 2
  public function replaceAllKeys(array $keys)
2120
  {
2121 2
    $result = array_combine($keys, $this->array);
2122
2123 2
    return static::create($result);
2124
  }
2125
2126
  /**
2127
   * Create an array using the current array as keys and the other array as values.
2128
   *
2129
   * @param array $array Values array
2130
   *
2131
   * @return Arrayy (Immutable) Arrayy object with values from the other array.
2132
   */
2133 2
  public function replaceAllValues(array $array)
2134
  {
2135 2
    $result = array_combine($this->array, $array);
2136
2137 2
    return static::create($result);
2138
  }
2139
2140
  /**
2141
   * Replace the keys in an array with another set.
2142
   *
2143
   * @param array $keys An array of keys matching the array's size
2144
   *
2145
   * @return Arrayy (Immutable)
2146
   */
2147 1
  public function replaceKeys(array $keys)
2148
  {
2149 1
    $values = array_values($this->array);
2150 1
    $result = array_combine($keys, $values);
2151
2152 1
    return static::create($result);
2153
  }
2154
2155
  /**
2156
   * Replace the first matched value in an array.
2157
   *
2158
   * @param mixed $search
2159
   * @param mixed $replacement
2160
   *
2161
   * @return Arrayy (Immutable)
2162
   */
2163 3
  public function replaceOneValue($search, $replacement = '')
2164
  {
2165 3
    $array = $this->array;
2166 3
    $key = array_search($search, $array, true);
2167
2168 3
    if ($key !== false) {
2169 3
      $array[$key] = $replacement;
2170 3
    }
2171
2172 3
    return static::create($array);
2173
  }
2174
2175
  /**
2176
   * Replace values in the current array.
2177
   *
2178
   * @param string $search      The string to replace.
2179
   * @param string $replacement What to replace it with.
2180
   *
2181
   * @return Arrayy (Immutable)
2182
   */
2183 1
  public function replaceValues($search, $replacement = '')
2184
  {
2185 1
    $array = $this->each(
2186
        function ($value) use ($search, $replacement) {
2187 1
          return UTF8::str_replace($search, $replacement, $value);
2188
        }
2189 1
    );
2190
2191 1
    return $array;
2192
  }
2193
2194
  /**
2195
   * Get the last elements from index $from until the end of this array.
2196
   *
2197
   * @param int $from
2198
   *
2199
   * @return Arrayy (Immutable)
2200
   */
2201 15
  public function rest($from = 1)
2202
  {
2203 15
    $result = array_splice($this->array, $from);
2204
2205 15
    return static::create($result);
2206
  }
2207
2208
  /**
2209
   * Return the array in the reverse order.
2210
   *
2211
   * @return self (Mutable) Return this Arrayy object.
2212
   */
2213 7
  public function reverse()
2214
  {
2215 7
    $this->array = array_reverse($this->array);
2216
2217 7
    return $this;
2218
  }
2219
2220
  /**
2221
   * Search for the first index of the current array via $value.
2222
   *
2223
   * @param mixed $value
2224
   *
2225
   * @return mixed
2226
   */
2227 20
  public function searchIndex($value)
2228
  {
2229 20
    return array_search($value, $this->array, true);
2230
  }
2231
2232
  /**
2233
   * Search for the value of the current array via $index.
2234
   *
2235
   * @param mixed $index
2236
   *
2237
   * @return Arrayy (Immutable) will return a empty Arrayy if the value wasn't found
2238
   */
2239 7
  public function searchValue($index)
2240
  {
2241
    // init
2242 7
    $return = array();
2243
2244 7
    if (null !== $index) {
2245 7
      $keyExists = isset($this->array[$index]);
2246
2247 7
      if ($keyExists !== false) {
2248 5
        $return = array($this->array[$index]);
2249 5
      }
2250 7
    }
2251
2252 7
    return static::create($return);
2253
  }
2254
2255
  /**
2256
   * Set a value for the current array (optional using dot-notation).
2257
   *
2258
   * @param string $key   The key to set
2259
   * @param mixed  $value Its value
2260
   *
2261
   * @return Arrayy (Immutable)
2262
   */
2263 17
  public function set($key, $value)
2264
  {
2265 17
    $this->internalSet($key, $value);
2266
2267 17
    return static::create($this->array);
2268
  }
2269
2270
  /**
2271
   * Get a value from a array and set it if it was not.
2272
   *
2273
   * WARNING: this method only set the value, if the $key is not already set
2274
   *
2275
   * @param string $key      The key
2276
   * @param mixed  $fallback The default value to set if it isn't
2277
   *
2278
   * @return mixed (Mutable)
2279
   */
2280 10
  public function setAndGet($key, $fallback = null)
2281
  {
2282
    // If the key doesn't exist, set it
2283 10
    if (!$this->has($key)) {
2284 5
      $this->array = $this->set($key, $fallback)->getArray();
2285 5
    }
2286
2287 10
    return $this->get($key);
2288
  }
2289
2290
  /**
2291
   * Shifts a specified value off the beginning of array.
2292
   *
2293
   * @return mixed A shifted element from the current array.
2294
   */
2295 4
  public function shift()
2296
  {
2297 4
    return array_shift($this->array);
2298
  }
2299
2300
  /**
2301
   * Shuffle the current array.
2302
   *
2303
   * @return Arrayy (Immutable)
2304
   */
2305 1
  public function shuffle()
2306
  {
2307 1
    $array = $this->array;
2308
2309 1
    shuffle($array);
2310
2311 1
    return static::create($array);
2312
  }
2313
2314
  /**
2315
   * Get the size of an array.
2316
   *
2317
   * @return int
2318
   */
2319 110
  public function size()
2320
  {
2321 110
    return count($this->array);
2322
  }
2323
2324
  /**
2325
   * Extract a slice of the array.
2326
   *
2327
   * @param int      $offset       Slice begin index
2328
   * @param int|null $length       Length of the slice
2329
   * @param bool     $preserveKeys Whether array keys are preserved or no
2330
   *
2331
   * @return static A slice of the original array with length $length
2332
   */
2333 4
  public function slice($offset, $length = null, $preserveKeys = false)
2334
  {
2335 4
    $result = array_slice($this->array, $offset, $length, $preserveKeys);
2336
2337 4
    return static::create($result);
2338
  }
2339
2340
  /**
2341
   * Sort the current array and optional you can keep the keys.
2342
   *
2343
   * @param integer $direction use SORT_ASC or SORT_DESC
2344
   * @param integer $strategy
2345
   * @param bool    $keepKeys
2346
   *
2347
   * @return self (Mutable) Return this Arrayy object.
2348
   */
2349 19
  public function sort($direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
2350
  {
2351 19
    $this->sorting($this->array, $direction, $strategy, $keepKeys);
2352
2353 19
    return $this;
2354
  }
2355
2356
  /**
2357
   * Sort the current array by key.
2358
   *
2359
   * @link http://php.net/manual/en/function.ksort.php
2360
   * @link http://php.net/manual/en/function.krsort.php
2361
   *
2362
   * @param int|string $direction use SORT_ASC or SORT_DESC
2363
   * @param int        $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
2364
   *
2365
   * @return self (Mutable) Return this Arrayy object.
2366
   */
2367 18
  public function sortKeys($direction = SORT_ASC, $strategy = SORT_REGULAR)
2368
  {
2369 18
    $this->sorterKeys($this->array, $direction, $strategy);
2370
2371 18
    return $this;
2372
  }
2373
2374
  /**
2375
   * Sort the current array by value.
2376
   *
2377
   * @param int $direction use SORT_ASC or SORT_DESC
2378
   * @param int $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
2379
   *
2380
   * @return Arrayy (Immutable)
2381
   */
2382 1
  public function sortValueKeepIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
2383
  {
2384 1
    return $this->sort($direction, $strategy, true);
2385
  }
2386
2387
  /**
2388
   * Sort the current array by value.
2389
   *
2390
   * @param int $direction use SORT_ASC or SORT_DESC
2391
   * @param int $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
2392
   *
2393
   * @return Arrayy (Immutable)
2394
   */
2395 1
  public function sortValueNewIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
2396
  {
2397 1
    return $this->sort($direction, $strategy, false);
2398
  }
2399
2400
  /**
2401
   * Sort a array by value, by a closure or by a property.
2402
   *
2403
   * - If the sorter is null, the array is sorted naturally.
2404
   * - Associative (string) keys will be maintained, but numeric keys will be re-indexed.
2405
   *
2406
   * @param null       $sorter
2407
   * @param string|int $direction
2408
   * @param int        $strategy
2409
   *
2410
   * @return Arrayy (Immutable)
2411
   */
2412 1
  public function sorter($sorter = null, $direction = SORT_ASC, $strategy = SORT_REGULAR)
2413
  {
2414 1
    $array = (array)$this->array;
2415 1
    $direction = $this->getDirection($direction);
2416
2417
    // Transform all values into their results.
2418 1
    if ($sorter) {
2419 1
      $arrayy = new self($array);
2420
2421 1
      $that = $this;
2422 1
      $results = $arrayy->each(
2423
          function ($value) use ($sorter, $that) {
2424 1
            return is_callable($sorter) ? $sorter($value) : $that->get($sorter, null, $value);
2425
          }
2426 1
      );
2427
2428 1
      $results = $results->getArray();
2429 1
    } else {
2430 1
      $results = $array;
2431
    }
2432
2433
    // Sort by the results and replace by original values
2434 1
    array_multisort($results, $direction, $strategy, $array);
2435
2436 1
    return static::create($array);
2437
  }
2438
2439
  /**
2440
   * sorting keys
2441
   *
2442
   * @param array $elements
2443
   * @param int   $direction
2444
   * @param int   $strategy
2445
   */
2446 18
  protected function sorterKeys(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR)
2447
  {
2448 18
    $direction = $this->getDirection($direction);
2449
2450
    switch ($direction) {
2451 18
      case 'desc':
2452 18
      case SORT_DESC:
2453 6
        krsort($elements, $strategy);
2454 6
        break;
2455 13
      case 'asc':
2456 13
      case SORT_ASC:
2457 13
      default:
2458 13
        ksort($elements, $strategy);
2459 13
    }
2460 18
  }
2461
2462
  /**
2463
   * @param array      &$elements
2464
   * @param int|string $direction
2465
   * @param int        $strategy
2466
   * @param bool       $keepKeys
2467
   */
2468 19
  protected function sorting(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
2469
  {
2470 19
    $direction = $this->getDirection($direction);
2471
2472 19
    if (!$strategy) {
2473 19
      $strategy = SORT_REGULAR;
2474 19
    }
2475
2476
    switch ($direction) {
2477 19
      case 'desc':
2478 19
      case SORT_DESC:
2479 9
        if ($keepKeys) {
2480 5
          arsort($elements, $strategy);
2481 5
        } else {
2482 4
          rsort($elements, $strategy);
2483
        }
2484 9
        break;
2485 10
      case 'asc':
2486 10
      case SORT_ASC:
2487 10
      default:
2488 10
        if ($keepKeys) {
2489 4
          asort($elements, $strategy);
2490 4
        } else {
2491 6
          sort($elements, $strategy);
2492
        }
2493 10
    }
2494 19
  }
2495
2496
  /**
2497
   * Split an array in the given amount of pieces.
2498
   *
2499
   * @param int  $numberOfPieces
2500
   * @param bool $keepKeys
2501
   *
2502
   * @return Arrayy (Immutable)
2503
   */
2504 1
  public function split($numberOfPieces = 2, $keepKeys = false)
2505
  {
2506 1
    $arrayCount = $this->count();
2507
2508 1
    if ($arrayCount === 0) {
2509 1
      $result = array();
2510 1
    } else {
2511 1
      $numberOfPieces = (int)$numberOfPieces;
2512 1
      $splitSize = ceil($arrayCount / $numberOfPieces);
2513 1
      $result = array_chunk($this->array, $splitSize, $keepKeys);
2514
    }
2515
2516 1
    return static::create($result);
2517
  }
2518
2519
  /**
2520
   * Stripe all empty items.
2521
   *
2522
   * @return Arrayy (Immutable)
2523
   */
2524 1
  public function stripEmpty()
2525
  {
2526 1
    return $this->filter(
2527
        function ($item) {
2528 1
          if (null === $item) {
2529 1
            return false;
2530
          }
2531
2532 1
          return (bool)trim($item);
2533
        }
2534 1
    );
2535
  }
2536
2537
  /**
2538
   * Swap two values between positions by key.
2539
   *
2540
   * @param string|int $swapA an key in the array
2541
   * @param string|int $swapB an key in the array
2542
   *
2543
   * @return Arrayy (Immutable)
2544
   */
2545 1
  public function swap($swapA, $swapB)
2546
  {
2547 1
    $array = $this->array;
2548
2549 1
    list($array[$swapA], $array[$swapB]) = array($array[$swapB], $array[$swapA]);
2550
2551 1
    return static::create($array);
2552
  }
2553
2554
  /**
2555
   * alias: for "Arrayy->getArray()"
2556
   *
2557
   * @see Arrayy::getArray()
2558
   */
2559 154
  public function toArray()
2560
  {
2561 154
    return $this->getArray();
2562
  }
2563
2564
  /**
2565
   * Convert the current array to JSON.
2566
   *
2567
   * @param null $options e.g. JSON_PRETTY_PRINT
2568
   *
2569
   * @return string
2570
   */
2571 5
  public function toJson($options = null)
2572
  {
2573 5
    return UTF8::json_encode($this->array, $options);
2574
  }
2575
2576
  /**
2577
   * Implodes array to a string with specified separator.
2578
   *
2579
   * @param string $separator The element's separator
2580
   *
2581
   * @return string The string representation of array, separated by ","
2582
   */
2583 19
  public function toString($separator = ',')
2584
  {
2585 19
    return $this->implode($separator);
2586
  }
2587
2588
  /**
2589
   * Return a duplicate free copy of the current array.
2590
   *
2591
   * @return Arrayy (Mutable)
2592
   */
2593 8
  public function unique()
2594
  {
2595 8
    $this->array = array_reduce(
0 ignored issues
show
Documentation Bug introduced by
It seems like array_reduce($this->arra...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...
2596 8
        $this->array,
2597 8
        function ($resultArray, $value) {
2598 7
          if (in_array($value, $resultArray, true) === false) {
2599 7
            $resultArray[] = $value;
2600 7
          }
2601
2602 7
          return $resultArray;
2603 8
        },
2604 8
        array()
2605 8
    );
2606
2607 8
    if ($this->array === null) {
2608
      $this->array = array();
2609
    } else {
2610 8
      $this->array = (array)$this->array;
2611
    }
2612
2613 8
    return $this;
2614
  }
2615
2616
  /**
2617
   * Prepends one or more values to the beginning of array at once.
2618
   *
2619
   * @return self (Mutable) Return this Arrayy object, with prepended elements to the beginning of array.
2620
   */
2621 4 View Code Duplication
  public function unshift(/* variadic arguments allowed */)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2622
  {
2623 4
    if (func_num_args()) {
2624 4
      $args = array_merge(array(&$this->array), func_get_args());
2625 4
      call_user_func_array('array_unshift', $args);
2626 4
    }
2627
2628 4
    return $this;
2629
  }
2630
2631
  /**
2632
   * Get all values from a array.
2633
   *
2634
   * @return Arrayy (Immutable)
2635
   */
2636 2
  public function values()
2637
  {
2638 2
    return static::create(array_values((array)$this->array));
2639
  }
2640
2641
  /**
2642
   * Apply the given function to every element in the array, discarding the results.
2643
   *
2644
   * @param callable $callable
2645
   * @param bool     $recursive Whether array will be walked recursively or no
2646
   *
2647
   * @return self (Mutable) Return this Arrayy object, with modified elements
2648
   */
2649 9
  public function walk($callable, $recursive = false)
2650
  {
2651 9
    if (true === $recursive) {
2652 4
      array_walk_recursive($this->array, $callable);
2653 4
    } else {
2654 5
      array_walk($this->array, $callable);
2655
    }
2656
2657 9
    return $this;
2658
  }
2659
2660
}
2661