Completed
Push — master ( 937a79...371ca1 )
by Lars
02:05
created

Arrayy::uniqueKeepIndex()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 4
cts 4
cp 1
crap 1
rs 10
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 748
  public function __construct($array = array())
34
  {
35 748
    $array = $this->fallbackForArray($array);
36
37 746
    $this->array = $array;
38 746
  }
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 1
  public function __get($key)
48
  {
49 1
    $return = $this->get($key);
50
51 1
    if (is_array($return)) {
52
      return self::create($return);
53
    }
54
55 1
    return $return;
56
  }
57
58
  /**
59
   * Call object as function.
60
   *
61
   * @param mixed $key
62
   *
63
   * @return mixed
64
   */
65
  public function __invoke($key = null)
66
  {
67
    if ($key !== null) {
68
      if (isset($this->array[$key])) {
69
        return $this->array[$key];
70
      }
71
72
      return false;
73
    }
74
75
    return (array)$this->array;
76
  }
77
78
  /**
79
   * Whether or not an element exists by key.
80
   *
81
   * @param mixed $key
82
   *
83
   * @return bool True is the key/index exists, otherwise false.
84
   */
85
  public function __isset($key)
86
  {
87
    return $this->offsetExists($key);
88
  }
89
90
  /**
91
   * Assigns a value to the specified element.
92
   *
93
   * @param mixed $key
94
   * @param mixed $value
95
   */
96 2
  public function __set($key, $value)
97
  {
98 2
    $this->internalSet($key, $value);
99 2
  }
100
101
  /**
102
   * magic to string
103
   *
104
   * @return string
105
   */
106 16
  public function __toString()
107
  {
108 16
    return $this->toString();
109
  }
110
111
  /**
112
   * Unset element by key.
113
   *
114
   * @param mixed $key
115
   */
116
  public function __unset($key)
117
  {
118
    unset($this->array[$key]);
119
  }
120
121
  /**
122
   * alias: for "Arrayy->append()"
123
   *
124
   * @see Arrayy::append()
125
   *
126
   * @param mixed $value
127
   *
128
   * @return static (Mutable) Return this Arrayy object, with the appended values.
129
   */
130 1
  public function add($value)
131
  {
132 1
    return $this->append($value);
133
  }
134
135
  /**
136
   * Append a value to the current array.
137
   *
138
   * @param mixed $value
139
   *
140
   * @return static (Mutable) Return this Arrayy object, with the appended values.
141
   */
142 9
  public function append($value)
143
  {
144 9
    $this->array[] = $value;
145
146 9
    return $this;
147
  }
148
149
  /**
150
   * Count the values from the current array.
151
   *
152
   * alias: for "Arrayy->size()"
153
   *
154
   * @see Arrayy::size()
155
   *
156
   * @return int
157
   */
158 93
  public function count()
159
  {
160 93
    return $this->size();
161
  }
162
163
  /**
164
   * Returns a new ArrayyIterator, thus implementing the IteratorAggregate interface.
165
   *
166
   * @return ArrayyIterator An iterator for the values in the array.
167
   */
168 19
  public function getIterator()
169
  {
170 19
    return new ArrayyIterator($this->array);
171
  }
172
173
  /**
174
   * Whether or not an offset exists.
175
   *
176
   * @param int|float|string $offset
177
   *
178
   * @return bool
179
   */
180 38
  public function offsetExists($offset)
181
  {
182 38
    if ($this->isEmpty()) {
183 4
      return false;
184
    }
185
186
    // php cast "bool"-index into "int"-index
187 34
    if ((bool)$offset === $offset) {
188 1
      $offset = (int)$offset;
189 1
    }
190
191 34
    $tmpReturn = array_key_exists($offset, $this->array);
192
193
    if (
194
        $tmpReturn === true
195 34
        ||
196
        (
197
            $tmpReturn === false
198 11
            &&
199 11
            strpos((string)$offset, $this->pathSeparator) === false
200 11
        )
201 34
    ) {
202 32
      return $tmpReturn;
203
    }
204
205 2
    $offsetExists = false;
206
207 2
    if (strpos((string)$offset, $this->pathSeparator) !== false) {
208
209 2
      $offsetExists = false;
210 2
      $explodedPath = explode($this->pathSeparator, (string)$offset);
211 2
      $lastOffset = array_pop($explodedPath);
212 2
      $containerPath = implode($this->pathSeparator, $explodedPath);
213
214 2
      $this->callAtPath(
215 2
          $containerPath,
216
          function ($container) use ($lastOffset, &$offsetExists) {
217 2
            $offsetExists = array_key_exists($lastOffset, $container);
218 2
          }
219 2
      );
220 2
    }
221
222 2
    return $offsetExists;
223
  }
224
225
  /**
226
   * Returns the value at specified offset.
227
   *
228
   * @param mixed $offset
229
   *
230
   * @return mixed return null if the offset did not exists
231
   */
232 24
  public function offsetGet($offset)
233
  {
234 24
    return $this->offsetExists($offset) ? $this->get($offset) : null;
235
  }
236
237
  /**
238
   * Assigns a value to the specified offset.
239
   *
240
   * @param mixed $offset
241
   * @param mixed $value
242
   */
243 15
  public function offsetSet($offset, $value)
244
  {
245 15
    if ($offset === null) {
246 4
      $this->array[] = $value;
247 4
    } else {
248 11
      $this->internalSet($offset, $value);
249
    }
250 15
  }
251
252
  /**
253
   * Unset an offset.
254
   *
255
   * @param mixed $offset
256
   */
257 6
  public function offsetUnset($offset)
258
  {
259 6
    if ($this->isEmpty()) {
260 1
      return;
261
    }
262
263 5
    if (array_key_exists($offset, $this->array)) {
264 3
      unset($this->array[$offset]);
265
266 3
      return;
267
    }
268
269 2
    if (strpos((string)$offset, $this->pathSeparator) !== false) {
270
271 1
      $path = explode($this->pathSeparator, (string)$offset);
272 1
      $pathToUnset = array_pop($path);
273
274 1
      $this->callAtPath(
275 1
          implode($this->pathSeparator, $path),
276
          function (&$offset) use (&$pathToUnset) {
277 1
            unset($offset[$pathToUnset]);
278 1
          }
279 1
      );
280
281 1
    }
282 2
  }
283
284
  /**
285
   * Serialize the current array.
286
   *
287
   * @return string
288
   */
289 2
  public function serialize()
290
  {
291 2
    return serialize($this->array);
292
  }
293
294
  /**
295
   * Unserialize an string and return this object.
296
   *
297
   * @param string $string
298
   *
299
   * @return static (Mutable)
300
   */
301 2
  public function unserialize($string)
302
  {
303 2
    $this->array = unserialize($string);
304
305 2
    return $this;
306
  }
307
308
  /**
309
   * Iterate over the current array and execute a callback for each loop.
310
   *
311
   * @param \Closure $closure
312
   *
313
   * @return static (Immutable)
314
   */
315 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...
316
  {
317 2
    $array = $this->array;
318
319 2
    foreach ($array as $key => $value) {
320 2
      $closure($value, $key);
321 2
    }
322
323 2
    return static::create($array);
324
  }
325
326
  /**
327
   * Returns the average value of the current array.
328
   *
329
   * @param int $decimals The number of decimals to return
330
   *
331
   * @return int|double The average value
332
   */
333 10
  public function average($decimals = 0)
334
  {
335 10
    $count = $this->count();
336
337 10
    if (!$count) {
338 2
      return 0;
339
    }
340
341 8
    if (!is_int($decimals)) {
342 3
      $decimals = 0;
343 3
    }
344
345 8
    return round(array_sum($this->array) / $count, $decimals);
346
  }
347
348
  /**
349
   * @param mixed      $path
350
   * @param callable   $callable
351
   * @param null|array $currentOffset
352
   */
353 2
  protected function callAtPath($path, $callable, &$currentOffset = null)
354
  {
355 2
    if ($currentOffset === null) {
356 2
      $currentOffset = &$this->array;
357 2
    }
358
359 2
    $explodedPath = explode($this->pathSeparator, $path);
360 2
    $nextPath = array_shift($explodedPath);
361
362 2
    if (!isset($currentOffset[$nextPath])) {
363
      return;
364
    }
365
366 2
    if (!empty($explodedPath)) {
367
      $this->callAtPath(
368
          implode($this->pathSeparator, $explodedPath),
369
          $callable,
370
          $currentOffset[$nextPath]
371
      );
372
    } else {
373 2
      $callable($currentOffset[$nextPath]);
374
    }
375 2
  }
376
377
  /**
378
   * Change the path separator of the array wrapper.
379
   *
380
   * By default, the separator is: .
381
   *
382
   * @param string $separator Separator to set.
383
   *
384
   * @return static Current instance.
385
   */
386
  public function changeSeparator($separator)
387
  {
388
    $this->pathSeparator = $separator;
389
390
    return $this;
391
  }
392
393
  /**
394
   * Create a chunked version of the current array.
395
   *
396
   * @param int  $size         Size of each chunk
397
   * @param bool $preserveKeys Whether array keys are preserved or no
398
   *
399
   * @return static (Immutable) A new array of chunks from the original array.
400
   */
401 4
  public function chunk($size, $preserveKeys = false)
402
  {
403 4
    $result = array_chunk($this->array, $size, $preserveKeys);
404
405 4
    return static::create($result);
406
  }
407
408
  /**
409
   * Clean all falsy values from the current array.
410
   *
411
   * @return static (Immutable)
412
   */
413 8
  public function clean()
414
  {
415 8
    return $this->filter(
416
        function ($value) {
417 7
          return (bool)$value;
418
        }
419 8
    );
420
  }
421
422
  /**
423
   * WARNING!!! -> Clear the current array.
424
   *
425
   * @return static (Mutable) Return this Arrayy object, with an empty array.
426
   */
427 4
  public function clear()
428
  {
429 4
    $this->array = array();
430
431 4
    return $this;
432
  }
433
434
  /**
435
   * Check if an item is in the current array.
436
   *
437
   * @param string|int|float $value
438
   *
439
   * @return bool
440
   */
441 13
  public function contains($value)
442
  {
443 13
    return in_array($value, $this->array, true);
444
  }
445
446
  /**
447
   * Check if an (case-insensitive) string is in the current array.
448
   *
449
   * @param string $value
450
   *
451
   * @return bool
452
   */
453 13
  public function containsCaseInsensitive($value)
454
  {
455 13
    return in_array(
456 13
        UTF8::strtolower($value),
457 13
        array_map(
458
            array(
459 13
                new UTF8(),
460 13
                'strtolower',
461 13
            ),
462 13
            $this->array
463 13
        ),
464
        true
465 13
    );
466
  }
467
468
  /**
469
   * Check if the given key/index exists in the array.
470
   *
471
   * @param string|int|float $key key/index to search for
472
   *
473
   * @return bool Returns true if the given key/index exists in the array, false otherwise
474
   */
475 4
  public function containsKey($key)
476
  {
477 4
    return $this->offsetExists($key);
478
  }
479
480
  /**
481
   * Check if all given needles are present in the array as key/index.
482
   *
483
   * @param array $needles
484
   *
485
   * @return bool Returns true if the given keys/indexes exists in the array, false otherwise
486
   */
487 1
  public function containsKeys(array $needles)
488
  {
489 1
    return count(array_intersect($needles, $this->keys()->getArray())) === count($needles);
490
  }
491
492
  /**
493
   * alias: for "Arrayy->contains()"
494
   *
495
   * @see Arrayy::contains()
496
   *
497
   * @param string|int|float $value
498
   *
499
   * @return bool
500
   */
501
  public function containsValue($value)
502
  {
503
    return $this->contains($value);
504
  }
505
506
  /**
507
   * Check if all given needles are present in the array.
508
   *
509
   * @param array $needles
510
   *
511
   * @return bool Returns true if the given values exists in the array, false otherwise
512
   */
513 1
  public function containsValues(array $needles)
514
  {
515 1
    return count(array_intersect($needles, $this->array)) === count($needles);
516
  }
517
518
  /**
519
   * Creates an Arrayy object.
520
   *
521
   * @param array $array
522
   *
523
   * @return static (Immutable) Returns an new instance of the Arrayy object.
524
   */
525 468
  public static function create($array = array())
526
  {
527 468
    return new static($array);
528
  }
529
530
  /**
531
   * WARNING: Creates an Arrayy object by reference.
532
   *
533
   * @param array $array
534
   *
535
   * @return static (Mutable) Return this Arrayy object.
536
   */
537
  public function createByReference(&$array = array())
538
  {
539
    $array = $this->fallbackForArray($array);
540
541
    $this->array = &$array;
542
543
    return $this;
544
  }
545
546
  /**
547
   * Create an new Arrayy object via JSON.
548
   *
549
   * @param string $json
550
   *
551
   * @return static (Immutable) Returns an new instance of the Arrayy object.
552
   */
553 5
  public static function createFromJson($json)
554
  {
555 5
    $array = UTF8::json_decode($json, true);
556
557 5
    return static::create($array);
558
  }
559
560
  /**
561
   * Create an new instance filled with values from an object that have implemented ArrayAccess.
562
   *
563
   * @param \ArrayAccess $object Object that implements ArrayAccess
564
   *
565
   * @return static (Immutable) Returns an new instance of the Arrayy object.
566
   */
567 4
  public static function createFromObject(\ArrayAccess $object)
568
  {
569 4
    $array = new static();
570 4
    foreach ($object as $key => $value) {
571
      /** @noinspection OffsetOperationsInspection */
572 3
      $array[$key] = $value;
573 4
    }
574
575 4
    return $array;
576
  }
577
578
  /**
579
   * Create an new Arrayy object via string.
580
   *
581
   * @param string      $str       The input string.
582
   * @param string|null $delimiter The boundary string.
583
   * @param string|null $regEx     Use the $delimiter or the $regEx, so if $pattern is null, $delimiter will be used.
584
   *
585
   * @return static (Immutable) Returns an new instance of the Arrayy object.
586
   */
587 8
  public static function createFromString($str, $delimiter, $regEx = null)
588
  {
589 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...
590 1
      preg_match_all($regEx, $str, $array);
591
592 1
      if (!empty($array)) {
593 1
        $array = $array[0];
594 1
      }
595
596 1
    } else {
597 7
      $array = explode($delimiter, $str);
598
    }
599
600
    // trim all string in the array
601 8
    array_walk(
602 8
        $array,
603
        function (&$val) {
604
          /** @noinspection ReferenceMismatchInspection */
605 8
          if (is_string($val)) {
606 8
            $val = trim($val);
607 8
          }
608 8
        }
609 8
    );
610
611 8
    return static::create($array);
612
  }
613
614
  /**
615
   * Create an new instance containing a range of elements.
616
   *
617
   * @param mixed $low  First value of the sequence
618
   * @param mixed $high The sequence is ended upon reaching the end value
619
   * @param int   $step Used as the increment between elements in the sequence
620
   *
621
   * @return static (Immutable) Returns an new instance of the Arrayy object.
622
   */
623 1
  public static function createWithRange($low, $high, $step = 1)
624
  {
625 1
    return static::create(range($low, $high, $step));
626
  }
627
628
  /**
629
   * Custom sort by index via "uksort".
630
   *
631
   * @link http://php.net/manual/en/function.uksort.php
632
   *
633
   * @param callable $function
634
   *
635
   * @return static (Mutable) Return this Arrayy object.
636
   */
637 5
  public function customSortKeys($function)
638
  {
639 5
    uksort($this->array, $function);
640
641 5
    return $this;
642
  }
643
644
  /**
645
   * Custom sort by value via "usort".
646
   *
647
   * @link http://php.net/manual/en/function.usort.php
648
   *
649
   * @param callable $function
650
   *
651
   * @return static (Mutable) Return this Arrayy object.
652
   */
653 4
  public function customSortValues($function)
654
  {
655 4
    usort($this->array, $function);
656
657 4
    return $this;
658
  }
659
660
  /**
661
   * Return values that are only in the current array.
662
   *
663
   * @param array $array
664
   *
665
   * @return static (Immutable)
666
   */
667 12
  public function diff(array $array = array())
668
  {
669 12
    $result = array_diff($this->array, $array);
670
671 12
    return static::create($result);
672
  }
673
674
  /**
675
   * Return values that are only in the current multi-dimensional array.
676
   *
677
   * @param array      $array
678
   * @param null|array $helperVariableForRecursion (only for internal usage)
679
   *
680
   * @return static (Immutable)
681
   */
682 1
  public function diffRecursive(array $array = array(), $helperVariableForRecursion = null)
683
  {
684 1
    $result = array();
685
686
    if (
687
        $helperVariableForRecursion !== null
688 1
        &&
689 1
        is_array($helperVariableForRecursion)
690 1
    ) {
691 1
      $arrayForTheLoop = $helperVariableForRecursion;
692 1
    } else {
693 1
      $arrayForTheLoop = $this->array;
694
    }
695
696 1
    foreach ($arrayForTheLoop as $key => $value) {
697 1
      if (array_key_exists($key, $array)) {
698 1
        if (is_array($value)) {
699 1
          $recursiveDiff = $this->diffRecursive($array[$key], $value);
700 1
          if (!empty($recursiveDiff)) {
701 1
            $result[$key] = $recursiveDiff;
702 1
          }
703 1
        } else {
704 1
          if ($value != $array[$key]) {
705 1
            $result[$key] = $value;
706 1
          }
707
        }
708 1
      } else {
709 1
        $result[$key] = $value;
710
      }
711 1
    }
712
713 1
    return static::create($result);
714
  }
715
716
  /**
717
   * Return values that are only in the new $array.
718
   *
719
   * @param array $array
720
   *
721
   * @return static (Immutable)
722
   */
723 8
  public function diffReverse(array $array = array())
724
  {
725 8
    $result = array_diff($array, $this->array);
726
727 8
    return static::create($result);
728
  }
729
730
  /**
731
   * Divide an array into two arrays. One with keys and the other with values.
732
   *
733
   * @return static (Immutable)
734
   */
735 1
  public function divide()
736
  {
737 1
    return static::create(
738
        array(
739 1
            $this->keys(),
740 1
            $this->values(),
741
        )
742 1
    );
743
  }
744
745
  /**
746
   * Iterate over the current array and modify the array's value.
747
   *
748
   * @param \Closure $closure
749
   *
750
   * @return static (Immutable)
751
   */
752 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...
753
  {
754 4
    $array = $this->array;
755
756 4
    foreach ($array as $key => $value) {
757 4
      $array[$key] = $closure($value, $key);
758 4
    }
759
760 4
    return static::create($array);
761
  }
762
763
  /**
764
   * Check if a value is in the current array using a closure.
765
   *
766
   * @param \Closure $closure
767
   *
768
   * @return bool Returns true if the given value is found, false otherwise
769
   */
770 4
  public function exists(\Closure $closure)
771
  {
772 4
    $isExists = false;
773 4
    foreach ($this->array as $key => $value) {
774 3
      if ($closure($value, $key)) {
775 1
        $isExists = true;
776 1
        break;
777
      }
778 4
    }
779
780 4
    return $isExists;
781
  }
782
783
  /**
784
   * create a fallback for array
785
   *
786
   * 1. use the current array, if it's a array
787
   * 2. call "getArray()" on object, if there is a "Arrayy"-object
788
   * 3. fallback to empty array, if there is nothing
789
   * 4. call "createFromObject()" on object, if there is a "\ArrayAccess"-object
790
   * 5. call "__toArray()" on object, if the method exists
791
   * 6. cast a string or object with "__toString()" into an array
792
   * 7. throw a "InvalidArgumentException"-Exception
793
   *
794
   * @param $array
795
   *
796
   * @return array
797
   *
798
   * @throws \InvalidArgumentException
799
   */
800 748
  protected function fallbackForArray(&$array)
801
  {
802 748
    if (is_array($array)) {
803 745
      return $array;
804
    }
805
806 10
    if ($array instanceof self) {
807 1
      return $array->getArray();
808
    }
809
810 9
    if (!$array) {
811 6
      return array();
812
    }
813
814 8
    if ($array instanceof \ArrayAccess) {
815
      /** @noinspection ReferenceMismatchInspection */
816
      return self::createFromObject($array)->getArray();
817
    }
818
819 8
    if (is_object($array) && method_exists($array, '__toArray')) {
820
      return (array)$array->__toArray();
821
    }
822
823
    /** @noinspection ReferenceMismatchInspection */
824
    if (
825 8
        is_string($array)
826
        ||
827 2
        (is_object($array) && method_exists($array, '__toString'))
828 8
    ) {
829 6
      return array((string)$array);
830
    }
831
832 2
    throw new \InvalidArgumentException(
833
        'Passed value should be a array'
834 2
    );
835
  }
836
837
  /**
838
   * Find all items in an array that pass the truth test.
839
   *
840
   * @param \Closure|null $closure
841
   *
842
   * @return static (Immutable)
843
   */
844 9
  public function filter($closure = null)
845
  {
846 9
    if (!$closure) {
847 1
      return $this->clean();
848
    }
849
850 9
    $array = array_filter($this->array, $closure);
851
852 9
    return static::create($array);
853
  }
854
855
  /**
856
   * Filters an array of objects (or a numeric array of associative arrays) based on the value of a particular property
857
   * within that.
858
   *
859
   * @param        $property
860
   * @param        $value
861
   * @param string $comparisonOp
862
   *                            'eq' (equals),<br />
863
   *                            'gt' (greater),<br />
864
   *                            'gte' || 'ge' (greater or equals),<br />
865
   *                            'lt' (less),<br />
866
   *                            'lte' || 'le' (less or equals),<br />
867
   *                            'ne' (not equals),<br />
868
   *                            'contains',<br />
869
   *                            'notContains',<br />
870
   *                            'newer' (via strtotime),<br />
871
   *                            'older' (via strtotime),<br />
872
   *
873
   * @return static (Immutable)
874
   */
875 1
  public function filterBy($property, $value, $comparisonOp = null)
876
  {
877 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...
878 1
      $comparisonOp = is_array($value) ? 'contains' : 'eq';
879 1
    }
880
881
    $ops = array(
882
        'eq'          => function ($item, $prop, $value) {
883 1
          return $item[$prop] === $value;
884 1
        },
885
        'gt'          => function ($item, $prop, $value) {
886
          return $item[$prop] > $value;
887 1
        },
888
        'ge'          => function ($item, $prop, $value) {
889
          return $item[$prop] >= $value;
890 1
        },
891
        'gte'         => function ($item, $prop, $value) {
892
          return $item[$prop] >= $value;
893 1
        },
894
        'lt'          => function ($item, $prop, $value) {
895 1
          return $item[$prop] < $value;
896 1
        },
897
        'le'          => function ($item, $prop, $value) {
898
          return $item[$prop] <= $value;
899 1
        },
900
        'lte'         => function ($item, $prop, $value) {
901
          return $item[$prop] <= $value;
902 1
        },
903
        'ne'          => function ($item, $prop, $value) {
904
          return $item[$prop] !== $value;
905 1
        },
906
        'contains'    => function ($item, $prop, $value) {
907 1
          return in_array($item[$prop], (array)$value, true);
908 1
        },
909
        'notContains' => function ($item, $prop, $value) {
910
          return !in_array($item[$prop], (array)$value, true);
911 1
        },
912
        'newer'       => function ($item, $prop, $value) {
913
          return strtotime($item[$prop]) > strtotime($value);
914 1
        },
915
        'older'       => function ($item, $prop, $value) {
916
          return strtotime($item[$prop]) < strtotime($value);
917 1
        },
918 1
    );
919
920 1
    $result = array_values(
921 1
        array_filter(
922 1
            (array)$this->array,
923
            function ($item) use (
924 1
                $property,
925 1
                $value,
926 1
                $ops,
927 1
                $comparisonOp
928
            ) {
929 1
              $item = (array)$item;
930 1
              $itemArrayy = new Arrayy($item);
931 1
              $item[$property] = $itemArrayy->get($property, array());
932
933 1
              return $ops[$comparisonOp]($item, $property, $value);
934
            }
935 1
        )
936 1
    );
937
938 1
    return static::create($result);
939
  }
940
941
  /**
942
   * Find the first item in an array that passes the truth test,
943
   *  otherwise return false
944
   *
945
   * @param \Closure $closure
946
   *
947
   * @return mixed|false false if we did not find the value
948
   */
949 8
  public function find(\Closure $closure)
950
  {
951 8
    foreach ($this->array as $key => $value) {
952 6
      if ($closure($value, $key)) {
953 5
        return $value;
954
      }
955 5
    }
956
957 3
    return false;
958
  }
959
960
  /**
961
   * find by ...
962
   *
963
   * @param        $property
964
   * @param        $value
965
   * @param string $comparisonOp
966
   *
967
   * @return static (Immutable)
968
   */
969
  public function findBy($property, $value, $comparisonOp = 'eq')
970
  {
971
    return $this->filterBy($property, $value, $comparisonOp);
972
  }
973
974
  /**
975
   * Get the first value from the current array.
976
   *
977
   * @return mixed Return null if there wasn't a element.
978
   */
979 13
  public function first()
980
  {
981 13
    $tmpArray = $this->array;
982 13
    $result = array_shift($tmpArray);
983
984 13
    if ($result === null) {
985 3
      return null;
986
    }
987
988 10
    return $result;
989
  }
990
991
  /**
992
   * Get the first value(s) from the current array.
993
   *
994
   * @param int|null $number how many values you will take?
995
   *
996
   * @return static (Immutable)
997
   */
998 28
  public function firstsImmutable($number = null)
999
  {
1000 28
    if ($number === null) {
1001 7
      $arrayTmp = $this->array;
1002 7
      $array = (array)array_shift($arrayTmp);
1003 7
    } else {
1004 21
      $number = (int)$number;
1005 21
      $arrayTmp = $this->array;
1006 21
      $array = array_splice($arrayTmp, 0, $number, true);
1007
    }
1008
1009 28
    return static::create($array);
1010
  }
1011
1012
  /**
1013
   * Get the first value(s) from the current array.
1014
   *
1015
   * @param int|null $number how many values you will take?
1016
   *
1017
   * @return static (Mutable)
1018
   */
1019 26
  public function firstsMutable($number = null)
1020
  {
1021 26
    if ($number === null) {
1022 11
      $this->array = (array)array_shift($this->array);
1023 11
    } else {
1024 15
      $number = (int)$number;
1025 15
      $this->array = array_splice($this->array, 0, $number, true);
1026
    }
1027
1028 26
    return $this;
1029
  }
1030
1031
  /**
1032
   * Exchanges all keys with their associated values in an array.
1033
   *
1034
   * @return static (Immutable)
1035
   */
1036 1
  public function flip()
1037
  {
1038 1
    $result = array_flip($this->array);
1039
1040 1
    return static::create($result);
1041
  }
1042
1043
  /**
1044
   * Get a value from an array (optional using dot-notation).
1045
   *
1046
   * @param string $key      The key to look for.
1047
   * @param mixed  $fallback Value to fallback to.
1048
   * @param array  $array    The array to get from, if it's set to "null" we use the current array from the class.
1049
   *
1050
   * @return mixed
1051
   */
1052 58
  public function get($key, $fallback = null, $array = null)
1053
  {
1054
    if (
1055
        $array !== null
1056 58
        &&
1057 3
        is_array($array)
1058 58
    ) {
1059 3
      $usedArray = $array;
1060 3
    } else {
1061 56
      $usedArray = $this->array;
1062
    }
1063
1064 58
    if ($key === null) {
1065 1
      return self::create($usedArray);
1066
    }
1067
1068
    // php cast "bool"-index into "int"-index
1069 58
    if ((bool)$key === $key) {
1070 2
      $key = (int)$key;
1071 2
    }
1072
1073 58
    if (array_key_exists($key, $usedArray) === true) {
1074 48
      if (is_array($usedArray[$key])) {
1075 5
        return self::create($usedArray[$key]);
1076
      }
1077
1078 45
      return $usedArray[$key];
1079
    }
1080
1081
    // Crawl through array, get key according to object or not
1082 19
    foreach (explode($this->pathSeparator, (string)$key) as $segment) {
1083 19
      if (!isset($usedArray[$segment])) {
1084 19
        return $fallback instanceof \Closure ? $fallback() : $fallback;
1085
      }
1086
1087 4
      $usedArray = $usedArray[$segment];
1088 4
    }
1089
1090 4
    if (is_array($usedArray)) {
1091
      return self::create($usedArray);
1092
    }
1093
1094 4
    return $usedArray;
1095
  }
1096
1097
  /**
1098
   * Get the current array from the "Arrayy"-object.
1099
   *
1100
   * @return array
1101
   */
1102 473
  public function getArray()
1103
  {
1104 473
    array_map(array('self', 'internalGetArray'), $this->array);
1105
1106 473
    return $this->array;
1107
  }
1108
1109
  /**
1110
   * @param mixed $value
1111
   */
1112 389
  protected function internalGetArray(&$value)
1113
  {
1114 389
    if ($value instanceof self) {
1115
      $value &= $value->getArray();
1116
    }
1117 389
  }
1118
1119
  /**
1120
   * Returns the values from a single column of the input array, identified by
1121
   * the $columnKey, can be used to extract data-columns from multi-arrays.
1122
   *
1123
   * Info: Optionally, you may provide an $indexKey to index the values in the returned
1124
   * array by the values from the $indexKey column in the input array.
1125
   *
1126
   * @param mixed $columnKey
1127
   * @param mixed $indexKey
1128
   *
1129
   * @return static (Immutable)
1130
   */
1131 1
  public function getColumn($columnKey = null, $indexKey = null)
1132
  {
1133 1
    $result = array_column($this->array, $columnKey, $indexKey);
1134
1135 1
    return static::create($result);
1136
  }
1137
1138
  /**
1139
   * Get correct PHP constant for direction.
1140
   *
1141
   * @param int|string $direction
1142
   *
1143
   * @return int
1144
   */
1145 38
  protected function getDirection($direction)
1146
  {
1147 38
    if (is_string($direction)) {
1148 10
      $direction = strtolower($direction);
1149
1150 10
      if ($direction === 'desc') {
1151 2
        $direction = SORT_DESC;
1152 2
      } else {
1153 8
        $direction = SORT_ASC;
1154
      }
1155 10
    }
1156
1157
    if (
1158
        $direction !== SORT_DESC
1159 38
        &&
1160
        $direction !== SORT_ASC
1161 38
    ) {
1162
      $direction = SORT_ASC;
1163
    }
1164
1165 38
    return $direction;
1166
  }
1167
1168
  /**
1169
   * alias: for "Arrayy->keys()"
1170
   *
1171
   * @see Arrayy::keys()
1172
   *
1173
   * @return static (Immutable)
1174
   */
1175 1
  public function getKeys()
1176
  {
1177 1
    return $this->keys();
1178
  }
1179
1180
  /**
1181
   * alias: for "Arrayy->randomImmutable()"
1182
   *
1183
   * @see Arrayy::randomImmutable()
1184
   *
1185
   * @return static (Immutable)
1186
   */
1187 3
  public function getRandom()
1188
  {
1189 3
    return $this->randomImmutable();
1190
  }
1191
1192
  /**
1193
   * alias: for "Arrayy->randomKey()"
1194
   *
1195
   * @see Arrayy::randomKey()
1196
   *
1197
   * @return mixed get a key/index or null if there wasn't a key/index
1198
   */
1199 3
  public function getRandomKey()
1200
  {
1201 3
    return $this->randomKey();
1202
  }
1203
1204
  /**
1205
   * alias: for "Arrayy->randomKeys()"
1206
   *
1207
   * @see Arrayy::randomKeys()
1208
   *
1209
   * @param int $number
1210
   *
1211
   * @return static (Immutable)
1212
   */
1213 9
  public function getRandomKeys($number)
1214
  {
1215 9
    return $this->randomKeys($number);
1216
  }
1217
1218
  /**
1219
   * alias: for "Arrayy->randomValue()"
1220
   *
1221
   * @see Arrayy::randomValue()
1222
   *
1223
   * @return mixed get a random value or null if there wasn't a value
1224
   */
1225 3
  public function getRandomValue()
1226
  {
1227 3
    return $this->randomValue();
1228
  }
1229
1230
  /**
1231
   * alias: for "Arrayy->randomValues()"
1232
   *
1233
   * @see Arrayy::randomValues()
1234
   *
1235
   * @param int $number
1236
   *
1237
   * @return static (Immutable)
1238
   */
1239 6
  public function getRandomValues($number)
1240
  {
1241 6
    return $this->randomValues($number);
1242
  }
1243
1244
  /**
1245
   * Group values from a array according to the results of a closure.
1246
   *
1247
   * @param string $grouper a callable function name
1248
   * @param bool   $saveKeys
1249
   *
1250
   * @return static (Immutable)
1251
   */
1252 3
  public function group($grouper, $saveKeys = false)
1253
  {
1254 3
    $array = (array)$this->array;
1255 3
    $result = array();
1256
1257
    // Iterate over values, group by property/results from closure
1258 3
    foreach ($array as $key => $value) {
1259
1260 3
      $groupKey = is_callable($grouper) ? $grouper($value, $key) : $this->get($grouper, null, $value);
1261 3
      $newValue = $this->get($groupKey, null, $result);
1262
1263 3
      if ($groupKey instanceof self) {
1264
        $groupKey = $groupKey->getArray();
1265
      }
1266
1267 3
      if ($newValue instanceof self) {
1268 3
        $newValue = $newValue->getArray();
1269 3
      }
1270
1271
      // Add to results
1272 3
      if ($groupKey !== null) {
1273 2
        if ($saveKeys) {
1274 1
          $result[$groupKey] = $newValue;
1275 1
          $result[$groupKey][$key] = $value;
1276 1
        } else {
1277 1
          $result[$groupKey] = $newValue;
1278 1
          $result[$groupKey][] = $value;
1279
        }
1280 2
      }
1281
1282 3
    }
1283
1284 3
    return static::create($result);
1285
  }
1286
1287
  /**
1288
   * Check if an array has a given key.
1289
   *
1290
   * @param mixed $key
1291
   *
1292
   * @return bool
1293
   */
1294 22
  public function has($key)
1295
  {
1296
    // Generate unique string to use as marker.
1297 22
    $unFound = (string)uniqid('arrayy', true);
1298
1299 22
    return $this->get($key, $unFound) !== $unFound;
1300
  }
1301
1302
  /**
1303
   * Implodes an array.
1304
   *
1305
   * @param string $with What to implode it with
1306
   *
1307
   * @return string
1308
   */
1309 27
  public function implode($with = '')
1310
  {
1311 27
    return implode($with, $this->array);
1312
  }
1313
1314
  /**
1315
   * Given a list and an iterate-function that returns
1316
   * a key for each element in the list (or a property name),
1317
   * returns an object with an index of each item.
1318
   *
1319
   * Just like groupBy, but for when you know your keys are unique.
1320
   *
1321
   * @param mixed $key
1322
   *
1323
   * @return static (Immutable)
1324
   */
1325 3
  public function indexBy($key)
1326
  {
1327 3
    $results = array();
1328
1329 3
    foreach ($this->array as $a) {
1330 3
      if (array_key_exists($key, $a) === true) {
1331 2
        $results[$a[$key]] = $a;
1332 2
      }
1333 3
    }
1334
1335 3
    return static::create($results);
1336
  }
1337
1338
  /**
1339
   * alias: for "Arrayy->searchIndex()"
1340
   *
1341
   * @see Arrayy::searchIndex()
1342
   *
1343
   * @param mixed $value Value to search for
1344
   *
1345
   * @return mixed
1346
   */
1347 4
  public function indexOf($value)
1348
  {
1349 4
    return $this->searchIndex($value);
1350
  }
1351
1352
  /**
1353
   * Get everything but the last..$to items.
1354
   *
1355
   * @param int $to
1356
   *
1357
   * @return static (Immutable)
1358
   */
1359 12
  public function initial($to = 1)
1360
  {
1361 12
    $slice = count($this->array) - $to;
1362
1363 12
    return $this->firstsImmutable($slice);
1364
  }
1365
1366
  /**
1367
   * Internal mechanics of remove method.
1368
   *
1369
   * @param string $key
1370
   *
1371
   * @return boolean
1372
   */
1373 18
  protected function internalRemove($key)
1374
  {
1375 18
    $path = explode($this->pathSeparator, (string)$key);
1376
1377
    // Crawl though the keys
1378 18
    while (count($path) > 1) {
1379
      $key = array_shift($path);
1380
1381
      if (!$this->has($key)) {
1382
        return false;
1383
      }
1384
1385
      $this->array = &$this->array[$key];
1386
    }
1387
1388 18
    $key = array_shift($path);
1389
1390 18
    unset($this->array[$key]);
1391
1392 18
    return true;
1393
  }
1394
1395
  /**
1396
   * Internal mechanic of set method.
1397
   *
1398
   * @param string $key
1399
   * @param mixed  $value
1400
   *
1401
   * @return bool
1402
   */
1403 28
  protected function internalSet($key, $value)
1404
  {
1405 28
    if ($key === null) {
1406
      return false;
1407
    }
1408
1409
    // init
1410 28
    $array =& $this->array;
1411 28
    $path = explode($this->pathSeparator, (string)$key);
1412
1413
    // Crawl through the keys
1414 28
    while (count($path) > 1) {
1415 2
      $key = array_shift($path);
1416
1417
      // If the key doesn't exist at this depth, we will just create an empty array
1418
      // to hold the next value, allowing us to create the arrays to hold final
1419
      // values at the correct depth. Then we'll keep digging into the array.
1420 2
      if (!isset($array[$key]) || !is_array($array[$key])) {
1421
        $array[$key] = self::create(array());
1422
      }
1423
1424 2
      $array =& $array[$key];
1425 2
    }
1426
1427 28
    $array[array_shift($path)] = $value;
1428
1429 28
    return true;
1430
  }
1431
1432
  /**
1433
   * Return an array with all elements found in input array.
1434
   *
1435
   * @param array $search
1436
   *
1437
   * @return static (Immutable)
1438
   */
1439 2
  public function intersection(array $search)
1440
  {
1441 2
    return static::create(array_values(array_intersect($this->array, $search)));
1442
  }
1443
1444
  /**
1445
   * Return a boolean flag which indicates whether the two input arrays have any common elements.
1446
   *
1447
   * @param array $search
1448
   *
1449
   * @return bool
1450
   */
1451 1
  public function intersects(array $search)
1452
  {
1453 1
    return count($this->intersection($search)->array) > 0;
1454
  }
1455
1456
  /**
1457
   * Invoke a function on all of an array's values.
1458
   *
1459
   * @param mixed $callable
1460
   * @param mixed $arguments
1461
   *
1462
   * @return static (Immutable)
1463
   */
1464 1
  public function invoke($callable, $arguments = array())
1465
  {
1466
    // If one argument given for each iteration, create an array for it.
1467 1
    if (!is_array($arguments)) {
1468 1
      $arguments = StaticArrayy::repeat($arguments, count($this->array))->getArray();
1469 1
    }
1470
1471
    // If the callable has arguments, pass them.
1472 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...
1473 1
      $array = array_map($callable, $this->array, $arguments);
1474 1
    } else {
1475 1
      $array = array_map($callable, $this->array);
1476
    }
1477
1478 1
    return static::create($array);
1479
  }
1480
1481
  /**
1482
   * Check whether array is associative or not.
1483
   *
1484
   * @return bool Returns true if associative, false otherwise
1485
   */
1486 15
  public function isAssoc()
1487
  {
1488 15
    if ($this->isEmpty()) {
1489 3
      return false;
1490
    }
1491
1492 13
    foreach ($this->keys()->getArray() as $key) {
1493 13
      if (!is_string($key)) {
1494 11
        return false;
1495
      }
1496 3
    }
1497
1498 3
    return true;
1499
  }
1500
1501
  /**
1502
   * Check whether the array is empty or not.
1503
   *
1504
   * @return bool Returns true if empty, false otherwise
1505
   */
1506 85
  public function isEmpty()
1507
  {
1508 85
    return !$this->array;
1509
  }
1510
1511
  /**
1512
   * Check if the current array is equal to the given "$array" or not.
1513
   *
1514
   * @param array $array
1515
   *
1516
   * @return bool
1517
   */
1518
  public function isEqual(array $array)
1519
  {
1520
    return ($this->array === $array);
1521
  }
1522
1523
  /**
1524
   * Check if the current array is a multi-array.
1525
   *
1526
   * @return bool
1527
   */
1528 14
  public function isMultiArray()
1529
  {
1530 14
    return !(count($this->array) === count($this->array, COUNT_RECURSIVE));
1531
  }
1532
1533
  /**
1534
   * Check whether array is numeric or not.
1535
   *
1536
   * @return bool Returns true if numeric, false otherwise
1537
   */
1538 5
  public function isNumeric()
1539
  {
1540 5
    if ($this->isEmpty()) {
1541 2
      return false;
1542
    }
1543
1544 4
    foreach ($this->keys() as $key) {
1545 4
      if (!is_int($key)) {
1546 2
        return false;
1547
      }
1548 3
    }
1549
1550 2
    return true;
1551
  }
1552
1553
  /**
1554
   * Check if the current array is sequential [0, 1, 2, 3, 4, 5 ...] or not.
1555
   *
1556
   * @return bool
1557
   */
1558 1
  public function isSequential()
1559
  {
1560 1
    return array_keys($this->array) === range(0, count($this->array) - 1);
1561
  }
1562
1563
  /**
1564
   * Get all keys from the current array.
1565
   *
1566
   * @return static (Immutable)
1567
   */
1568 25
  public function keys()
1569
  {
1570 25
    return static::create(array_keys($this->array));
1571
  }
1572
1573
  /**
1574
   * Get the last value from the current array.
1575
   *
1576
   * @return mixed Return null if there wasn't a element.
1577
   */
1578 4
  public function last()
1579
  {
1580 4
    return $this->pop();
1581
  }
1582
1583
  /**
1584
   * Get the last value(s) from the current array.
1585
   *
1586
   * @param int|null $number
1587
   *
1588
   * @return static (Immutable)
1589
   */
1590 13
  public function lastsImmutable($number = null)
1591
  {
1592 13
    if ($this->isEmpty()) {
1593 1
      return static::create();
1594
    }
1595
1596 12
    if ($number === null) {
1597 8
      $poppedValue = $this->pop();
1598
1599 8
      if ($poppedValue === null) {
1600 1
        $poppedValue = array($poppedValue);
1601 1
      } else {
1602 7
        $poppedValue = (array)$poppedValue;
1603
      }
1604
1605 8
      $arrayy = static::create($poppedValue);
1606 8
    } else {
1607 4
      $number = (int)$number;
1608 4
      $arrayy = $this->rest(-$number);
1609
    }
1610
1611 12
    return $arrayy;
1612
  }
1613
1614
  /**
1615
   * Get the last value(s) from the current array.
1616
   *
1617
   * @param int|null $number
1618
   *
1619
   * @return static (Mutable)
1620
   */
1621 13
  public function lastsMutable($number = null)
1622
  {
1623 13
    if ($this->isEmpty()) {
1624 1
      return $this;
1625
    }
1626
1627 12
    if ($number === null) {
1628 8
      $poppedValue = $this->pop();
1629
1630 8
      if ($poppedValue === null) {
1631 1
        $poppedValue = array($poppedValue);
1632 1
      } else {
1633 7
        $poppedValue = (array)$poppedValue;
1634
      }
1635
1636 8
      $this->array = static::create($poppedValue)->array;
1637 8
    } else {
1638 4
      $number = (int)$number;
1639 4
      $this->array = $this->rest(-$number)->array;
1640
    }
1641
1642 12
    return $this;
1643
  }
1644
1645
  /**
1646
   * Count the values from the current array.
1647
   *
1648
   * alias: for "Arrayy->size()"
1649
   *
1650
   * @see Arrayy::size()
1651
   *
1652
   * @return int
1653
   */
1654 10
  public function length()
1655
  {
1656 10
    return $this->size();
1657
  }
1658
1659
  /**
1660
   * Apply the given function to the every element of the array,
1661
   * collecting the results.
1662
   *
1663
   * @param callable $callable
1664
   *
1665
   * @return static (Immutable) Arrayy object with modified elements
1666
   */
1667 4
  public function map($callable)
1668
  {
1669 4
    $result = array_map($callable, $this->array);
1670
1671 4
    return static::create($result);
1672
  }
1673
1674
  /**
1675
   * Check if all items in current array match a truth test.
1676
   *
1677
   * @param \Closure $closure
1678
   *
1679
   * @return bool
1680
   */
1681 15 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...
1682
  {
1683 15
    if (count($this->array) === 0) {
1684 2
      return false;
1685
    }
1686
1687
    // init
1688 13
    $array = $this->array;
1689
1690 13
    foreach ($array as $key => $value) {
1691 13
      $value = $closure($value, $key);
1692
1693 13
      if ($value === false) {
1694 7
        return false;
1695
      }
1696 9
    }
1697
1698 7
    return true;
1699
  }
1700
1701
  /**
1702
   * Check if any item in the current array matches a truth test.
1703
   *
1704
   * @param \Closure $closure
1705
   *
1706
   * @return bool
1707
   */
1708 14 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...
1709
  {
1710 14
    if (count($this->array) === 0) {
1711 2
      return false;
1712
    }
1713
1714
    // init
1715 12
    $array = $this->array;
1716
1717 12
    foreach ($array as $key => $value) {
1718 12
      $value = $closure($value, $key);
1719
1720 12
      if ($value === true) {
1721 9
        return true;
1722
      }
1723 5
    }
1724
1725 4
    return false;
1726
  }
1727
1728
  /**
1729
   * Get the max value from an array.
1730
   *
1731
   * @return mixed
1732
   */
1733 10
  public function max()
1734
  {
1735 10
    if ($this->count() === 0) {
1736 1
      return false;
1737
    }
1738
1739 9
    return max($this->array);
1740
  }
1741
1742
  /**
1743
   * Merge the new $array into the current array.
1744
   *
1745
   * - keep key,value from the current array, also if the index is in the new $array
1746
   *
1747
   * @param array $array
1748
   * @param bool  $recursive
1749
   *
1750
   * @return static (Immutable)
1751
   */
1752 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...
1753
  {
1754 25
    if (true === $recursive) {
1755 4
      $result = array_replace_recursive($this->array, $array);
1756 4
    } else {
1757 21
      $result = array_replace($this->array, $array);
1758
    }
1759
1760 25
    return static::create($result);
1761
  }
1762
1763
  /**
1764
   * Merge the new $array into the current array.
1765
   *
1766
   * - replace duplicate assoc-keys from the current array with the key,values from the new $array
1767
   * - create new indexes
1768
   *
1769
   * @param array $array
1770
   * @param bool  $recursive
1771
   *
1772
   * @return static (Immutable)
1773
   */
1774 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...
1775
  {
1776 16
    if (true === $recursive) {
1777 4
      $result = array_merge_recursive($this->array, $array);
1778 4
    } else {
1779 12
      $result = array_merge($this->array, $array);
1780
    }
1781
1782 16
    return static::create($result);
1783
  }
1784
1785
  /**
1786
   * Merge the the current array into the $array.
1787
   *
1788
   * - use key,value from the new $array, also if the index is in the current array
1789
   *
1790
   * @param array $array
1791
   * @param bool  $recursive
1792
   *
1793
   * @return static (Immutable)
1794
   */
1795 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...
1796
  {
1797 16
    if (true === $recursive) {
1798 4
      $result = array_replace_recursive($array, $this->array);
1799 4
    } else {
1800 12
      $result = array_replace($array, $this->array);
1801
    }
1802
1803 16
    return static::create($result);
1804
  }
1805
1806
  /**
1807
   * Merge the current array into the new $array.
1808
   *
1809
   * - replace duplicate assoc-keys from new $array with the key,values from the current array
1810
   * - create new indexes
1811
   *
1812
   * @param array $array
1813
   * @param bool  $recursive
1814
   *
1815
   * @return static (Immutable)
1816
   */
1817 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...
1818
  {
1819 16
    if (true === $recursive) {
1820 4
      $result = array_merge_recursive($array, $this->array);
1821 4
    } else {
1822 12
      $result = array_merge($array, $this->array);
1823
    }
1824
1825 16
    return static::create($result);
1826
  }
1827
1828
  /**
1829
   * Get the min value from an array.
1830
   *
1831
   * @return mixed
1832
   */
1833 10
  public function min()
1834
  {
1835 10
    if ($this->count() === 0) {
1836 1
      return false;
1837
    }
1838
1839 9
    return min($this->array);
1840
  }
1841
1842
  /**
1843
   * Get a subset of the items from the given array.
1844
   *
1845
   * @param mixed[] $keys
1846
   *
1847
   * @return static (Immutable)
1848
   */
1849
  public function only(array $keys)
1850
  {
1851
    $array = $this->array;
1852
1853
    return static::create(array_intersect_key($array, array_flip($keys)));
1854
  }
1855
1856
  /**
1857
   * Pad array to the specified size with a given value.
1858
   *
1859
   * @param int   $size  Size of the result array
1860
   * @param mixed $value Empty value by default
1861
   *
1862
   * @return static (Immutable) Arrayy object padded to $size with $value
1863
   */
1864 4
  public function pad($size, $value)
1865
  {
1866 4
    $result = array_pad($this->array, $size, $value);
1867
1868 4
    return static::create($result);
1869
  }
1870
1871
  /**
1872
   * Pop a specified value off the end of the current array.
1873
   *
1874
   * @return mixed The popped element from the current array. (Mutable)
1875
   */
1876 16
  public function pop()
1877
  {
1878 16
    return array_pop($this->array);
1879
  }
1880
1881
  /**
1882
   * Prepend a value to the current array.
1883
   *
1884
   * @param mixed $value
1885
   * @param mixed $key
1886
   *
1887
   * @return static (Mutable) Return this Arrayy object, with the prepended value.
1888
   */
1889 8
  public function prepend($value, $key = null)
1890
  {
1891 8
    if ($key === null) {
1892 8
      array_unshift($this->array, $value);
1893 8
    } else {
1894
      /** @noinspection AdditionOperationOnArraysInspection */
1895 1
      $this->array = array($key => $value) + $this->array;
1896
    }
1897
1898 8
    return $this;
1899
  }
1900
1901
  /**
1902
   * Push one or more values onto the end of array at once.
1903
   *
1904
   * @return static (Mutable) Return this Arrayy object, with pushed elements to the end of array.
1905
   */
1906 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...
1907
  {
1908 4
    if (func_num_args()) {
1909 4
      $args = array_merge(array(&$this->array), func_get_args());
1910 4
      call_user_func_array('array_push', $args);
1911 4
    }
1912
1913 4
    return $this;
1914
  }
1915
1916
  /**
1917
   * Get a random value from the current array.
1918
   *
1919
   * @param null|int $number how many values you will take?
1920
   *
1921
   * @return static (Immutable)
1922
   */
1923 17
  public function randomImmutable($number = null)
1924
  {
1925 17
    if ($this->count() === 0) {
1926
      return static::create();
1927
    }
1928
1929 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...
1930 14
      $arrayRandValue = array($this->array[array_rand($this->array)]);
1931
1932 14
      return static::create($arrayRandValue);
1933
    }
1934
1935 5
    $arrayTmp = $this->array;
1936 5
    shuffle($arrayTmp);
1937
1938 5
    return self::create($arrayTmp)->firstsImmutable($number);
1939
  }
1940
1941
  /**
1942
   * Pick a random key/index from the keys of this array.
1943
   *
1944
   * @return mixed get a key/index or null if there wasn't a key/index
1945
   *
1946
   * @throws \RangeException If array is empty
1947
   */
1948 4
  public function randomKey()
1949
  {
1950 4
    $result = $this->randomKeys(1);
1951
1952 4
    if (!isset($result[0])) {
1953
      $result[0] = null;
1954
    }
1955
1956 4
    return $result[0];
1957
  }
1958
1959
  /**
1960
   * Pick a given number of random keys/indexes out of this array.
1961
   *
1962
   * @param int $number The number of keys/indexes (should be <= $this->count())
1963
   *
1964
   * @return static (Immutable)
1965
   *
1966
   * @throws \RangeException If array is empty
1967
   */
1968 14
  public function randomKeys($number)
1969
  {
1970 14
    $number = (int)$number;
1971 14
    $count = $this->count();
1972
1973 14
    if ($number === 0 || $number > $count) {
1974 3
      throw new \RangeException(
1975 3
          sprintf(
1976 3
              'Number of requested keys (%s) must be equal or lower than number of elements in this array (%s)',
1977 3
              $number,
1978
              $count
1979 3
          )
1980 3
      );
1981
    }
1982
1983 11
    $result = (array)array_rand($this->array, $number);
1984
1985 11
    return static::create($result);
1986
  }
1987
1988
  /**
1989
   * Get a random value from the current array.
1990
   *
1991
   * @param null|int $number how many values you will take?
1992
   *
1993
   * @return static (Mutable)
1994
   */
1995 17
  public function randomMutable($number = null)
1996
  {
1997 17
    if ($this->count() === 0) {
1998
      return static::create();
1999
    }
2000
2001 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...
2002 7
      $arrayRandValue = array($this->array[array_rand($this->array)]);
2003 7
      $this->array = $arrayRandValue;
2004
2005 7
      return $this;
2006
    }
2007
2008 11
    shuffle($this->array);
2009
2010 11
    return $this->firstsMutable($number);
2011
  }
2012
2013
  /**
2014
   * Pick a random value from the values of this array.
2015
   *
2016
   * @return mixed get a random value or null if there wasn't a value
2017
   */
2018 4
  public function randomValue()
2019
  {
2020 4
    $result = $this->randomImmutable();
2021
2022 4
    if (!isset($result[0])) {
2023
      $result[0] = null;
2024
    }
2025
2026 4
    return $result[0];
2027
  }
2028
2029
  /**
2030
   * Pick a given number of random values out of this array.
2031
   *
2032
   * @param int $number
2033
   *
2034
   * @return static (Mutable)
2035
   */
2036 7
  public function randomValues($number)
2037
  {
2038 7
    $number = (int)$number;
2039
2040 7
    return $this->randomMutable($number);
2041
  }
2042
2043
  /**
2044
   * Get a random value from an array, with the ability to skew the results.
2045
   *
2046
   * Example: randomWeighted(['foo' => 1, 'bar' => 2]) has a 66% chance of returning bar.
2047
   *
2048
   * @param array    $array
2049
   * @param null|int $number how many values you will take?
2050
   *
2051
   * @return static (Immutable)
2052
   */
2053 9
  public function randomWeighted(array $array, $number = null)
2054
  {
2055 9
    $options = array();
2056 9
    foreach ($array as $option => $weight) {
2057 9
      if ($this->searchIndex($option) !== false) {
2058 2
        for ($i = 0; $i < $weight; ++$i) {
2059 1
          $options[] = $option;
2060 1
        }
2061 2
      }
2062 9
    }
2063
2064 9
    return $this->mergeAppendKeepIndex($options)->randomImmutable($number);
2065
  }
2066
2067
  /**
2068
   * Reduce the current array via callable e.g. anonymous-function.
2069
   *
2070
   * @param mixed $callable
2071
   * @param array $init
2072
   *
2073
   * @return static (Immutable)
2074
   */
2075 3
  public function reduce($callable, array $init = array())
2076
  {
2077 3
    $result = array_reduce($this->array, $callable, $init);
2078
2079 3
    if ($result === null) {
2080
      $this->array = array();
2081
    } else {
2082 3
      $this->array = (array)$result;
2083
    }
2084
2085 3
    return static::create($this->array);
2086
  }
2087
2088
  /**
2089
   * Create a numerically re-indexed Arrayy object.
2090
   *
2091
   * @return static (Mutable) Return this Arrayy object, with re-indexed array-elements.
2092
   */
2093 9
  public function reindex()
2094
  {
2095 9
    $this->array = array_values($this->array);
2096
2097 9
    return $this;
2098
  }
2099
2100
  /**
2101
   * Return all items that fail the truth test.
2102
   *
2103
   * @param \Closure $closure
2104
   *
2105
   * @return static (Immutable)
2106
   */
2107 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...
2108
  {
2109 1
    $filtered = array();
2110
2111 1
    foreach ($this->array as $key => $value) {
2112 1
      if (!$closure($value, $key)) {
2113 1
        $filtered[$key] = $value;
2114 1
      }
2115 1
    }
2116
2117 1
    return static::create($filtered);
2118
  }
2119
2120
  /**
2121
   * Remove a value from the current array (optional using dot-notation).
2122
   *
2123
   * @param mixed $key
2124
   *
2125
   * @return static (Immutable)
2126
   */
2127 18
  public function remove($key)
2128
  {
2129
    // Recursive call
2130 18
    if (is_array($key)) {
2131
      foreach ($key as $k) {
2132
        $this->internalRemove($k);
2133
      }
2134
2135
      return static::create($this->array);
2136
    }
2137
2138 18
    $this->internalRemove($key);
2139
2140 18
    return static::create($this->array);
2141
  }
2142
2143
  /**
2144
   * Remove the first value from the current array.
2145
   *
2146
   * @return static (Immutable)
2147
   */
2148 7
  public function removeFirst()
2149
  {
2150 7
    $tmpArray = $this->array;
2151 7
    array_shift($tmpArray);
2152
2153 7
    return static::create($tmpArray);
2154
  }
2155
2156
  /**
2157
   * Remove the last value from the current array.
2158
   *
2159
   * @return static (Immutable)
2160
   */
2161 7
  public function removeLast()
2162
  {
2163 7
    $tmpArray = $this->array;
2164 7
    array_pop($tmpArray);
2165
2166 7
    return static::create($tmpArray);
2167
  }
2168
2169
  /**
2170
   * Removes a particular value from an array (numeric or associative).
2171
   *
2172
   * @param mixed $value
2173
   *
2174
   * @return static (Immutable)
2175
   */
2176 7
  public function removeValue($value)
2177
  {
2178 7
    $isNumericArray = true;
2179 7
    foreach ($this->array as $key => $item) {
2180 6
      if ($item === $value) {
2181 6
        if (!is_int($key)) {
2182
          $isNumericArray = false;
2183
        }
2184 6
        unset($this->array[$key]);
2185 6
      }
2186 7
    }
2187
2188 7
    if ($isNumericArray) {
2189 7
      $this->array = array_values($this->array);
2190 7
    }
2191
2192 7
    return static::create($this->array);
2193
  }
2194
2195
  /**
2196
   * Replace a key with a new key/value pair.
2197
   *
2198
   * @param $replace
2199
   * @param $key
2200
   * @param $value
2201
   *
2202
   * @return static (Immutable)
2203
   */
2204 2
  public function replace($replace, $key, $value)
2205
  {
2206 2
    $this->remove($replace);
2207
2208 2
    return $this->set($key, $value);
2209
  }
2210
2211
  /**
2212
   * Create an array using the current array as values and the other array as keys.
2213
   *
2214
   * @param array $keys Keys array
2215
   *
2216
   * @return static (Immutable) Arrayy object with keys from the other array.
2217
   */
2218 2
  public function replaceAllKeys(array $keys)
2219
  {
2220 2
    $result = array_combine($keys, $this->array);
2221
2222 2
    return static::create($result);
2223
  }
2224
2225
  /**
2226
   * Create an array using the current array as keys and the other array as values.
2227
   *
2228
   * @param array $array Values array
2229
   *
2230
   * @return static (Immutable) Arrayy object with values from the other array.
2231
   */
2232 2
  public function replaceAllValues(array $array)
2233
  {
2234 2
    $result = array_combine($this->array, $array);
2235
2236 2
    return static::create($result);
2237
  }
2238
2239
  /**
2240
   * Replace the keys in an array with another set.
2241
   *
2242
   * @param array $keys An array of keys matching the array's size
2243
   *
2244
   * @return static (Immutable)
2245
   */
2246 1
  public function replaceKeys(array $keys)
2247
  {
2248 1
    $values = array_values($this->array);
2249 1
    $result = array_combine($keys, $values);
2250
2251 1
    return static::create($result);
2252
  }
2253
2254
  /**
2255
   * Replace the first matched value in an array.
2256
   *
2257
   * @param mixed $search
2258
   * @param mixed $replacement
2259
   *
2260
   * @return static (Immutable)
2261
   */
2262 3
  public function replaceOneValue($search, $replacement = '')
2263
  {
2264 3
    $array = $this->array;
2265 3
    $key = array_search($search, $array, true);
2266
2267 3
    if ($key !== false) {
2268 3
      $array[$key] = $replacement;
2269 3
    }
2270
2271 3
    return static::create($array);
2272
  }
2273
2274
  /**
2275
   * Replace values in the current array.
2276
   *
2277
   * @param string $search      The string to replace.
2278
   * @param string $replacement What to replace it with.
2279
   *
2280
   * @return static (Immutable)
2281
   */
2282 1
  public function replaceValues($search, $replacement = '')
2283
  {
2284 1
    $array = $this->each(
2285
        function ($value) use ($search, $replacement) {
2286 1
          return UTF8::str_replace($search, $replacement, $value);
2287
        }
2288 1
    );
2289
2290 1
    return $array;
2291
  }
2292
2293
  /**
2294
   * Get the last elements from index $from until the end of this array.
2295
   *
2296
   * @param int $from
2297
   *
2298
   * @return static (Immutable)
2299
   */
2300 15
  public function rest($from = 1)
2301
  {
2302 15
    $tmpArray = $this->array;
2303
2304 15
    return static::create(array_splice($tmpArray, $from));
2305
  }
2306
2307
  /**
2308
   * Move an array element to a new index.
2309
   *
2310
   * cherry-picked from: http://stackoverflow.com/questions/12624153/move-an-array-element-to-a-new-index-in-php
2311
   *
2312
   * @param int|string $from
2313
   * @param int|string $to
2314
   *
2315
   * @return static (Immutable)
2316
   */
2317 1
  public function moveElement($from, $to)
2318
  {
2319 1
    $array = $this->array;
2320
2321 1
    if (is_int($from)) {
2322 1
      $tmp = array_splice($array, $from, 1);
2323 1
      array_splice($array, $to, 0, $tmp);
2324 1
      $output = $array;
2325 1
    } elseif (is_string($from)) {
2326 1
      $indexToMove = array_search($from, array_keys($array), true);
2327 1
      $itemToMove = $array[$from];
2328 1
      array_splice($array, $indexToMove, 1);
2329 1
      $i = 0;
2330 1
      $output = array();
2331 1
      foreach($array as $key => $item) {
2332 1
        if ($i == $to) {
2333 1
          $output[$from] = $itemToMove;
2334 1
        }
2335 1
        $output[$key] = $item;
2336 1
        $i++;
2337 1
      }
2338 1
    } else {
2339
      $output = array();
2340
    }
2341
2342 1
    return static::create($output);
2343
  }
2344
2345
  /**
2346
   * Return the array in the reverse order.
2347
   *
2348
   * @return static (Mutable) Return this Arrayy object.
2349
   */
2350 7
  public function reverse()
2351
  {
2352 7
    $this->array = array_reverse($this->array);
2353
2354 7
    return $this;
2355
  }
2356
2357
  /**
2358
   * Search for the first index of the current array via $value.
2359
   *
2360
   * @param mixed $value
2361
   *
2362
   * @return int|float|string
2363
   */
2364 20
  public function searchIndex($value)
2365
  {
2366 20
    return array_search($value, $this->array, true);
2367
  }
2368
2369
  /**
2370
   * Search for the value of the current array via $index.
2371
   *
2372
   * @param mixed $index
2373
   *
2374
   * @return static (Immutable) will return a empty Arrayy if the value wasn't found
2375
   */
2376 9
  public function searchValue($index)
2377
  {
2378
    // init
2379 9
    $return = array();
2380
2381 9
    if ($this->isEmpty()) {
2382
      return static::create();
2383
    }
2384
2385
    // php cast "bool"-index into "int"-index
2386 9
    if ((bool)$index === $index) {
2387 1
      $index = (int)$index;
2388 1
    }
2389
2390 9
    if (array_key_exists($index, $this->array) === true) {
2391 7
      $return = array($this->array[$index]);
2392 7
    }
2393
2394
2395 9
    return static::create($return);
2396
  }
2397
2398
  /**
2399
   * Set a value for the current array (optional using dot-notation).
2400
   *
2401
   * @param string $key   The key to set
2402
   * @param mixed  $value Its value
2403
   *
2404
   * @return static (Immutable)
2405
   */
2406 17
  public function set($key, $value)
2407
  {
2408 17
    $this->internalSet($key, $value);
2409
2410 17
    return static::create($this->array);
2411
  }
2412
2413
  /**
2414
   * Get a value from a array and set it if it was not.
2415
   *
2416
   * WARNING: this method only set the value, if the $key is not already set
2417
   *
2418
   * @param string $key      The key
2419
   * @param mixed  $fallback The default value to set if it isn't
2420
   *
2421
   * @return mixed (Mutable)
2422
   */
2423 11
  public function setAndGet($key, $fallback = null)
2424
  {
2425
    // If the key doesn't exist, set it
2426 11
    if (!$this->has($key)) {
2427 4
      $this->array = $this->set($key, $fallback)->getArray();
2428 4
    }
2429
2430 11
    return $this->get($key);
2431
  }
2432
2433
  /**
2434
   * Shifts a specified value off the beginning of array.
2435
   *
2436
   * @return mixed A shifted element from the current array. (Mutable)
2437
   */
2438 4
  public function shift()
2439
  {
2440 4
    return array_shift($this->array);
2441
  }
2442
2443
  /**
2444
   * Shuffle the current array.
2445
   *
2446
   * @return static (Immutable)
2447
   */
2448 1
  public function shuffle()
2449
  {
2450 1
    $array = $this->array;
2451
2452 1
    shuffle($array);
2453
2454 1
    return static::create($array);
2455
  }
2456
2457
  /**
2458
   * Get the size of an array.
2459
   *
2460
   * @return int
2461
   */
2462 93
  public function size()
2463
  {
2464 93
    return count($this->array);
2465
  }
2466
2467
  /**
2468
   * Extract a slice of the array.
2469
   *
2470
   * @param int      $offset       Slice begin index
2471
   * @param int|null $length       Length of the slice
2472
   * @param bool     $preserveKeys Whether array keys are preserved or no
2473
   *
2474
   * @return static A slice of the original array with length $length
2475
   */
2476 4
  public function slice($offset, $length = null, $preserveKeys = false)
2477
  {
2478 4
    $result = array_slice($this->array, $offset, $length, $preserveKeys);
2479
2480 4
    return static::create($result);
2481
  }
2482
2483
  /**
2484
   * Sort the current array and optional you can keep the keys.
2485
   *
2486
   * @param integer $direction use SORT_ASC or SORT_DESC
2487
   * @param integer $strategy
2488
   * @param bool    $keepKeys
2489
   *
2490
   * @return static (Mutable) Return this Arrayy object.
2491
   */
2492 19
  public function sort($direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
2493
  {
2494 19
    $this->sorting($this->array, $direction, $strategy, $keepKeys);
2495
2496 19
    return $this;
2497
  }
2498
2499
  /**
2500
   * Sort the current array by key.
2501
   *
2502
   * @link http://php.net/manual/en/function.ksort.php
2503
   * @link http://php.net/manual/en/function.krsort.php
2504
   *
2505
   * @param int|string $direction use SORT_ASC or SORT_DESC
2506
   * @param int        $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
2507
   *
2508
   * @return static (Mutable) Return this Arrayy object.
2509
   */
2510 18
  public function sortKeys($direction = SORT_ASC, $strategy = SORT_REGULAR)
2511
  {
2512 18
    $this->sorterKeys($this->array, $direction, $strategy);
2513
2514 18
    return $this;
2515
  }
2516
2517
  /**
2518
   * Sort the current array by value.
2519
   *
2520
   * @param int $direction use SORT_ASC or SORT_DESC
2521
   * @param int $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
2522
   *
2523
   * @return static (Immutable)
2524
   */
2525 1
  public function sortValueKeepIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
2526
  {
2527 1
    return $this->sort($direction, $strategy, true);
2528
  }
2529
2530
  /**
2531
   * Sort the current array by value.
2532
   *
2533
   * @param int $direction use SORT_ASC or SORT_DESC
2534
   * @param int $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
2535
   *
2536
   * @return static (Immutable)
2537
   */
2538 1
  public function sortValueNewIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
2539
  {
2540 1
    return $this->sort($direction, $strategy, false);
2541
  }
2542
2543
  /**
2544
   * Sort a array by value, by a closure or by a property.
2545
   *
2546
   * - If the sorter is null, the array is sorted naturally.
2547
   * - Associative (string) keys will be maintained, but numeric keys will be re-indexed.
2548
   *
2549
   * @param null       $sorter
2550
   * @param string|int $direction
2551
   * @param int        $strategy
2552
   *
2553
   * @return static (Immutable)
2554
   */
2555 1
  public function sorter($sorter = null, $direction = SORT_ASC, $strategy = SORT_REGULAR)
2556
  {
2557 1
    $array = (array)$this->array;
2558 1
    $direction = $this->getDirection($direction);
2559
2560
    // Transform all values into their results.
2561 1
    if ($sorter) {
2562 1
      $arrayy = self::create($array);
2563
2564 1
      $that = $this;
2565 1
      $results = $arrayy->each(
2566
          function ($value) use ($sorter, $that) {
2567 1
            return is_callable($sorter) ? $sorter($value) : $that->get($sorter, null, $value);
2568
          }
2569 1
      );
2570
2571 1
      $results = $results->getArray();
2572 1
    } else {
2573 1
      $results = $array;
2574
    }
2575
2576
    // Sort by the results and replace by original values
2577 1
    array_multisort($results, $direction, $strategy, $array);
2578
2579 1
    return static::create($array);
2580
  }
2581
2582
  /**
2583
   * sorting keys
2584
   *
2585
   * @param array $elements
2586
   * @param int   $direction
2587
   * @param int   $strategy
2588
   */
2589 18
  protected function sorterKeys(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR)
2590
  {
2591 18
    $direction = $this->getDirection($direction);
2592
2593
    switch ($direction) {
2594 18
      case 'desc':
2595 18
      case SORT_DESC:
2596 6
        krsort($elements, $strategy);
2597 6
        break;
2598 13
      case 'asc':
2599 13
      case SORT_ASC:
2600 13
      default:
2601 13
        ksort($elements, $strategy);
2602 13
    }
2603 18
  }
2604
2605
  /**
2606
   * @param array      &$elements
2607
   * @param int|string $direction
2608
   * @param int        $strategy
2609
   * @param bool       $keepKeys
2610
   */
2611 19
  protected function sorting(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
2612
  {
2613 19
    $direction = $this->getDirection($direction);
2614
2615 19
    if (!$strategy) {
2616 19
      $strategy = SORT_REGULAR;
2617 19
    }
2618
2619
    switch ($direction) {
2620 19
      case 'desc':
2621 19
      case SORT_DESC:
2622 9
        if ($keepKeys) {
2623 5
          arsort($elements, $strategy);
2624 5
        } else {
2625 4
          rsort($elements, $strategy);
2626
        }
2627 9
        break;
2628 10
      case 'asc':
2629 10
      case SORT_ASC:
2630 10
      default:
2631 10
        if ($keepKeys) {
2632 4
          asort($elements, $strategy);
2633 4
        } else {
2634 6
          sort($elements, $strategy);
2635
        }
2636 10
    }
2637 19
  }
2638
2639
  /**
2640
   * Split an array in the given amount of pieces.
2641
   *
2642
   * @param int  $numberOfPieces
2643
   * @param bool $keepKeys
2644
   *
2645
   * @return static (Immutable)
2646
   */
2647 1
  public function split($numberOfPieces = 2, $keepKeys = false)
2648
  {
2649 1
    $arrayCount = $this->count();
2650
2651 1
    if ($arrayCount === 0) {
2652 1
      $result = array();
2653 1
    } else {
2654 1
      $numberOfPieces = (int)$numberOfPieces;
2655 1
      $splitSize = (int)ceil($arrayCount / $numberOfPieces);
2656 1
      $result = array_chunk($this->array, $splitSize, $keepKeys);
2657
    }
2658
2659 1
    return static::create($result);
2660
  }
2661
2662
  /**
2663
   * Stripe all empty items.
2664
   *
2665
   * @return static (Immutable)
2666
   */
2667 1
  public function stripEmpty()
2668
  {
2669 1
    return $this->filter(
2670
        function ($item) {
2671 1
          if ($item === null) {
2672 1
            return false;
2673
          }
2674
2675 1
          return (bool)trim((string)$item);
2676
        }
2677 1
    );
2678
  }
2679
2680
  /**
2681
   * Swap two values between positions by key.
2682
   *
2683
   * @param string|int $swapA an key in the array
2684
   * @param string|int $swapB an key in the array
2685
   *
2686
   * @return static (Immutable)
2687
   */
2688 1
  public function swap($swapA, $swapB)
2689
  {
2690 1
    $array = $this->array;
2691
2692 1
    list($array[$swapA], $array[$swapB]) = array($array[$swapB], $array[$swapA]);
2693
2694 1
    return static::create($array);
2695
  }
2696
2697
  /**
2698
   * alias: for "Arrayy->getArray()"
2699
   *
2700
   * @see Arrayy::getArray()
2701
   */
2702 141
  public function toArray()
2703
  {
2704 141
    return $this->getArray();
2705
  }
2706
2707
  /**
2708
   * Convert the current array to JSON.
2709
   *
2710
   * @param null $options e.g. JSON_PRETTY_PRINT
2711
   *
2712
   * @return string
2713
   */
2714 5
  public function toJson($options = null)
2715
  {
2716 5
    return UTF8::json_encode($this->array, $options);
2717
  }
2718
2719
  /**
2720
   * Implodes array to a string with specified separator.
2721
   *
2722
   * @param string $separator The element's separator
2723
   *
2724
   * @return string The string representation of array, separated by ","
2725
   */
2726 19
  public function toString($separator = ',')
2727
  {
2728 19
    return $this->implode($separator);
2729
  }
2730
2731
  /**
2732
   * alias: for "Arrayy->unique()"
2733
   *
2734
   * @see Arrayy::unique()
2735
   *
2736 8
   * @return static (Mutable) Return this Arrayy object, with the appended values.
2737
   */
2738 8
  public function uniqueKeepIndex()
2739 8
  {
2740 8
    return $this->unique();
2741 7
  }
2742 7
2743 7
  /**
2744
   * Return a duplicate free copy of the current array.
2745 7
   *
2746 8
   * @return static (Mutable)
2747 8
   */
2748 8
  public function unique()
2749
  {
2750 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...
2751
        $this->array,
2752
        function ($resultArray, $value) {
2753 8
          if (!in_array($value, $resultArray, true)) {
2754
            $resultArray[] = $value;
2755
          }
2756 8
2757
          return $resultArray;
2758
        },
2759
        array()
2760
    );
2761
2762
    if ($this->array === null) {
2763
      $this->array = array();
2764 4
    } else {
2765
      $this->array = (array)$this->array;
2766 4
    }
2767 4
2768 4
    return $this;
2769 4
  }
2770
2771 4
  /**
2772
   * Prepends one or more values to the beginning of array at once.
2773
   *
2774
   * @return static (Mutable) Return this Arrayy object, with prepended elements to the beginning of array.
2775
   */
2776 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...
2777
  {
2778
    if (func_num_args()) {
2779 2
      $args = array_merge(array(&$this->array), func_get_args());
2780
      call_user_func_array('array_unshift', $args);
2781 2
    }
2782
2783
    return $this;
2784
  }
2785
2786
  /**
2787
   * Get all values from a array.
2788
   *
2789
   * @return static (Immutable)
2790
   */
2791
  public function values()
2792 9
  {
2793
    return static::create(array_values((array)$this->array));
2794 9
  }
2795 4
2796 4
  /**
2797 5
   * Apply the given function to every element in the array, discarding the results.
2798
   *
2799
   * @param callable $callable
2800 9
   * @param bool     $recursive Whether array will be walked recursively or no
2801
   *
2802
   * @return static (Mutable) Return this Arrayy object, with modified elements
2803
   */
2804
  public function walk($callable, $recursive = false)
2805
  {
2806
    if (true === $recursive) {
2807
      array_walk_recursive($this->array, $callable);
2808
    } else {
2809
      array_walk($this->array, $callable);
2810
    }
2811
2812
    return $this;
2813
  }
2814
2815
}
2816