Completed
Push — master ( 532069...602e9a )
by Lars
09:48
created

Arrayy::get()   D

Complexity

Conditions 10
Paths 18

Size

Total Lines 39
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 10

Importance

Changes 0
Metric Value
cc 10
eloc 23
nc 18
nop 3
dl 0
loc 39
ccs 7
cts 7
cp 1
crap 10
rs 4.8196
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arrayy;
6
7
use voku\helper\UTF8;
8
9
/** @noinspection ClassReImplementsParentInterfaceInspection */
10
11
/**
12
 * Methods to manage arrays.
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
class Arrayy extends \ArrayObject implements \ArrayAccess, \Serializable, \Countable
18
{
19
  /**
20
   * @var array
21
   */
22
  protected $array = array();
23
24
  /**
25
   * @var string
26
   */
27
  protected $pathSeparator = '.';
28
29
  /** @noinspection MagicMethodsValidityInspection */
30
  /**
31
   * Initializes
32
   *
33 728
   * @param array $array
34
   */
35 728
  public function __construct($array = array())
36
  {
37 726
    $array = $this->fallbackForArray($array);
38 726
39
    $this->array = $array;
40
  }
41
42
  /**
43
   * Get a value by key.
44
   *
45
   * @param $key
46
   *
47
   * @return mixed Get a Value from the current array.
48
   */
49
  public function __get($key)
50
  {
51
    $return = $this->get($key);
52
53
    if (is_array($return)) {
54
      return self::create($return);
55
    }
56
57
    return $return;
58
  }
59
60
  /**
61
   * Call object as function.
62
   *
63
   * @param mixed $key
64
   *
65
   * @return mixed
66
   */
67
  public function __invoke($key = null)
68
  {
69
    if ($key !== null) {
70
      if (isset($this->array[$key])) {
71
        return $this->array[$key];
72
      } else {
73
        return false;
74
      }
75
    }
76
77
    return (array)$this->array;
78
  }
79
80
  /**
81
   * Whether or not an element exists by key.
82
   *
83
   * @param mixed $key
84
   *
85
   * @return bool True is the key/index exists, otherwise false.
86
   */
87
  public function __isset($key)
88
  {
89
    return $this->offsetExists($key);
90
  }
91
92
  /**
93
   * Assigns a value to the specified element.
94
   *
95
   * @param mixed $key
96
   * @param mixed $value
97
   */
98
  public function __set($key, $value)
99
  {
100 16
    $this->internalSet($key, $value);
101
  }
102 16
103
  /**
104
   * magic to string
105
   *
106
   * @return string
107
   */
108
  public function __toString()
109
  {
110
    return $this->toString();
111
  }
112
113
  /**
114
   * Unset element by key.
115
   *
116
   * @param mixed $key
117
   */
118
  public function __unset($key)
119
  {
120
    unset($this->array[$key]);
121
  }
122
123
  /**
124 1
   * alias: for "Arrayy->append()"
125
   *
126 1
   * @see Arrayy::append()
127
   *
128
   * @param mixed $value
129
   *
130
   * @return self (Mutable) Return this Arrayy object, with the appended values.
131
   */
132
  public function add($value)
133
  {
134
    return $this->append($value);
135
  }
136 9
137
  /**
138 9
   * Append a value to the current array.
139
   *
140 9
   * @param mixed $value
141
   *
142
   * @return self (Mutable) Return this Arrayy object, with the appended values.
143
   */
144
  public function append($value)
145
  {
146
    $this->array[] = $value;
147
148
    return $this;
149
  }
150
151
  /**
152 110
   * Count the values from the current array.
153
   *
154 110
   * alias: for "Arrayy->size()"
155
   *
156
   * @see Arrayy::size()
157
   *
158
   * @return int
159
   */
160
  public function count()
161
  {
162 19
    return $this->size();
163
  }
164 19
165
  /**
166
   * Returns a new ArrayyIterator, thus implementing the IteratorAggregate interface.
167
   *
168
   * @return ArrayyIterator An iterator for the values in the array.
169
   */
170
  public function getIterator()
171
  {
172
    return new ArrayyIterator($this->array);
173
  }
174 37
175
  /**
176 37
   * Whether or not an offset exists.
177
   *
178
   * @param mixed $offset
179 37
   *
180
   * @return bool
181
   */
182 15
  public function offsetExists($offset)
183
  {
184 37
    $tmpReturn = isset($this->array[$offset]);
185
186
    if (
187
        $tmpReturn === true
188 35
        ||
189
        (
190
            $tmpReturn === false
191
            &&
192 2
            strpos((string)$offset, $this->pathSeparator) === false
193 2
        )
194 2
    ) {
195 2
196
      return $tmpReturn;
197 2
198
    } else {
199
200 2
      $offsetExists = false;
201 2
202
      if (strpos((string)$offset, $this->pathSeparator) !== false) {
203
204 2
        $offsetExists = false;
205
        $explodedPath = explode($this->pathSeparator, (string)$offset);
206
        $lastOffset = array_pop($explodedPath);
207
        $containerPath = implode($this->pathSeparator, $explodedPath);
208
209
        $this->callAtPath(
210
            $containerPath,
211
            function ($container) use ($lastOffset, &$offsetExists) {
212
              $offsetExists = isset($container[$lastOffset]);
213
            }
214
        );
215 23
      }
216
217 23
      return $offsetExists;
218
    }
219
  }
220
221
  /**
222
   * Returns the value at specified offset.
223
   *
224
   * @param mixed $offset
225
   *
226 14
   * @return mixed return null if the offset did not exists
227
   */
228 14
  public function offsetGet($offset)
229 4
  {
230
    return $this->offsetExists($offset) ? $this->get($offset) : null;
231 10
  }
232
233 14
  /**
234
   * Assigns a value to the specified offset.
235
   *
236
   * @param mixed $offset
237
   * @param mixed $value
238
   */
239
  public function offsetSet($offset, $value)
240 6
  {
241
    if ($offset === null) {
242 6
      $this->array[] = $value;
243 3
    } else {
244
      $this->internalSet($offset, $value);
245 3
    }
246
  }
247
248 3
  /**
249 3
   * Unset an offset.
250
   *
251 3
   * @param mixed $offset
252 3
   */
253
  public function offsetUnset($offset)
254 1
  {
255 3
    if (isset($this->array[$offset])) {
256
      unset($this->array[$offset]);
257 3
258
      return;
259
    }
260
261
    if (strpos((string)$offset, $this->pathSeparator) !== false) {
262
263
      $path = explode($this->pathSeparator, (string)$offset);
264 2
      $pathToUnset = array_pop($path);
265
266 2
      $this->callAtPath(
267
          implode($this->pathSeparator, $path),
268
          function (&$offset) use (&$pathToUnset) {
269
            unset($offset[$pathToUnset]);
270
          }
271
      );
272
273
    }
274
  }
275
276 2
  /**
277
   * Serialize the current array.
278 2
   *
279
   * @return string
280 2
   */
281
  public function serialize()
282
  {
283
    return serialize($this->array);
284
  }
285
286
  /**
287
   * Unserialize an string and return this object.
288
   *
289
   * @param string $string
290 2
   *
291
   * @return self (Mutable)
292 2
   */
293
  public function unserialize($string)
294 2
  {
295 2
    $this->array = unserialize($string);
296
297
    return $this;
298 2
  }
299
300
  /**
301
   * Iterate over the current array and execute a callback for each loop.
302
   *
303
   * @param \Closure $closure
304
   *
305
   * @return Arrayy (Immutable)
306
   */
307 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...
308 10
  {
309
    $array = $this->array;
310 10
311
    foreach ($array as $key => $value) {
312 10
      $closure($value, $key);
313 2
    }
314
315
    return static::create($array);
316 8
  }
317 3
318
  /**
319
   * Returns the average value of the current array.
320 8
   *
321
   * @param int $decimals The number of decimals to return
322
   *
323
   * @return int|double The average value
324
   */
325
  public function average($decimals = 0)
326
  {
327
    $count = $this->count();
328 4
329
    if (!$count) {
330 4
      return 0;
331 4
    }
332
333
    if (!is_int($decimals)) {
334 4
      $decimals = 0;
335 4
    }
336
337 4
    return round(array_sum($this->array) / $count, $decimals);
338 2
  }
339
340
  /**
341 2
   * @param mixed      $path
342
   * @param callable   $callable
343
   * @param null|array $currentOffset
344
   */
345
  protected function callAtPath($path, $callable, &$currentOffset = null)
346
  {
347
    if ($currentOffset === null) {
348 2
      $currentOffset = &$this->array;
349
    }
350 2
351
    $explodedPath = explode($this->pathSeparator, $path);
352
    $nextPath = array_shift($explodedPath);
353
354
    if (!isset($currentOffset[$nextPath])) {
355
      return;
356
    }
357
358
    if (!empty($explodedPath)) {
359
      $this->callAtPath(
360
          implode($this->pathSeparator, $explodedPath),
361
          $callable,
362
          $currentOffset[$nextPath]
363
      );
364
    } else {
365
      $callable($currentOffset[$nextPath]);
366
    }
367
  }
368
369
  /**
370
   * Change the path separator of the array wrapper.
371
   *
372
   * By default, the separator is: .
373
   *
374
   * @param string $separator Separator to set.
375
   *
376 4
   * @return Arrayy Current instance.
377
   */
378 4
  public function changeSeparator($separator)
379
  {
380 4
    $this->pathSeparator = $separator;
381
382
    return $this;
383
  }
384
385
  /**
386
   * Create a chunked version of the current array.
387
   *
388 8
   * @param int  $size         Size of each chunk
389
   * @param bool $preserveKeys Whether array keys are preserved or no
390 8
   *
391
   * @return Arrayy (Immutable) A new array of chunks from the original array.
392 7
   */
393 8
  public function chunk($size, $preserveKeys = false)
394
  {
395
    $result = array_chunk($this->array, $size, $preserveKeys);
396
397
    return static::create($result);
398
  }
399
400
  /**
401
   * Clean all falsy values from the current array.
402 4
   *
403
   * @return Arrayy (Immutable)
404 4
   */
405
  public function clean()
406 4
  {
407
    return $this->filter(
408
        function ($value) {
409
          return (bool)$value;
410
        }
411
    );
412
  }
413
414
  /**
415
   * WARNING!!! -> Clear the current array.
416 13
   *
417
   * @return self (Mutable) Return this Arrayy object, with an empty array.
418 13
   */
419
  public function clear()
420
  {
421
    $this->array = array();
422
423
    return $this;
424
  }
425
426
  /**
427
   * Check if an item is in the current array.
428 13
   *
429
   * @param string|int|float $value
430 13
   *
431 13
   * @return bool
432
   */
433
  public function contains($value)
434 13
  {
435 13
    return in_array($value, $this->array, true);
436
  }
437 13
438
  /**
439 13
   * Check if an (case-insensitive) string is in the current array.
440
   *
441
   * @param string $value
442
   *
443
   * @return bool
444
   */
445
  public function containsCaseInsensitive($value)
446
  {
447
    return in_array(
448
        UTF8::strtolower($value),
449
        array_map(
450 4
            array(
451
                new UTF8(),
452 4
                'strtolower',
453
            ),
454
            $this->array
455
        ),
456
        true
457
    );
458
  }
459
460
  /**
461
   * Check if the given key/index exists in the array.
462 1
   *
463
   * @param string|int|float $key key/index to search for
464 1
   *
465
   * @return bool Returns true if the given key/index exists in the array, false otherwise
466
   */
467
  public function containsKey($key)
468
  {
469
    return $this->offsetExists($key);
470
  }
471
472
  /**
473
   * Check if all given needles are present in the array as key/index.
474
   *
475
   * @param array $needles
476
   *
477
   * @return bool Returns true if the given keys/indexes exists in the array, false otherwise
478
   */
479
  public function containsKeys(array $needles)
480
  {
481
    return count(array_intersect($needles, $this->keys()->getArray())) === count($needles);
482
  }
483
484
  /**
485
   * alias: for "Arrayy->contains()"
486
   *
487
   * @see Arrayy::contains()
488 1
   *
489
   * @param string|int|float $value
490 1
   *
491
   * @return bool
492
   */
493
  public function containsValue($value)
494
  {
495
    return $this->contains($value);
496
  }
497
498
  /**
499
   * Check if all given needles are present in the array.
500 452
   *
501
   * @param array $needles
502 452
   *
503
   * @return bool Returns true if the given values exists in the array, false otherwise
504
   */
505
  public function containsValues(array $needles)
506
  {
507
    return count(array_intersect($needles, $this->array)) === count($needles);
508
  }
509
510
  /**
511
   * Creates an Arrayy object.
512
   *
513
   * @param array $array
514
   *
515
   * @return Arrayy (Immutable) Returns an new instance of the Arrayy object.
516
   */
517
  public static function create($array = array())
518
  {
519
    return new static($array);
520
  }
521
522
  /**
523
   * WARNING: Creates an Arrayy object by reference.
524
   *
525
   * @param array $array
526
   *
527
   * @return self (Mutable) Return this Arrayy object.
528 5
   */
529
  public function createByReference(&$array = array())
530 5
  {
531
    $array = $this->fallbackForArray($array);
532 5
533
    $this->array = &$array;
534
535
    return $this;
536
  }
537
538
  /**
539
   * Create an new Arrayy object via JSON.
540
   *
541
   * @param string $json
542 4
   *
543
   * @return Arrayy (Immutable) Returns an new instance of the Arrayy object.
544 4
   */
545 4
  public static function createFromJson($json)
546
  {
547 3
    $array = UTF8::json_decode($json, true);
548
549
    return static::create($array);
550 4
  }
551
552
  /**
553
   * Create an new instance filled with values from an object that have implemented ArrayAccess.
554
   *
555
   * @param \ArrayAccess $object Object that implements ArrayAccess
556
   *
557
   * @return Arrayy (Immutable) Returns an new instance of the Arrayy object.
558
   */
559
  public static function createFromObject(\ArrayAccess $object)
560
  {
561
    $array = new static();
562 8
    foreach ($object as $key => $value) {
563
      /** @noinspection OffsetOperationsInspection */
564 8
      $array[$key] = $value;
565 1
    }
566
567 1
    return $array;
568 1
  }
569
570
  /**
571
   * Create an new Arrayy object via string.
572 7
   *
573
   * @param string      $str       The input string.
574
   * @param string|null $delimiter The boundary string.
575
   * @param string|null $regEx     Use the $delimiter or the $regEx, so if $pattern is null, $delimiter will be used.
576 8
   *
577
   * @return Arrayy (Immutable) Returns an new instance of the Arrayy object.
578
   */
579
  public static function createFromString($str, $delimiter, $regEx = null)
580 8
  {
581 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...
582
      preg_match_all($regEx, $str, $array);
583 8
584
      if (!empty($array)) {
585
        $array = $array[0];
586 8
      }
587
588
    } else {
589
      $array = explode($delimiter, $str);
590
    }
591
592
    // trim all string in the array
593
    array_walk(
594
        $array,
595
        function (&$val) {
596
          /** @noinspection ReferenceMismatchInspection */
597
          if (is_string($val)) {
598 1
            $val = trim($val);
599
          }
600 1
        }
601
    );
602
603
    return static::create($array);
604
  }
605
606
  /**
607
   * Create an new instance containing a range of elements.
608
   *
609
   * @param mixed $low  First value of the sequence
610
   * @param mixed $high The sequence is ended upon reaching the end value
611
   * @param int   $step Used as the increment between elements in the sequence
612 5
   *
613
   * @return Arrayy (Immutable) Returns an new instance of the Arrayy object.
614 5
   */
615
  public static function createWithRange($low, $high, $step = 1)
616 5
  {
617
    return static::create(range($low, $high, $step));
618
  }
619
620
  /**
621
   * Custom sort by index via "uksort".
622
   *
623
   * @link http://php.net/manual/en/function.uksort.php
624
   *
625
   * @param callable $function
626
   *
627
   * @return self (Mutable) Return this Arrayy object.
628 4
   */
629
  public function customSortKeys($function)
630 4
  {
631
    uksort($this->array, $function);
632 4
633
    return $this;
634
  }
635
636
  /**
637
   * Custom sort by value via "usort".
638
   *
639
   * @link http://php.net/manual/en/function.usort.php
640
   *
641
   * @param callable $function
642 12
   *
643
   * @return self (Mutable) Return this Arrayy object.
644 12
   */
645
  public function customSortValues($function)
646 12
  {
647
    usort($this->array, $function);
648
649
    return $this;
650
  }
651
652
  /**
653
   * Return values that are only in the current array.
654
   *
655
   * @param array $array
656
   *
657 1
   * @return Arrayy (Immutable)
658
   */
659 1
  public function diff(array $array = array())
660
  {
661 1
    $result = array_diff($this->array, $array);
662 1
663
    return static::create($result);
664 1
  }
665
666
  /**
667 1
   * Return values that are only in the current multi-dimensional array.
668 1
   *
669 1
   * @param array      $array
670 1
   * @param null|array $helperVariableForRecursion (only for internal usage)
671 1
   *
672 1
   * @return Arrayy (Immutable)
673
   */
674
  public function diffRecursive(array $array = array(), $helperVariableForRecursion = null)
675 1
  {
676 1
    $result = array();
677
678
    if (
679
        $helperVariableForRecursion !== null
680 1
        &&
681
        is_array($helperVariableForRecursion)
682
    ) {
683
      $arrayForTheLoop = $helperVariableForRecursion;
684 1
    } else {
685
      $arrayForTheLoop = $this->array;
686
    }
687
688
    foreach ($arrayForTheLoop as $key => $value) {
689
      if (array_key_exists($key, $array)) {
690
        if (is_array($value)) {
691
          $recursiveDiff = $this->diffRecursive($array[$key], $value);
692
          if (!empty($recursiveDiff)) {
693
            $result[$key] = $recursiveDiff;
694 8
          }
695
        } else {
696 8
          if ($value != $array[$key]) {
697
            $result[$key] = $value;
698 8
          }
699
        }
700
      } else {
701
        $result[$key] = $value;
702
      }
703
    }
704
705
    return static::create($result);
706 1
  }
707
708 1
  /**
709
   * Return values that are only in the new $array.
710 1
   *
711 1
   * @param array $array
712
   *
713
   * @return Arrayy (Immutable)
714
   */
715
  public function diffReverse(array $array = array())
716
  {
717
    $result = array_diff($array, $this->array);
718
719
    return static::create($result);
720
  }
721
722
  /**
723 22
   * Divide an array into two arrays. One with keys and the other with values.
724
   *
725 22
   * @return Arrayy (Immutable)
726
   */
727 22
  public function divide()
728 18
  {
729
    return static::create(
730
        array(
731 22
            $this->keys(),
732
            $this->values(),
733
        )
734
    );
735
  }
736
737
  /**
738
   * Iterate over the current array and modify the array's value.
739
   *
740
   * @param \Closure $closure
741 4
   *
742
   * @return Arrayy (Immutable)
743 4
   */
744 4 View Code Duplication
  public function each(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
745 3
  {
746 1
    $array = $this->array;
747 3
748
    foreach ($array as $key => &$value) {
749
      $value = $closure($value, $key);
750
    }
751 4
752
    return static::create($array);
753
  }
754
755
  /**
756
   * Check if a value is in the current array using a closure.
757
   *
758
   * @param \Closure $closure
759
   *
760
   * @return bool Returns true if the given value is found, false otherwise
761
   */
762
  public function exists(\Closure $closure)
763
  {
764
    $isExists = false;
765
    foreach ($this->array as $key => $value) {
766
      if ($closure($value, $key)) {
767
        $isExists = true;
768
        break;
769
      }
770
    }
771 728
772
    return $isExists;
773 728
  }
774 725
775
  /**
776
   * create a fallback for array
777 9
   *
778
   * 1. use the current array, if it's a array
779
   * 2. call "getArray()" on object, if there is a "Arrayy"-object
780
   * 3. fallback to empty array, if there is nothing
781 9
   * 4. call "createFromObject()" on object, if there is a "\ArrayAccess"-object
782 6
   * 5. call "__toArray()" on object, if the method exists
783
   * 6. cast a string or object with "__toString()" into an array
784
   * 7. throw a "InvalidArgumentException"-Exception
785 8
   *
786
   * @param $array
787
   *
788
   * @return array
789
   *
790 8
   * @throws \InvalidArgumentException
791
   */
792
  protected function fallbackForArray(&$array)
793
  {
794
    if (is_array($array)) {
795
      return $array;
796 8
    }
797
798 8
    if ($array instanceof self) {
799
      return $array->getArray();
800 6
    }
801
802
    if (!$array) {
803 2
      return array();
804 2
    }
805
806
    if ($array instanceof \ArrayAccess) {
807
      /** @noinspection ReferenceMismatchInspection */
808
      return self::createFromObject($array)->getArray();
809
    }
810
811
    if (is_object($array) && method_exists($array, '__toArray')) {
812
      return (array)$array->__toArray();
813
    }
814
815 9
    /** @noinspection ReferenceMismatchInspection */
816
    if (
817 9
        is_string($array)
818 1
        ||
819
        (is_object($array) && method_exists($array, '__toString'))
820
    ) {
821 9
      return (array)$array;
822
    }
823 9
824
    throw new \InvalidArgumentException(
825
        'Passed value should be a array'
826
    );
827
  }
828
829
  /**
830
   * Find all items in an array that pass the truth test.
831
   *
832
   * @param \Closure|null $closure
833
   *
834
   * @return Arrayy (Immutable)
835
   */
836
  public function filter($closure = null)
837
  {
838
    if (!$closure) {
839
      return $this->clean();
840
    }
841
842
    $array = array_filter($this->array, $closure);
843
844
    return static::create($array);
845
  }
846 1
847
  /**
848 1
   * Filters an array of objects (or a numeric array of associative arrays) based on the value of a particular property
849 1
   * within that.
850
   *
851
   * @param        $property
852
   * @param        $value
853
   * @param string $comparisonOp
854 1
   *                            'eq' (equals),<br />
855 1
   *                            'gt' (greater),<br />
856
   *                            'gte' || 'ge' (greater or equals),<br />
857
   *                            'lt' (less),<br />
858 1
   *                            'lte' || 'le' (less or equals),<br />
859
   *                            'ne' (not equals),<br />
860
   *                            'contains',<br />
861 1
   *                            'notContains',<br />
862
   *                            'newer' (via strtotime),<br />
863
   *                            'older' (via strtotime),<br />
864 1
   *
865
   * @return Arrayy (Immutable)
866 1
   */
867 1
  public function filterBy($property, $value, $comparisonOp = null)
868
  {
869
    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...
870 1
      $comparisonOp = is_array($value) ? 'contains' : 'eq';
871
    }
872
873 1
    $ops = array(
874
        'eq'          => function ($item, $prop, $value) {
875
          return $item[$prop] === $value;
876 1
        },
877
        'gt'          => function ($item, $prop, $value) {
878 1
          return $item[$prop] > $value;
879 1
        },
880
        'ge'          => function ($item, $prop, $value) {
881
          return $item[$prop] >= $value;
882 1
        },
883
        'gte'         => function ($item, $prop, $value) {
884
          return $item[$prop] >= $value;
885 1
        },
886
        'lt'          => function ($item, $prop, $value) {
887
          return $item[$prop] < $value;
888 1
        },
889
        'le'          => function ($item, $prop, $value) {
890
          return $item[$prop] <= $value;
891 1
        },
892
        'lte'         => function ($item, $prop, $value) {
893 1
          return $item[$prop] <= $value;
894
        },
895 1
        'ne'          => function ($item, $prop, $value) {
896 1
          return $item[$prop] !== $value;
897 1
        },
898 1
        'contains'    => function ($item, $prop, $value) {
899
          return in_array($item[$prop], (array)$value, true);
900 1
        },
901 1
        'notContains' => function ($item, $prop, $value) {
902 1
          return !in_array($item[$prop], (array)$value, true);
903
        },
904 1
        'newer'       => function ($item, $prop, $value) {
905 1
          return strtotime($item[$prop]) > strtotime($value);
906
        },
907
        'older'       => function ($item, $prop, $value) {
908
          return strtotime($item[$prop]) < strtotime($value);
909 1
        },
910
    );
911
912
    $result = array_values(
913
        array_filter(
914
            (array)$this->array,
915
            function ($item) use (
916
                $property,
917
                $value,
918
                $ops,
919
                $comparisonOp
920 8
            ) {
921
              $item = (array)$item;
922 8
              $itemArrayy = new Arrayy($item);
923 6
              $item[$property] = $itemArrayy->get($property, array());
924 6
925
              return $ops[$comparisonOp]($item, $property, $value);
926
            }
927
        )
928 3
    );
929
930
    return static::create($result);
931
  }
932
933
  /**
934
   * Find the first item in an array that passes the truth test,
935
   *  otherwise return false
936
   *
937
   * @param \Closure $closure
938
   *
939
   * @return mixed|false false if we did not find the value
940
   */
941
  public function find(\Closure $closure)
942
  {
943
    foreach ($this->array as $key => $value) {
944
      if ($closure($value, $key)) {
945
        return $value;
946
      }
947
    }
948
949
    return false;
950 13
  }
951
952 13
  /**
953 13
   * find by ...
954
   *
955 13
   * @param        $property
956 3
   * @param        $value
957
   * @param string $comparisonOp
958 10
   *
959
   * @return Arrayy (Immutable)
960
   */
961
  public function findBy($property, $value, $comparisonOp = 'eq')
962
  {
963
    return $this->filterBy($property, $value, $comparisonOp);
964
  }
965
966
  /**
967
   * Get the first value from the current array.
968
   *
969 28
   * @return mixed Return null if there wasn't a element.
970
   */
971 28
  public function first()
972 7
  {
973 7
    $tmpArray = $this->array;
974
    $result = array_shift($tmpArray);
975 21
976 21
    if ($result === null) {
977 21
      return null;
978
    } else {
979
      return $result;
980 28
    }
981
  }
982
983
  /**
984
   * Get the first value(s) from the current array.
985
   *
986
   * @param int|null $number how many values you will take?
987
   *
988
   * @return Arrayy (Immutable)
989
   */
990 26
  public function firstsImmutable($number = null)
991
  {
992 26
    if ($number === null) {
993 11
      $arrayTmp = $this->array;
994
      $array = (array)array_shift($arrayTmp);
995 15
    } else {
996 15
      $number = (int)$number;
997
      $arrayTmp = $this->array;
998
      $array = array_splice($arrayTmp, 0, $number, true);
999 26
    }
1000
1001
    return static::create($array);
1002
  }
1003
1004
  /**
1005
   * Get the first value(s) from the current array.
1006
   *
1007 1
   * @param int|null $number how many values you will take?
1008
   *
1009 1
   * @return self (Mutable)
1010
   */
1011 1
  public function firstsMutable($number = null)
1012
  {
1013
    if ($number === null) {
1014
      $this->array = (array)array_shift($this->array);
1015
    } else {
1016
      $number = (int)$number;
1017
      $this->array = array_splice($this->array, 0, $number, true);
1018
    }
1019
1020
    return $this;
1021
  }
1022
1023 54
  /**
1024
   * Exchanges all keys with their associated values in an array.
1025 54
   *
1026 3
   * @return Arrayy (Immutable)
1027
   */
1028 52
  public function flip()
1029
  {
1030
    $result = array_flip($this->array);
1031 54
1032 1
    return static::create($result);
1033
  }
1034
1035 54
  /**
1036 42
   * Get a value from an array (optional using dot-notation).
1037
   *
1038
   * @param string $key     The key to look for.
1039
   * @param mixed  $default Default value to fallback to.
1040 20
   * @param array  $array   The array to get from, if it's set to "null" we use the current array from the class.
1041 20
   *
1042 17
   * @return mixed
1043
   */
1044
  public function get($key, $default = null, $array = null)
1045 3
  {
1046
    if (
1047
        $array !== null
1048 3
        &&
1049
        is_array($array)
1050
    ) {
1051
      $usedArray = $array;
1052
    } else {
1053
      $usedArray = $this->array;
1054
    }
1055
1056 481
    if ($key === null) {
1057
      return self::create($usedArray);
1058 481
    }
1059
1060
    if (isset($usedArray[$key])) {
1061
      if (is_array($usedArray[$key])) {
1062
        return self::create($usedArray[$key]);
1063
      } else {
1064
        return $usedArray[$key];
1065
      }
1066
    }
1067
1068
    // Crawl through array, get key according to object or not
1069
    foreach (explode($this->pathSeparator, (string)$key) as $segment) {
1070
      if (!isset($usedArray[$segment])) {
1071
        return $default instanceof \Closure ? $default() : $default;
1072
      }
1073 1
1074
      $usedArray = $usedArray[$segment];
1075 1
    }
1076
1077 1
    if (is_array($usedArray)) {
1078
      return self::create($usedArray);
1079
    } else {
1080
      return $usedArray;
1081
    }
1082
  }
1083
1084
  /**
1085
   * Get the current array from the "Arrayy"-object.
1086
   *
1087 38
   * @return array
1088
   */
1089 38
  public function getArray()
1090 10
  {
1091
    array_map(array('self', 'internalGetArray'), $this->array);
1092 10
1093 2
    return $this->array;
1094
  }
1095 8
1096
  /**
1097
   * @param mixed $value
1098
   */
1099
  protected function internalGetArray(&$value)
1100 38
  {
1101
    if ($value instanceof self) {
1102 38
      $value &= $value->getArray();
1103
    }
1104
  }
1105
1106
  /**
1107 38
   * Returns the values from a single column of the input array, identified by
1108
   * the $columnKey, can be used to extract data-columns from multi-arrays.
1109
   *
1110
   * Info: Optionally, you may provide an $indexKey to index the values in the returned
1111
   * array by the values from the $indexKey column in the input array.
1112
   *
1113
   * @param mixed $columnKey
1114
   * @param mixed $indexKey
1115
   *
1116
   * @return Arrayy (Immutable)
1117 1
   */
1118
  public function getColumn($columnKey = null, $indexKey = null)
1119 1
  {
1120
    $result = array_column($this->array, $columnKey, $indexKey);
1121
1122
    return static::create($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by array_column($this->array, $columnKey, $indexKey) on line 1120 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...
1123
  }
1124
1125
  /**
1126
   * Get correct PHP constant for direction.
1127
   *
1128
   * @param int|string $direction
1129 3
   *
1130
   * @return int
1131 3
   */
1132
  protected function getDirection($direction)
1133
  {
1134
    if (is_string($direction)) {
1135
      $direction = strtolower($direction);
1136
1137
      if ($direction === 'desc') {
1138
        $direction = SORT_DESC;
1139
      } else {
1140
        $direction = SORT_ASC;
1141 3
      }
1142
    }
1143 3
1144
    if (
1145
        $direction !== SORT_DESC
1146
        &&
1147
        $direction !== SORT_ASC
1148
    ) {
1149
      $direction = SORT_ASC;
1150
    }
1151
1152
    return $direction;
1153
  }
1154
1155 9
  /**
1156
   * alias: for "Arrayy->keys()"
1157 9
   *
1158
   * @see Arrayy::keys()
1159
   *
1160
   * @return Arrayy (Immutable)
1161
   */
1162
  public function getKeys()
1163
  {
1164
    return $this->keys();
1165
  }
1166
1167 3
  /**
1168
   * alias: for "Arrayy->randomImmutable()"
1169 3
   *
1170
   * @see Arrayy::randomImmutable()
1171
   *
1172
   * @return Arrayy (Immutable)
1173
   */
1174
  public function getRandom()
1175
  {
1176
    return $this->randomImmutable();
1177
  }
1178
1179
  /**
1180
   * alias: for "Arrayy->randomKey()"
1181 6
   *
1182
   * @see Arrayy::randomKey()
1183 6
   *
1184
   * @return mixed get a key/index or null if there wasn't a key/index
1185
   */
1186
  public function getRandomKey()
1187
  {
1188
    return $this->randomKey();
1189
  }
1190
1191
  /**
1192
   * alias: for "Arrayy->randomKeys()"
1193
   *
1194 3
   * @see Arrayy::randomKeys()
1195
   *
1196 3
   * @param int $number
1197 3
   *
1198
   * @return Arrayy (Immutable)
1199
   */
1200 3
  public function getRandomKeys($number)
1201 3
  {
1202 3
    return $this->randomKeys($number);
1203
  }
1204
1205 3
  /**
1206 2
   * alias: for "Arrayy->randomValue()"
1207 1
   *
1208 1
   * @see Arrayy::randomValue()
1209
   *
1210 1
   * @return mixed get a random value or null if there wasn't a value
1211 3
   */
1212
  public function getRandomValue()
1213
  {
1214
    return $this->randomValue();
1215
  }
1216
1217 3
  /**
1218
   * alias: for "Arrayy->randomValues()"
1219
   *
1220
   * @see Arrayy::randomValues()
1221
   *
1222
   * @param int $number
1223
   *
1224
   * @return Arrayy (Immutable)
1225
   */
1226
  public function getRandomValues($number)
1227 19
  {
1228
    return $this->randomValues($number);
1229
  }
1230 19
1231
  /**
1232 19
   * Group values from a array according to the results of a closure.
1233
   *
1234
   * @param string $grouper a callable function name
1235
   * @param bool   $saveKeys
1236
   *
1237
   * @return Arrayy (Immutable)
1238
   */
1239
  public function group($grouper, $saveKeys = false)
1240
  {
1241
    $array = (array)$this->array;
1242 27
    $result = array();
1243
1244 27
    // Iterate over values, group by property/results from closure
1245
    foreach ($array as $key => $value) {
1246
1247
      $groupKey = is_callable($grouper) ? $grouper($value, $key) : $this->get($grouper, null, $value);
1248
      $newValue = $this->get($groupKey, null, $result);
1249
1250
      if ($groupKey instanceof self) {
1251
        $groupKey = $groupKey->getArray();
1252
      }
1253
1254
      if ($newValue instanceof self) {
1255
        $newValue = $newValue->getArray();
1256
      }
1257
1258 3
      // Add to results
1259
      if ($groupKey !== null) {
1260 3
        if ($saveKeys) {
1261
          $result[$groupKey] = $newValue;
1262 3
          $result[$groupKey][$key] = $value;
1263 3
        } else {
1264 3
          $result[$groupKey] = $newValue;
1265
          $result[$groupKey][] = $value;
1266
        }
1267
      }
1268 3
1269
    }
1270
1271
    return static::create($result);
1272
  }
1273
1274
  /**
1275
   * Check if an array has a given key.
1276
   *
1277
   * @param mixed $key
1278
   *
1279
   * @return bool
1280 4
   */
1281
  public function has($key)
1282 4
  {
1283
    // Generate unique string to use as marker.
1284
    $unFound = (string)uniqid('arrayy', true);
1285
1286
    return $this->get($key, $unFound) !== $unFound;
1287
  }
1288
1289
  /**
1290
   * Implodes an array.
1291
   *
1292 12
   * @param string $with What to implode it with
1293
   *
1294 12
   * @return string
1295
   */
1296 12
  public function implode($with = '')
1297
  {
1298
    return implode($with, $this->array);
1299
  }
1300
1301
  /**
1302
   * Given a list and an iterate-function that returns
1303
   * a key for each element in the list (or a property name),
1304
   * returns an object with an index of each item.
1305
   *
1306 18
   * Just like groupBy, but for when you know your keys are unique.
1307
   *
1308 18
   * @param mixed $key
1309
   *
1310
   * @return Arrayy (Immutable)
1311 18
   */
1312
  public function indexBy($key)
1313
  {
1314
    $results = array();
1315
1316
    foreach ($this->array as $a) {
1317
      if (isset($a[$key])) {
1318
        $results[$a[$key]] = $a;
1319
      }
1320
    }
1321 18
1322
    return static::create($results);
1323 18
  }
1324
1325 18
  /**
1326
   * alias: for "Arrayy->searchIndex()"
1327
   *
1328
   * @see Arrayy::searchIndex()
1329
   *
1330
   * @param mixed $value Value to search for
1331
   *
1332
   * @return mixed
1333
   */
1334
  public function indexOf($value)
1335
  {
1336 27
    return $this->searchIndex($value);
1337
  }
1338 27
1339
  /**
1340
   * Get everything but the last..$to items.
1341
   *
1342
   * @param int $to
1343 27
   *
1344 27
   * @return Arrayy (Immutable)
1345
   */
1346
  public function initial($to = 1)
1347 27
  {
1348 2
    $slice = count($this->array) - $to;
1349
1350
    return $this->firstsImmutable($slice);
1351
  }
1352 2
1353
  /**
1354
   * Internal mechanics of remove method.
1355 2
   *
1356
   * @param string $key
1357
   *
1358 27
   * @return boolean
1359
   */
1360 27
  protected function internalRemove($key)
1361
  {
1362
    $path = explode($this->pathSeparator, (string)$key);
1363
1364
    // Crawl though the keys
1365
    while (count($path) > 1) {
1366
      $key = array_shift($path);
1367
1368
      if (!$this->has($key)) {
1369
        return false;
1370 2
      }
1371
1372 2
      $this->array = &$this->array[$key];
1373
    }
1374
1375
    $key = array_shift($path);
1376
1377
    unset($this->array[$key]);
1378
1379
    return true;
1380
  }
1381
1382 1
  /**
1383
   * Internal mechanic of set method.
1384 1
   *
1385
   * @param string $key
1386
   * @param mixed  $value
1387
   *
1388
   * @return bool
1389
   */
1390
  protected function internalSet($key, $value)
1391
  {
1392
    if ($key === null) {
1393
      return false;
1394
    }
1395 1
1396
    // init
1397
    $array =& $this->array;
1398 1
    $path = explode($this->pathSeparator, (string)$key);
1399 1
1400
    // Crawl through the keys
1401
    while (count($path) > 1) {
1402
      $key = array_shift($path);
1403 1
1404 1
      // If the key doesn't exist at this depth, we will just create an empty array
1405
      // to hold the next value, allowing us to create the arrays to hold final
1406 1
      // values at the correct depth. Then we'll keep digging into the array.
1407
      if (!isset($array[$key]) || !is_array($array[$key])) {
1408
        $array[$key] = self::create(array());
1409 1
      }
1410
1411
      $array =& $array[$key];
1412
    }
1413
1414
    $array[array_shift($path)] = $value;
1415
1416
    return true;
1417 15
  }
1418
1419 15
  /**
1420 3
   * Return an array with all elements found in input array.
1421
   *
1422
   * @param array $search
1423 13
   *
1424 13
   * @return Arrayy (Immutable)
1425 13
   */
1426
  public function intersection(array $search)
1427
  {
1428
    return static::create(array_values(array_intersect($this->array, $search)));
1429 3
  }
1430
1431
  /**
1432
   * Return a boolean flag which indicates whether the two input arrays have any common elements.
1433
   *
1434
   * @param array $search
1435
   *
1436
   * @return bool
1437 25
   */
1438
  public function intersects(array $search)
1439 25
  {
1440
    return count($this->intersection($search)->array) > 0;
1441
  }
1442
1443
  /**
1444
   * Invoke a function on all of an array's values.
1445
   *
1446
   * @param mixed $callable
1447
   * @param mixed $arguments
1448
   *
1449
   * @return Arrayy (Immutable)
1450
   */
1451
  public function invoke($callable, $arguments = array())
1452
  {
1453
    // If one argument given for each iteration, create an array for it.
1454
    if (!is_array($arguments)) {
1455
      $arguments = StaticArrayy::repeat($arguments, count($this->array))->getArray();
1456
    }
1457
1458
    // If the callable has arguments, pass them.
1459 14
    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...
1460
      $array = array_map($callable, $this->array, $arguments);
1461 14
    } else {
1462
      $array = array_map($callable, $this->array);
1463
    }
1464
1465
    return static::create($array);
1466
  }
1467
1468
  /**
1469 5
   * Check whether array is associative or not.
1470
   *
1471 5
   * @return bool Returns true if associative, false otherwise
1472 2
   */
1473
  public function isAssoc()
1474
  {
1475 4
    if ($this->isEmpty()) {
1476 4
      return false;
1477 4
    }
1478
1479
    foreach ($this->keys()->getArray() as $key) {
1480
      if (!is_string($key)) {
1481 2
        return false;
1482
      }
1483
    }
1484
1485
    return true;
1486
  }
1487
1488
  /**
1489 1
   * Check whether the array is empty or not.
1490
   *
1491 1
   * @return bool Returns true if empty, false otherwise
1492
   */
1493
  public function isEmpty()
1494
  {
1495
    return !$this->array;
1496
  }
1497
1498
  /**
1499 25
   * Check if the current array is equal to the given "$array" or not.
1500
   *
1501 25
   * @param array $array
1502
   *
1503
   * @return bool
1504
   */
1505
  public function isEqual(array $array)
1506
  {
1507
    return ($this->array === $array);
1508
  }
1509 4
1510
  /**
1511 4
   * Check if the current array is a multi-array.
1512
   *
1513 4
   * @return bool
1514 1
   */
1515
  public function isMultiArray()
1516 3
  {
1517
    return !(count($this->array) === count($this->array, COUNT_RECURSIVE));
1518
  }
1519
1520
  /**
1521
   * Check whether array is numeric or not.
1522
   *
1523
   * @return bool Returns true if numeric, false otherwise
1524
   */
1525
  public function isNumeric()
1526
  {
1527 12
    if ($this->isEmpty()) {
1528
      return false;
1529 12
    }
1530 8
1531 8
    foreach ($this->keys() as $key) {
1532
      if (!is_int($key)) {
1533 4
        return false;
1534 4
      }
1535
    }
1536
1537 12
    return true;
1538
  }
1539
1540
  /**
1541
   * Check if the current array is sequential [0, 1, 2, 3, 4, 5 ...] or not.
1542
   *
1543
   * @return bool
1544
   */
1545
  public function isSequential()
1546
  {
1547 12
    return array_keys($this->array) === range(0, count($this->array) - 1);
1548
  }
1549 12
1550 8
  /**
1551 8
   * Get all keys from the current array.
1552
   *
1553 4
   * @return Arrayy (Immutable)
1554 4
   */
1555
  public function keys()
1556
  {
1557 12
    return static::create(array_keys($this->array));
1558
  }
1559
1560
  /**
1561
   * Get the last value from the current array.
1562
   *
1563
   * @return mixed Return null if there wasn't a element.
1564
   */
1565
  public function last()
1566
  {
1567
    return $this->pop();
1568
  }
1569 10
1570
  /**
1571 10
   * Get the last value(s) from the current array.
1572
   *
1573
   * @param int|null $number
1574
   *
1575
   * @return Arrayy (Immutable)
1576
   */
1577
  public function lastsImmutable($number = null)
1578
  {
1579
    if ($number === null) {
1580
      $poppedValue = (array)$this->pop();
1581
      $arrayy = static::create($poppedValue);
1582 4
    } else {
1583
      $number = (int)$number;
1584 4
      $arrayy = $this->rest(-$number);
1585
    }
1586 4
1587
    return $arrayy;
1588
  }
1589
1590
  /**
1591
   * Get the last value(s) from the current array.
1592
   *
1593
   * @param int|null $number
1594
   *
1595
   * @return self (Mutable)
1596 9
   */
1597
  public function lastsMutable($number = null)
1598
  {
1599 9
    if ($number === null) {
1600
      $poppedValue = (array)$this->pop();
1601
      $this->array = static::create($poppedValue)->array;
1602 9
    } else {
1603 2
      $number = (int)$number;
1604
      $this->array = $this->rest(-$number)->array;
1605
    }
1606 7
1607
    return $this;
1608 7
  }
1609
1610
  /**
1611
   * Count the values from the current array.
1612
   *
1613
   * alias: for "Arrayy->size()"
1614
   *
1615
   * @see Arrayy::size()
1616
   *
1617
   * @return int
1618 9
   */
1619
  public function length()
1620
  {
1621 9
    return $this->size();
1622
  }
1623
1624 9
  /**
1625 2
   * Apply the given function to the every element of the array,
1626
   * collecting the results.
1627
   *
1628 7
   * @param callable $callable
1629
   *
1630 7
   * @return Arrayy (Immutable) Arrayy object with modified elements
1631
   */
1632
  public function map($callable)
1633
  {
1634
    $result = array_map($callable, $this->array);
1635
1636
    return static::create($result);
1637
  }
1638 10
1639
  /**
1640 10
   * Check if all items in current array match a truth test.
1641 1
   *
1642
   * @param \Closure $closure
1643
   *
1644 9
   * @return bool
1645
   */
1646 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...
1647
  {
1648
    // Reduce the array to only booleans
1649
    $array = $this->each($closure);
1650
1651
    // Check the results
1652
    if (count($array) === 0) {
1653
      return true;
1654
    }
1655
1656
    $array = array_search(false, $array->toArray(), false);
1657 25
1658
    return is_bool($array);
1659 25
  }
1660 4
1661
  /**
1662 21
   * Check if any item in the current array matches a truth test.
1663
   *
1664
   * @param \Closure $closure
1665 25
   *
1666
   * @return bool
1667
   */
1668 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...
1669
  {
1670
    // Reduce the array to only booleans
1671
    $array = $this->each($closure);
1672
1673
    // Check the results
1674
    if (count($array) === 0) {
1675
      return true;
1676
    }
1677
1678
    $array = array_search(true, $array->toArray(), false);
1679 16
1680
    return is_int($array);
1681 16
  }
1682 4
1683
  /**
1684 12
   * Get the max value from an array.
1685
   *
1686
   * @return mixed
1687 16
   */
1688
  public function max()
1689
  {
1690
    if ($this->count() === 0) {
1691
      return false;
1692
    }
1693
1694
    return max($this->array);
1695
  }
1696
1697
  /**
1698
   * Merge the new $array into the current array.
1699
   *
1700 16
   * - keep key,value from the current array, also if the index is in the new $array
1701
   *
1702 16
   * @param array $array
1703 4
   * @param bool  $recursive
1704
   *
1705 12
   * @return Arrayy (Immutable)
1706
   */
1707 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...
1708 16
  {
1709
    if (true === $recursive) {
1710
      $result = array_replace_recursive($this->array, $array);
1711
    } else {
1712
      $result = array_replace($this->array, $array);
1713
    }
1714
1715
    return static::create($result);
1716
  }
1717
1718
  /**
1719
   * Merge the new $array into the current array.
1720
   *
1721
   * - replace duplicate assoc-keys from the current array with the key,values from the new $array
1722 16
   * - create new indexes
1723
   *
1724 16
   * @param array $array
1725 4
   * @param bool  $recursive
1726
   *
1727 12
   * @return Arrayy (Immutable)
1728
   */
1729 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...
1730 16
  {
1731
    if (true === $recursive) {
1732
      $result = array_merge_recursive($this->array, $array);
1733
    } else {
1734
      $result = array_merge($this->array, $array);
1735
    }
1736
1737
    return static::create($result);
1738 10
  }
1739
1740 10
  /**
1741 1
   * Merge the the current array into the $array.
1742
   *
1743
   * - use key,value from the new $array, also if the index is in the current array
1744 9
   *
1745
   * @param array $array
1746
   * @param bool  $recursive
1747
   *
1748
   * @return Arrayy (Immutable)
1749
   */
1750 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...
1751
  {
1752
    if (true === $recursive) {
1753
      $result = array_replace_recursive($array, $this->array);
1754
    } else {
1755
      $result = array_replace($array, $this->array);
1756
    }
1757
1758
    return static::create($result);
1759
  }
1760
1761
  /**
1762
   * Merge the current array into the new $array.
1763
   *
1764
   * - replace duplicate assoc-keys from new $array with the key,values from the current array
1765
   * - create new indexes
1766
   *
1767
   * @param array $array
1768
   * @param bool  $recursive
1769 4
   *
1770
   * @return Arrayy (Immutable)
1771 4
   */
1772 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...
1773 4
  {
1774
    if (true === $recursive) {
1775
      $result = array_merge_recursive($array, $this->array);
1776
    } else {
1777
      $result = array_merge($array, $this->array);
1778
    }
1779
1780
    return static::create($result);
1781 16
  }
1782
1783 16
  /**
1784
   * Get the min value from an array.
1785
   *
1786
   * @return mixed
1787
   */
1788
  public function min()
1789
  {
1790
    if ($this->count() === 0) {
1791
      return false;
1792
    }
1793
1794 8
    return min($this->array);
1795
  }
1796 8
1797 8
  /**
1798
   * Get a subset of the items from the given array.
1799
   *
1800 1
   * @param mixed[] $keys
1801
   *
1802
   * @return Arrayy (Immutable)
1803 8
   */
1804
  public function only(array $keys)
1805
  {
1806
    $array = $this->array;
1807
1808
    return static::create(array_intersect_key($array, array_flip($keys)));
1809
  }
1810
1811 4
  /**
1812
   * Pad array to the specified size with a given value.
1813 4
   *
1814 4
   * @param int   $size  Size of the result array
1815 4
   * @param mixed $value Empty value by default
1816
   *
1817
   * @return Arrayy (Immutable) Arrayy object padded to $size with $value
1818 4
   */
1819
  public function pad($size, $value)
1820
  {
1821
    $result = array_pad($this->array, $size, $value);
1822
1823
    return static::create($result);
1824
  }
1825
1826
  /**
1827
   * Pop a specified value off the end of the current array.
1828 17
   *
1829
   * @return mixed The popped element from the current array. (Mutable)
1830 17
   */
1831
  public function pop()
1832
  {
1833
    return array_pop($this->array);
1834 17
  }
1835 14
1836
  /**
1837 14
   * Prepend a value to the current array.
1838
   *
1839
   * @param mixed $value
1840 5
   * @param mixed $key
1841 5
   *
1842
   * @return self (Mutable) Return this Arrayy object, with the prepended value.
1843 5
   */
1844
  public function prepend($value, $key = null)
1845
  {
1846
    if ($key === null) {
1847
      array_unshift($this->array, $value);
1848
    } else {
1849
      /** @noinspection AdditionOperationOnArraysInspection */
1850
      $this->array = array($key => $value) + $this->array;
1851
    }
1852
1853
    return $this;
1854 4
  }
1855
1856 4
  /**
1857
   * Push one or more values onto the end of array at once.
1858 4
   *
1859
   * @return self (Mutable) Return this Arrayy object, with pushed elements to the end of array.
1860
   */
1861 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...
1862 4
  {
1863
    if (func_num_args()) {
1864
      $args = array_merge(array(&$this->array), func_get_args());
1865
      call_user_func_array('array_push', $args);
1866
    }
1867
1868
    return $this;
1869
  }
1870
1871
  /**
1872
   * Get a random value from the current array.
1873
   *
1874 14
   * @param null|int $number how many values you will take?
1875
   *
1876 14
   * @return Arrayy (Immutable)
1877 14
   */
1878
  public function randomImmutable($number = null)
1879 14
  {
1880 3
    if ($this->count() === 0) {
1881
      return static::create();
1882 3
    }
1883
1884 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...
1885
      $arrayRandValue = (array)$this->array[array_rand($this->array)];
1886
1887
      return static::create($arrayRandValue);
1888
    }
1889 11
1890
    $arrayTmp = $this->array;
1891 11
    shuffle($arrayTmp);
1892
1893
    return self::create($arrayTmp)->firstsImmutable($number);
1894
  }
1895
1896
  /**
1897
   * Pick a random key/index from the keys of this array.
1898
   *
1899
   *
1900
   * @return mixed get a key/index or null if there wasn't a key/index
1901 16
   *
1902
   * @throws \RangeException If array is empty
1903 16
   */
1904
  public function randomKey()
1905
  {
1906
    $result = $this->randomKeys(1);
1907 16
1908 6
    if (!isset($result[0])) {
1909 6
      $result[0] = null;
1910
    }
1911 6
1912
    return $result[0];
1913
  }
1914 11
1915
  /**
1916 11
   * Pick a given number of random keys/indexes out of this array.
1917
   *
1918
   * @param int $number The number of keys/indexes (should be <= $this->count())
1919
   *
1920
   * @return Arrayy (Immutable)
1921
   *
1922
   * @throws \RangeException If array is empty
1923
   */
1924 4
  public function randomKeys($number)
1925
  {
1926 4
    $number = (int)$number;
1927
    $count = $this->count();
1928 4
1929
    if ($number === 0 || $number > $count) {
1930
      throw new \RangeException(
1931
          sprintf(
1932 4
              'Number of requested keys (%s) must be equal or lower than number of elements in this array (%s)',
1933
              $number,
1934
              $count
1935
          )
1936
      );
1937
    }
1938
1939
    $result = (array)array_rand($this->array, $number);
1940
1941
    return static::create($result);
1942 7
  }
1943
1944 7
  /**
1945
   * Get a random value from the current array.
1946 7
   *
1947
   * @param null|int $number how many values you will take?
1948
   *
1949
   * @return Arrayy (Mutable)
1950
   */
1951
  public function randomMutable($number = null)
1952
  {
1953
    if ($this->count() === 0) {
1954
      return static::create();
1955
    }
1956
1957 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...
1958
      $arrayRandValue = (array)$this->array[array_rand($this->array)];
1959 9
      $this->array = $arrayRandValue;
1960
1961 9
      return $this;
1962 9
    }
1963 9
1964 9
    shuffle($this->array);
1965 1
1966
    return $this->firstsMutable($number);
1967
  }
1968
1969
  /**
1970 9
   * Pick a random value from the values of this array.
1971
   *
1972
   * @return mixed get a random value or null if there wasn't a value
1973
   */
1974
  public function randomValue()
1975
  {
1976
    $result = $this->randomImmutable();
1977
1978
    if (!isset($result[0])) {
1979
      $result[0] = null;
1980
    }
1981 3
1982
    return $result[0];
1983 3
  }
1984
1985 3
  /**
1986
   * Pick a given number of random values out of this array.
1987
   *
1988 3
   * @param int $number
1989
   *
1990
   * @return Arrayy (Mutable)
1991 3
   */
1992
  public function randomValues($number)
1993
  {
1994
    $number = (int)$number;
1995
1996
    return $this->randomMutable($number);
1997
  }
1998
1999 9
  /**
2000
   * Get a random value from an array, with the ability to skew the results.
2001 9
   *
2002
   * Example: randomWeighted(['foo' => 1, 'bar' => 2]) has a 66% chance of returning bar.
2003 9
   *
2004
   * @param array    $array
2005
   * @param null|int $number how many values you will take?
2006
   *
2007
   * @return Arrayy (Immutable)
2008
   */
2009
  public function randomWeighted(array $array, $number = null)
2010
  {
2011
    $options = array();
2012
    foreach ($array as $option => $weight) {
2013 1
      if ($this->searchIndex($option) !== false) {
2014
        for ($i = 0; $i < $weight; ++$i) {
2015 1
          $options[] = $option;
2016
        }
2017 1
      }
2018 1
    }
2019 1
2020
    return $this->mergeAppendKeepIndex($options)->randomImmutable($number);
2021
  }
2022
2023 1
  /**
2024
   * Reduce the current array via callable e.g. anonymous-function.
2025
   *
2026
   * @param mixed $callable
2027
   * @param array $init
2028
   *
2029
   * @return Arrayy (Immutable)
2030
   */
2031
  public function reduce($callable, array $init = array())
2032
  {
2033 18
    $result = array_reduce($this->array, $callable, $init);
2034
2035
    if ($result === null) {
2036 18
      $this->array = array();
2037
    } else {
2038
      $this->array = (array)$result;
2039
    }
2040
2041
    return static::create($this->array);
2042
  }
2043
2044 18
  /**
2045
   * Create a numerically re-indexed Arrayy object.
2046 18
   *
2047
   * @return self (Mutable) Return this Arrayy object, with re-indexed array-elements.
2048
   */
2049
  public function reindex()
2050
  {
2051
    $this->array = array_values($this->array);
2052
2053
    return $this;
2054 7
  }
2055
2056 7
  /**
2057 7
   * Return all items that fail the truth test.
2058
   *
2059 7
   * @param \Closure $closure
2060
   *
2061
   * @return Arrayy (Immutable)
2062
   */
2063 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...
2064
  {
2065
    $filtered = array();
2066
2067 7
    foreach ($this->array as $key => $value) {
2068
      if (!$closure($value, $key)) {
2069 7
        $filtered[$key] = $value;
2070 7
      }
2071
    }
2072 7
2073
    return static::create($filtered);
2074
  }
2075
2076
  /**
2077
   * Remove a value from the current array (optional using dot-notation).
2078
   *
2079
   * @param mixed $key
2080
   *
2081
   * @return Arrayy (Immutable)
2082 7
   */
2083
  public function remove($key)
2084 7
  {
2085 7
    // Recursive call
2086 6
    if (is_array($key)) {
2087 6
      foreach ($key as $k) {
2088
        $this->internalRemove($k);
2089
      }
2090 6
2091
      return static::create($this->array);
2092
    }
2093
2094 7
    $this->internalRemove($key);
2095 7
2096
    return static::create($this->array);
2097
  }
2098 7
2099
  /**
2100
   * Remove the first value from the current array.
2101
   *
2102
   * @return Arrayy (Immutable)
2103
   */
2104
  public function removeFirst()
2105
  {
2106
    $tmpArray = $this->array;
2107
    array_shift($tmpArray);
2108
2109
    return static::create($tmpArray);
2110 2
  }
2111
2112 2
  /**
2113
   * Remove the last value from the current array.
2114 2
   *
2115
   * @return Arrayy (Immutable)
2116
   */
2117
  public function removeLast()
2118
  {
2119
    $tmpArray = $this->array;
2120
    array_pop($tmpArray);
2121
2122
    return static::create($tmpArray);
2123
  }
2124 2
2125
  /**
2126 2
   * Removes a particular value from an array (numeric or associative).
2127
   *
2128 2
   * @param mixed $value
2129
   *
2130
   * @return Arrayy (Immutable)
2131
   */
2132
  public function removeValue($value)
2133
  {
2134
    $isNumericArray = true;
2135
    foreach ($this->array as $key => $item) {
2136
      if ($item === $value) {
2137
        if (!is_int($key)) {
2138 2
          $isNumericArray = false;
2139
        }
2140 2
        unset($this->array[$key]);
2141
      }
2142 2
    }
2143
2144
    if ($isNumericArray) {
2145
      $this->array = array_values($this->array);
2146
    }
2147
2148
    return static::create($this->array);
2149
  }
2150
2151
  /**
2152 1
   * Replace a key with a new key/value pair.
2153
   *
2154 1
   * @param $replace
2155 1
   * @param $key
2156
   * @param $value
2157 1
   *
2158
   * @return Arrayy (Immutable)
2159
   */
2160
  public function replace($replace, $key, $value)
2161
  {
2162
    $this->remove($replace);
2163
2164
    return $this->set($key, $value);
2165
  }
2166
2167
  /**
2168 3
   * Create an array using the current array as values and the other array as keys.
2169
   *
2170 3
   * @param array $keys Keys array
2171 3
   *
2172
   * @return Arrayy (Immutable) Arrayy object with keys from the other array.
2173 3
   */
2174 3
  public function replaceAllKeys(array $keys)
2175
  {
2176
    $result = array_combine($keys, $this->array);
2177 3
2178
    return static::create($result);
2179
  }
2180
2181
  /**
2182
   * Create an array using the current array as keys and the other array as values.
2183
   *
2184
   * @param array $array Values array
2185
   *
2186
   * @return Arrayy (Immutable) Arrayy object with values from the other array.
2187
   */
2188 1
  public function replaceAllValues(array $array)
2189
  {
2190 1
    $result = array_combine($this->array, $array);
2191
2192 1
    return static::create($result);
2193 1
  }
2194
2195
  /**
2196 1
   * Replace the keys in an array with another set.
2197
   *
2198
   * @param array $keys An array of keys matching the array's size
2199
   *
2200
   * @return Arrayy (Immutable)
2201
   */
2202
  public function replaceKeys(array $keys)
2203
  {
2204
    $values = array_values($this->array);
2205
    $result = array_combine($keys, $values);
2206 15
2207
    return static::create($result);
2208 15
  }
2209
2210 15
  /**
2211
   * Replace the first matched value in an array.
2212
   *
2213
   * @param mixed $search
2214
   * @param mixed $replacement
2215
   *
2216
   * @return Arrayy (Immutable)
2217
   */
2218
  public function replaceOneValue($search, $replacement = '')
2219
  {
2220
    $array = $this->array;
2221
    $key = array_search($search, $array, true);
2222
2223 1
    if ($key !== false) {
2224
      $array[$key] = $replacement;
2225 1
    }
2226
2227 1
    return static::create($array);
2228 1
  }
2229 1
2230 1
  /**
2231 1
   * Replace values in the current array.
2232 1
   *
2233 1
   * @param string $search      The string to replace.
2234 1
   * @param string $replacement What to replace it with.
2235 1
   *
2236 1
   * @return Arrayy (Immutable)
2237 1
   */
2238 1
  public function replaceValues($search, $replacement = '')
2239 1
  {
2240
    $array = $this->each(
2241 1
        function ($value) use ($search, $replacement) {
2242 1
          return UTF8::str_replace($search, $replacement, $value);
2243
        }
2244
    );
2245
2246
    return $array;
2247
  }
2248 1
2249
  /**
2250
   * Get the last elements from index $from until the end of this array.
2251
   *
2252
   * @param int $from
2253
   *
2254
   * @return Arrayy (Immutable)
2255
   */
2256 7
  public function rest($from = 1)
2257
  {
2258 7
    $tmpArray = $this->array;
2259
2260 7
    return static::create(array_splice($tmpArray, $from));
2261
  }
2262
2263
  /**
2264
   * Move an array element to a new index.
2265
   *
2266
   * cherry-picked from: http://stackoverflow.com/questions/12624153/move-an-array-element-to-a-new-index-in-php
2267
   *
2268
   * @param int|string $from
2269
   * @param int|string $to
2270 20
   *
2271
   * @return Arrayy (Immutable)
2272 20
   */
2273
  public function moveElement($from, $to)
2274
  {
2275
    $array = $this->array;
2276
2277
    if (is_int($from)) {
2278
      $tmp = array_splice($array, $from, 1);
2279
      array_splice($array, $to, 0, $tmp);
2280
      $output = $array;
2281
    } elseif (is_string($from)) {
2282 7
      $indexToMove = array_search($from, array_keys($array), true);
2283
      $itemToMove = $array[$from];
2284
      array_splice($array, $indexToMove, 1);
2285 7
      $i = 0;
2286
      $output = array();
2287 7
      foreach($array as $key => $item) {
2288 7
        if ($i == $to) {
2289
          $output[$from] = $itemToMove;
2290 7
        }
2291 5
        $output[$key] = $item;
2292
        $i++;
2293
      }
2294
    } else {
2295 7
      $output = array();
2296
    }
2297
2298
    return static::create($output);
2299
  }
2300
2301
  /**
2302
   * Return the array in the reverse order.
2303
   *
2304
   * @return self (Mutable) Return this Arrayy object.
2305
   */
2306 17
  public function reverse()
2307
  {
2308 17
    $this->array = array_reverse($this->array);
2309
2310 17
    return $this;
2311
  }
2312
2313
  /**
2314
   * Search for the first index of the current array via $value.
2315
   *
2316
   * @param mixed $value
2317
   *
2318
   * @return mixed
2319
   */
2320
  public function searchIndex($value)
2321
  {
2322
    return array_search($value, $this->array, true);
2323 10
  }
2324
2325
  /**
2326 10
   * Search for the value of the current array via $index.
2327 5
   *
2328
   * @param mixed $index
2329
   *
2330 10
   * @return Arrayy (Immutable) will return a empty Arrayy if the value wasn't found
2331
   */
2332
  public function searchValue($index = null)
2333
  {
2334
    // init
2335
    $return = array();
2336
2337
    if (
2338 4
        $index !== null
2339
        &&
2340 4
        isset($this->array[$index])
2341
    ) {
2342
      $return = array($this->array[$index]);
2343
    }
2344
2345
    return static::create($return);
2346
  }
2347
2348 1
  /**
2349
   * Set a value for the current array (optional using dot-notation).
2350 1
   *
2351
   * @param string $key   The key to set
2352 1
   * @param mixed  $value Its value
2353
   *
2354 1
   * @return Arrayy (Immutable)
2355
   */
2356
  public function set($key, $value)
2357
  {
2358
    $this->internalSet($key, $value);
2359
2360
    return static::create($this->array);
2361
  }
2362 110
2363
  /**
2364 110
   * Get a value from a array and set it if it was not.
2365
   *
2366
   * WARNING: this method only set the value, if the $key is not already set
2367
   *
2368
   * @param string $key      The key
2369
   * @param mixed  $fallback The default value to set if it isn't
2370
   *
2371
   * @return mixed (Mutable)
2372
   */
2373
  public function setAndGet($key, $fallback = null)
2374
  {
2375
    // If the key doesn't exist, set it
2376 4
    if (!$this->has($key)) {
2377
      $this->array = $this->set($key, $fallback)->getArray();
2378 4
    }
2379
2380 4
    return $this->get($key);
2381
  }
2382
2383
  /**
2384
   * Shifts a specified value off the beginning of array.
2385
   *
2386
   * @return mixed A shifted element from the current array. (Mutable)
2387
   */
2388
  public function shift()
2389
  {
2390
    return array_shift($this->array);
2391
  }
2392 19
2393
  /**
2394 19
   * Shuffle the current array.
2395
   *
2396 19
   * @return Arrayy (Immutable)
2397
   */
2398
  public function shuffle()
2399
  {
2400
    $array = $this->array;
2401
2402
    shuffle($array);
2403
2404
    return static::create($array);
2405
  }
2406
2407
  /**
2408
   * Get the size of an array.
2409
   *
2410 18
   * @return int
2411
   */
2412 18
  public function size()
2413
  {
2414 18
    return count($this->array);
2415
  }
2416
2417
  /**
2418
   * Extract a slice of the array.
2419
   *
2420
   * @param int      $offset       Slice begin index
2421
   * @param int|null $length       Length of the slice
2422
   * @param bool     $preserveKeys Whether array keys are preserved or no
2423
   *
2424
   * @return static A slice of the original array with length $length
2425 1
   */
2426
  public function slice($offset, $length = null, $preserveKeys = false)
2427 1
  {
2428
    $result = array_slice($this->array, $offset, $length, $preserveKeys);
2429
2430
    return static::create($result);
2431
  }
2432
2433
  /**
2434
   * Sort the current array and optional you can keep the keys.
2435
   *
2436
   * @param integer $direction use SORT_ASC or SORT_DESC
2437
   * @param integer $strategy
2438 1
   * @param bool    $keepKeys
2439
   *
2440 1
   * @return self (Mutable) Return this Arrayy object.
2441
   */
2442
  public function sort($direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
2443
  {
2444
    $this->sorting($this->array, $direction, $strategy, $keepKeys);
2445
2446
    return $this;
2447
  }
2448
2449
  /**
2450
   * Sort the current array by key.
2451
   *
2452
   * @link http://php.net/manual/en/function.ksort.php
2453
   * @link http://php.net/manual/en/function.krsort.php
2454
   *
2455 1
   * @param int|string $direction use SORT_ASC or SORT_DESC
2456
   * @param int        $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
2457 1
   *
2458 1
   * @return self (Mutable) Return this Arrayy object.
2459
   */
2460
  public function sortKeys($direction = SORT_ASC, $strategy = SORT_REGULAR)
2461 1
  {
2462 1
    $this->sorterKeys($this->array, $direction, $strategy);
2463
2464 1
    return $this;
2465 1
  }
2466
2467 1
  /**
2468 1
   * Sort the current array by value.
2469
   *
2470
   * @param int $direction use SORT_ASC or SORT_DESC
2471 1
   * @param int $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
2472
   *
2473 1
   * @return Arrayy (Immutable)
2474
   */
2475
  public function sortValueKeepIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
2476
  {
2477 1
    return $this->sort($direction, $strategy, true);
2478
  }
2479 1
2480
  /**
2481
   * Sort the current array by value.
2482
   *
2483
   * @param int $direction use SORT_ASC or SORT_DESC
2484
   * @param int $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
2485
   *
2486
   * @return Arrayy (Immutable)
2487
   */
2488
  public function sortValueNewIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
2489 18
  {
2490
    return $this->sort($direction, $strategy, false);
2491 18
  }
2492
2493
  /**
2494 18
   * Sort a array by value, by a closure or by a property.
2495 18
   *
2496 6
   * - If the sorter is null, the array is sorted naturally.
2497 6
   * - Associative (string) keys will be maintained, but numeric keys will be re-indexed.
2498 13
   *
2499 13
   * @param null       $sorter
2500
   * @param string|int $direction
2501 13
   * @param int        $strategy
2502
   *
2503 18
   * @return Arrayy (Immutable)
2504
   */
2505
  public function sorter($sorter = null, $direction = SORT_ASC, $strategy = SORT_REGULAR)
2506
  {
2507
    $array = (array)$this->array;
2508
    $direction = $this->getDirection($direction);
2509
2510
    // Transform all values into their results.
2511 19
    if ($sorter) {
2512
      $arrayy = self::create($array);
2513 19
2514
      $that = $this;
2515 19
      $results = $arrayy->each(
2516 19
          function ($value) use ($sorter, $that) {
2517
            return is_callable($sorter) ? $sorter($value) : $that->get($sorter, null, $value);
2518
          }
2519
      );
2520 19
2521 19
      $results = $results->getArray();
2522 9
    } else {
2523 5
      $results = $array;
2524
    }
2525 4
2526
    // Sort by the results and replace by original values
2527 9
    array_multisort($results, $direction, $strategy, $array);
2528 10
2529 10
    return static::create($array);
2530
  }
2531 10
2532 4
  /**
2533
   * sorting keys
2534 6
   *
2535
   * @param array $elements
2536
   * @param int   $direction
2537 19
   * @param int   $strategy
2538
   */
2539
  protected function sorterKeys(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR)
2540
  {
2541
    $direction = $this->getDirection($direction);
2542
2543
    switch ($direction) {
2544
      case 'desc':
2545
      case SORT_DESC:
2546
        krsort($elements, $strategy);
2547 1
        break;
2548
      case 'asc':
2549 1
      case SORT_ASC:
2550
      default:
2551 1
        ksort($elements, $strategy);
2552 1
    }
2553
  }
2554 1
2555 1
  /**
2556 1
   * @param array      &$elements
2557
   * @param int|string $direction
2558
   * @param int        $strategy
2559 1
   * @param bool       $keepKeys
2560
   */
2561
  protected function sorting(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
2562
  {
2563
    $direction = $this->getDirection($direction);
2564
2565
    if (!$strategy) {
2566
      $strategy = SORT_REGULAR;
2567 1
    }
2568
2569 1
    switch ($direction) {
2570
      case 'desc':
2571 1
      case SORT_DESC:
2572 1
        if ($keepKeys) {
2573
          arsort($elements, $strategy);
2574
        } else {
2575 1
          rsort($elements, $strategy);
2576 1
        }
2577
        break;
2578
      case 'asc':
2579
      case SORT_ASC:
2580
      default:
2581
        if ($keepKeys) {
2582
          asort($elements, $strategy);
2583
        } else {
2584
          sort($elements, $strategy);
2585
        }
2586
    }
2587
  }
2588 1
2589
  /**
2590 1
   * Split an array in the given amount of pieces.
2591
   *
2592 1
   * @param int  $numberOfPieces
2593
   * @param bool $keepKeys
2594 1
   *
2595
   * @return Arrayy (Immutable)
2596
   */
2597
  public function split($numberOfPieces = 2, $keepKeys = false)
2598
  {
2599
    $arrayCount = $this->count();
2600
2601
    if ($arrayCount === 0) {
2602 155
      $result = array();
2603
    } else {
2604 155
      $numberOfPieces = (int)$numberOfPieces;
2605
      $splitSize = (int)ceil($arrayCount / $numberOfPieces);
2606
      $result = array_chunk($this->array, $splitSize, $keepKeys);
2607
    }
2608
2609
    return static::create($result);
2610
  }
2611
2612
  /**
2613
   * Stripe all empty items.
2614 5
   *
2615
   * @return Arrayy (Immutable)
2616 5
   */
2617
  public function stripEmpty()
2618
  {
2619
    return $this->filter(
2620
        function ($item) {
2621
          if ($item === null) {
2622
            return false;
2623
          }
2624
2625
          return (bool)trim((string)$item);
2626 19
        }
2627
    );
2628 19
  }
2629
2630
  /**
2631
   * Swap two values between positions by key.
2632
   *
2633
   * @param string|int $swapA an key in the array
2634
   * @param string|int $swapB an key in the array
2635
   *
2636 8
   * @return Arrayy (Immutable)
2637
   */
2638 8
  public function swap($swapA, $swapB)
2639 8
  {
2640 8
    $array = $this->array;
2641 7
2642 7
    list($array[$swapA], $array[$swapB]) = array($array[$swapB], $array[$swapA]);
2643
2644
    return static::create($array);
2645 7
  }
2646 8
2647 8
  /**
2648
   * alias: for "Arrayy->getArray()"
2649
   *
2650 8
   * @see Arrayy::getArray()
2651
   */
2652
  public function toArray()
2653 8
  {
2654
    return $this->getArray();
2655
  }
2656 8
2657
  /**
2658
   * Convert the current array to JSON.
2659
   *
2660
   * @param null $options e.g. JSON_PRETTY_PRINT
2661
   *
2662
   * @return string
2663
   */
2664 4
  public function toJson($options = null)
2665
  {
2666 4
    return UTF8::json_encode($this->array, $options);
2667 4
  }
2668 4
2669
  /**
2670
   * Implodes array to a string with specified separator.
2671 4
   *
2672
   * @param string $separator The element's separator
2673
   *
2674
   * @return string The string representation of array, separated by ","
2675
   */
2676
  public function toString($separator = ',')
2677
  {
2678
    return $this->implode($separator);
2679 2
  }
2680
2681 2
  /**
2682
   * Return a duplicate free copy of the current array.
2683
   *
2684
   * @return Arrayy (Mutable)
2685
   */
2686
  public function unique()
2687
  {
2688
    $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...
2689
        $this->array,
2690
        function ($resultArray, $value) {
2691
          if (!in_array($value, $resultArray, true)) {
2692 9
            $resultArray[] = $value;
2693
          }
2694 9
2695 4
          return $resultArray;
2696
        },
2697 5
        array()
2698
    );
2699
2700 9
    if ($this->array === null) {
2701
      $this->array = array();
2702
    } else {
2703
      $this->array = (array)$this->array;
2704
    }
2705
2706
    return $this;
2707
  }
2708
2709
  /**
2710
   * Prepends one or more values to the beginning of array at once.
2711
   *
2712
   * @return self (Mutable) Return this Arrayy object, with prepended elements to the beginning of array.
2713
   */
2714 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...
2715
  {
2716
    if (func_num_args()) {
2717
      $args = array_merge(array(&$this->array), func_get_args());
2718
      call_user_func_array('array_unshift', $args);
2719
    }
2720
2721
    return $this;
2722
  }
2723
2724
  /**
2725
   * Get all values from a array.
2726
   *
2727
   * @return Arrayy (Immutable)
2728
   */
2729
  public function values()
2730
  {
2731
    return static::create(array_values((array)$this->array));
2732
  }
2733
2734
  /**
2735
   * Apply the given function to every element in the array, discarding the results.
2736
   *
2737
   * @param callable $callable
2738
   * @param bool     $recursive Whether array will be walked recursively or no
2739
   *
2740
   * @return self (Mutable) Return this Arrayy object, with modified elements
2741
   */
2742
  public function walk($callable, $recursive = false)
2743
  {
2744
    if (true === $recursive) {
2745
      array_walk_recursive($this->array, $callable);
2746
    } else {
2747
      array_walk($this->array, $callable);
2748
    }
2749
2750
    return $this;
2751
  }
2752
2753
}
2754