Completed
Push — master ( 9eccde...ce6277 )
by Lars
02:25
created

Arrayy::pad()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 2
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Arrayy;
4
5
use voku\helper\UTF8;
6
7
/** @noinspection ClassReImplementsParentInterfaceInspection */
8
9
/**
10
 * Methods to manage arrays.
11
 *
12
 * For the full copyright and license information, please view the LICENSE
13
 * file that was distributed with this source code.
14
 */
15
class Arrayy extends \ArrayObject implements \ArrayAccess, \Serializable, \Countable
16
{
17
  /**
18
   * @var array
19
   */
20
  protected $array = array();
21
22
  /**
23
   * @var string
24
   */
25
  protected $pathSeparator = '.';
26
27
  /** @noinspection MagicMethodsValidityInspection */
28
  /**
29
   * Initializes
30
   *
31
   * @param array $array
32
   */
33 728
  public function __construct($array = array())
34
  {
35 728
    $array = $this->fallbackForArray($array);
36
37 726
    $this->array = $array;
38 726
  }
39
40
  /**
41
   * Get a value by key.
42
   *
43
   * @param $key
44
   *
45
   * @return mixed Get a Value from the current array.
46
   */
47
  public function &__get($key)
48
  {
49
    return $this->array[$key];
50
  }
51
52
  /**
53
   * Call object as function.
54
   *
55
   * @param mixed $key
56
   *
57
   * @return mixed
58
   */
59
  public function __invoke($key = null)
60
  {
61
    if ($key !== null) {
62
      if (isset($this->array[$key])) {
63
        return $this->array[$key];
64
      } else {
65
        return false;
66
      }
67
    }
68
69
    return (array)$this->array;
70
  }
71
72
  /**
73
   * Whether or not an element exists by key.
74
   *
75
   * @param mixed $key
76
   *
77
   * @return bool True is the key/index exists, otherwise false.
78
   */
79
  public function __isset($key)
80
  {
81
    return $this->offsetExists($key);
82
  }
83
84
  /**
85
   * Assigns a value to the specified element.
86
   *
87
   * @param mixed $key
88
   * @param mixed $value
89
   */
90
  public function __set($key, $value)
91
  {
92
    $this->internalSet($key, $value);
93
  }
94
95
  /**
96
   * magic to string
97
   *
98
   * @return string
99
   */
100 16
  public function __toString()
101
  {
102 16
    return $this->toString();
103
  }
104
105
  /**
106
   * Unset element by key.
107
   *
108
   * @param mixed $key
109
   */
110
  public function __unset($key)
111
  {
112
    unset($this->array[$key]);
113
  }
114
115
  /**
116
   * alias: for "Arrayy->append()"
117
   *
118
   * @see Arrayy::append()
119
   *
120
   * @param mixed $value
121
   *
122
   * @return self (Mutable) Return this Arrayy object, with the appended values.
123
   */
124 1
  public function add($value)
125
  {
126 1
    return $this->append($value);
127
  }
128
129
  /**
130
   * Append a value to the current array.
131
   *
132
   * @param mixed $value
133
   *
134
   * @return self (Mutable) Return this Arrayy object, with the appended values.
135
   */
136 9
  public function append($value)
137
  {
138 9
    $this->array[] = $value;
139
140 9
    return $this;
141
  }
142
143
  /**
144
   * Count the values from the current array.
145
   *
146
   * alias: for "Arrayy->size()"
147
   *
148
   * @see Arrayy::size()
149
   *
150
   * @return int
151
   */
152 110
  public function count()
153
  {
154 110
    return $this->size();
155
  }
156
157
  /**
158
   * Returns a new ArrayyIterator, thus implementing the IteratorAggregate interface.
159
   *
160
   * @return ArrayyIterator An iterator for the values in the array.
161
   */
162 19
  public function getIterator()
163
  {
164 19
    return new ArrayyIterator($this->array);
165
  }
166
167
  /**
168
   * Whether or not an offset exists.
169
   *
170
   * @param mixed $offset
171
   *
172
   * @return bool
173
   */
174 37
  public function offsetExists($offset)
175
  {
176 37
    $tmpReturn = isset($this->array[$offset]);
177
178
    if (
179 37
        $tmpReturn === true
180
        ||
181
        (
182 15
            $tmpReturn === false
183
            &&
184 37
            strpos($offset, $this->pathSeparator) === false
185
        )
186
    ) {
187
188 35
      return isset($this->array[$offset]);
189
190
    } else {
191
192 2
      $offsetExists = false;
193 2
      $explodedPath = explode($this->pathSeparator, $offset);
194 2
      $lastOffset = array_pop($explodedPath);
195 2
      $containerPath = implode($this->pathSeparator, $explodedPath);
196
197 2
      $this->callAtPath(
198
          $containerPath,
199
          function ($container) use ($lastOffset, &$offsetExists) {
200 2
            $offsetExists = isset($container[$lastOffset]);
201 2
          }
202
      );
203
204 2
      return $offsetExists;
205
    }
206
  }
207
208
  /**
209
   * Returns the value at specified offset.
210
   *
211
   * @param mixed $offset
212
   *
213
   * @return mixed return null if the offset did not exists
214
   */
215 23
  public function offsetGet($offset)
216
  {
217 23
    return $this->offsetExists($offset) ? $this->get($offset) : null;
218
  }
219
220
  /**
221
   * Assigns a value to the specified offset.
222
   *
223
   * @param mixed $offset
224
   * @param mixed $value
225
   */
226 14
  public function offsetSet($offset, $value)
227
  {
228 14
    if (null === $offset) {
229 4
      $this->array[] = $value;
230
    } else {
231 10
      $this->internalSet($offset, $value);
232
    }
233 14
  }
234
235
  /**
236
   * Unset an offset.
237
   *
238
   * @param mixed $offset
239
   */
240 6
  public function offsetUnset($offset)
241
  {
242 6
    if (isset($this->array[$offset])) {
243 3
      unset($this->array[$offset]);
244
245 3
      return;
246
    }
247
248 3
    $path = explode($this->pathSeparator, $offset);
249 3
    $pathToUnset = array_pop($path);
250
251 3
    $this->callAtPath(
252 3
        implode($this->pathSeparator, $path),
253
        function (&$offset) use (&$pathToUnset) {
254 1
          unset($offset[$pathToUnset]);
255 3
        }
256
    );
257 3
  }
258
259
  /**
260
   * Serialize the current array.
261
   *
262
   * @return string
263
   */
264 2
  public function serialize()
265
  {
266 2
    return serialize($this->array);
267
  }
268
269
  /**
270
   * Unserialize an string and return this object.
271
   *
272
   * @param string $string
273
   *
274
   * @return self (Mutable)
275
   */
276 2
  public function unserialize($string)
277
  {
278 2
    $this->array = unserialize($string);
279
280 2
    return $this;
281
  }
282
283
  /**
284
   * Iterate over the current array and execute a callback for each loop.
285
   *
286
   * @param \Closure $closure
287
   *
288
   * @return Arrayy (Immutable)
289
   */
290 2 View Code Duplication
  public function at(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
291
  {
292 2
    $array = $this->array;
293
294 2
    foreach ($array as $key => $value) {
295 2
      $closure($value, $key);
296
    }
297
298 2
    return static::create($array);
299
  }
300
301
  /**
302
   * Returns the average value of the current array.
303
   *
304
   * @param int $decimals The number of decimals to return
305
   *
306
   * @return int|double The average value
307
   */
308 10
  public function average($decimals = null)
309
  {
310 10
    $count = $this->count();
311
312 10
    if (!$count) {
313 2
      return 0;
314
    }
315
316 8
    if (!is_int($decimals)) {
317 3
      $decimals = null;
318
    }
319
320 8
    return round(array_sum($this->array) / $count, $decimals);
321
  }
322
323
  /**
324
   * @param mixed      $path
325
   * @param callable   $callable
326
   * @param null|array $currentOffset
327
   */
328 4
  protected function callAtPath($path, $callable, &$currentOffset = null)
329
  {
330 4
    if ($currentOffset === null) {
331 4
      $currentOffset = &$this->array;
332
    }
333
334 4
    $explodedPath = explode($this->pathSeparator, $path);
335 4
    $nextPath = array_shift($explodedPath);
336
337 4
    if (!isset($currentOffset[$nextPath])) {
338 2
      return;
339
    }
340
341 2
    if (!empty($explodedPath)) {
342
      $this->callAtPath(
343
          implode($this->pathSeparator, $explodedPath),
344
          $callable,
345
          $currentOffset[$nextPath]
346
      );
347
    } else {
348 2
      $callable($currentOffset[$nextPath]);
349
    }
350 2
  }
351
352
  /**
353
   * Change the path separator of the array wrapper.
354
   *
355
   * By default, the separator is: .
356
   *
357
   * @param string $separator Separator to set.
358
   *
359
   * @return Arrayy Current instance.
360
   */
361
  public function changeSeparator($separator)
362
  {
363
    $this->pathSeparator = $separator;
364
365
    return $this;
366
  }
367
368
  /**
369
   * Create a chunked version of the current array.
370
   *
371
   * @param int  $size         Size of each chunk
372
   * @param bool $preserveKeys Whether array keys are preserved or no
373
   *
374
   * @return Arrayy (Immutable) A new array of chunks from the original array.
375
   */
376 4
  public function chunk($size, $preserveKeys = false)
377
  {
378 4
    $result = array_chunk($this->array, $size, $preserveKeys);
379
380 4
    return static::create($result);
381
  }
382
383
  /**
384
   * Clean all falsy values from the current array.
385
   *
386
   * @return Arrayy (Immutable)
387
   */
388 8
  public function clean()
389
  {
390 8
    return $this->filter(
391
        function ($value) {
392 7
          return (bool)$value;
393 8
        }
394
    );
395
  }
396
397
  /**
398
   * WARNING!!! -> Clear the current array.
399
   *
400
   * @return self (Mutable) Return this Arrayy object, with an empty array.
401
   */
402 4
  public function clear()
403
  {
404 4
    $this->array = array();
405
406 4
    return $this;
407
  }
408
409
  /**
410
   * Check if an item is in the current array.
411
   *
412
   * @param string|int|float $value
413
   *
414
   * @return bool
415
   */
416 13
  public function contains($value)
417
  {
418 13
    return in_array($value, $this->array, true);
419
  }
420
421
  /**
422
   * Check if an (case-insensitive) string is in the current array.
423
   *
424
   * @param string $value
425
   *
426
   * @return bool
427
   */
428 13
  public function containsCaseInsensitive($value)
429
  {
430 13
    return in_array(
431 13
        UTF8::strtolower($value),
432
        array_map(
433
            array(
434 13
                new UTF8(),
435 13
                'strtolower',
436
            ),
437 13
            $this->array
438
        ),
439 13
        true
440
    );
441
  }
442
443
  /**
444
   * Check if the given key/index exists in the array.
445
   *
446
   * @param string|int|float $key key/index to search for
447
   *
448
   * @return bool Returns true if the given key/index exists in the array, false otherwise
449
   */
450 4
  public function containsKey($key)
451
  {
452 4
    return $this->offsetExists($key);
453
  }
454
455
  /**
456
   * Check if all given needles are present in the array as key/index.
457
   *
458
   * @param array $needles
459
   *
460
   * @return bool Returns true if the given keys/indexes exists in the array, false otherwise
461
   */
462 1
  public function containsKeys(array $needles)
463
  {
464 1
    return count(array_intersect($needles, $this->keys()->getArray())) === count($needles);
465
  }
466
467
  /**
468
   * alias: for "Arrayy->contains()"
469
   *
470
   * @see Arrayy::contains()
471
   *
472
   * @param string|int|float $value
473
   *
474
   * @return bool
475
   */
476
  public function containsValue($value)
477
  {
478
    return $this->contains($value);
479
  }
480
481
  /**
482
   * Check if all given needles are present in the array.
483
   *
484
   * @param array $needles
485
   *
486
   * @return bool Returns true if the given values exists in the array, false otherwise
487
   */
488 1
  public function containsValues(array $needles)
489
  {
490 1
    return count(array_intersect($needles, $this->array)) === count($needles);
491
  }
492
493
  /**
494
   * Creates an Arrayy object.
495
   *
496
   * @param array $array
497
   *
498
   * @return Arrayy (Immutable) Returns an new instance of the Arrayy object.
499
   */
500 452
  public static function create($array = array())
501
  {
502 452
    return new static($array);
503
  }
504
505
  /**
506
   * WARNING: Creates an Arrayy object by reference.
507
   *
508
   * @param array $array
509
   *
510
   * @return self (Mutable) Return this Arrayy object.
511
   */
512
  public function createByReference(&$array = array())
513
  {
514
    $array = $this->fallbackForArray($array);
515
516
    $this->array = &$array;
517
518
    return $this;
519
  }
520
521
  /**
522
   * Create an new Arrayy object via JSON.
523
   *
524
   * @param string $json
525
   *
526
   * @return Arrayy (Immutable) Returns an new instance of the Arrayy object.
527
   */
528 5
  public static function createFromJson($json)
529
  {
530 5
    $array = UTF8::json_decode($json, true);
531
532 5
    return static::create($array);
533
  }
534
535
  /**
536
   * Create an new instance filled with values from an object that have implemented ArrayAccess.
537
   *
538
   * @param \ArrayAccess $object Object that implements ArrayAccess
539
   *
540
   * @return Arrayy (Immutable) Returns an new instance of the Arrayy object.
541
   */
542 4
  public static function createFromObject(\ArrayAccess $object)
543
  {
544 4
    $array = new static();
545 4
    foreach ($object as $key => $value) {
546
      /** @noinspection OffsetOperationsInspection */
547 3
      $array[$key] = $value;
548
    }
549
550 4
    return $array;
551
  }
552
553
  /**
554
   * Create an new Arrayy object via string.
555
   *
556
   * @param string      $str       The input string.
557
   * @param string|null $delimiter The boundary string.
558
   * @param string|null $regEx     Use the $delimiter or the $regEx, so if $pattern is null, $delimiter will be used.
559
   *
560
   * @return Arrayy (Immutable) Returns an new instance of the Arrayy object.
561
   */
562 8
  public static function createFromString($str, $delimiter, $regEx = null)
563
  {
564 8
    if ($regEx) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $regEx of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
565 1
      preg_match_all($regEx, $str, $array);
566
567 1
      if (!empty($array)) {
568 1
        $array = $array[0];
569
      }
570
571
    } else {
572 7
      $array = explode($delimiter, $str);
573
    }
574
575
    // trim all string in the array
576 8
    array_walk(
577
        $array,
578
        function (&$val) {
579
          /** @noinspection ReferenceMismatchInspection */
580 8
          if (is_string($val)) {
581 8
            $val = trim($val);
582
          }
583 8
        }
584
    );
585
586 8
    return static::create($array);
587
  }
588
589
  /**
590
   * Create an new instance containing a range of elements.
591
   *
592
   * @param mixed $low  First value of the sequence
593
   * @param mixed $high The sequence is ended upon reaching the end value
594
   * @param int   $step Used as the increment between elements in the sequence
595
   *
596
   * @return Arrayy (Immutable) Returns an new instance of the Arrayy object.
597
   */
598 1
  public static function createWithRange($low, $high, $step = 1)
599
  {
600 1
    return static::create(range($low, $high, $step));
601
  }
602
603
  /**
604
   * Custom sort by index via "uksort".
605
   *
606
   * @link http://php.net/manual/en/function.uksort.php
607
   *
608
   * @param callable $function
609
   *
610
   * @return self (Mutable) Return this Arrayy object.
611
   */
612 5
  public function customSortKeys($function)
613
  {
614 5
    uksort($this->array, $function);
615
616 5
    return $this;
617
  }
618
619
  /**
620
   * Custom sort by value via "usort".
621
   *
622
   * @link http://php.net/manual/en/function.usort.php
623
   *
624
   * @param callable $function
625
   *
626
   * @return self (Mutable) Return this Arrayy object.
627
   */
628 4
  public function customSortValues($function)
629
  {
630 4
    usort($this->array, $function);
631
632 4
    return $this;
633
  }
634
635
  /**
636
   * Return values that are only in the current array.
637
   *
638
   * @param array $array
639
   *
640
   * @return Arrayy (Immutable)
641
   */
642 12
  public function diff(array $array = array())
643
  {
644 12
    $result = array_diff($this->array, $array);
645
646 12
    return static::create($result);
647
  }
648
649
  /**
650
   * Return values that are only in the current multi-dimensional array.
651
   *
652
   * @param array      $array
653
   * @param null|array $helperVariableForRecursion (only for internal usage)
654
   *
655
   * @return Arrayy (Immutable)
656
   */
657 1
  public function diffRecursive(array $array = array(), $helperVariableForRecursion = null)
658
  {
659 1
    $result = array();
660
661 1
    if ($helperVariableForRecursion !== null && is_array($helperVariableForRecursion) === true) {
662 1
      $arrayForTheLoop = $helperVariableForRecursion;
663
    } else {
664 1
      $arrayForTheLoop = $this->array;
665
    }
666
667 1
    foreach ($arrayForTheLoop as $key => $value) {
668 1
      if (array_key_exists($key, $array)) {
669 1
        if (is_array($value)) {
670 1
          $recursiveDiff = $this->diffRecursive($array[$key], $value);
671 1
          if (!empty($recursiveDiff)) {
672 1
            $result[$key] = $recursiveDiff;
673
          }
674
        } else {
675 1
          if ($value != $array[$key]) {
676 1
            $result[$key] = $value;
677
          }
678
        }
679
      } else {
680 1
        $result[$key] = $value;
681
      }
682
    }
683
684 1
    return static::create($result);
685
  }
686
687
  /**
688
   * Return values that are only in the new $array.
689
   *
690
   * @param array $array
691
   *
692
   * @return Arrayy (Immutable)
693
   */
694 8
  public function diffReverse(array $array = array())
695
  {
696 8
    $result = array_diff($array, $this->array);
697
698 8
    return static::create($result);
699
  }
700
701
  /**
702
   * Divide an array into two arrays. One with keys and the other with values.
703
   *
704
   * @return Arrayy (Immutable)
705
   */
706 1
  public function divide()
707
  {
708 1
    return static::create(
709
        array(
710 1
            $this->keys(),
711 1
            $this->values(),
712
        )
713
    );
714
  }
715
716
  /**
717
   * Iterate over the current array and modify the array's value.
718
   *
719
   * @param \Closure $closure
720
   *
721
   * @return Arrayy (Immutable)
722
   */
723 22 View Code Duplication
  public function each(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
724
  {
725 22
    $array = $this->array;
726
727 22
    foreach ($array as $key => &$value) {
728 18
      $value = $closure($value, $key);
729
    }
730
731 22
    return static::create($array);
732
  }
733
734
  /**
735
   * Check if a value is in the current array using a closure.
736
   *
737
   * @param \Closure $closure
738
   *
739
   * @return bool Returns true if the given value is found, false otherwise
740
   */
741 4
  public function exists(\Closure $closure)
742
  {
743 4
    $isExists = false;
744 4
    foreach ($this->array as $key => $value) {
745 3
      if ($closure($value, $key)) {
746 1
        $isExists = true;
747 3
        break;
748
      }
749
    }
750
751 4
    return $isExists;
752
  }
753
754
  /**
755
   * create a fallback for array
756
   *
757
   * 1. use the current array, if it's a array
758
   * 2. call "getArray()" on object, if there is a "Arrayy"-object
759
   * 3. fallback to empty array, if there is nothing
760
   * 4. call "createFromObject()" on object, if there is a "\ArrayAccess"-object
761
   * 5. call "__toArray()" on object, if the method exists
762
   * 6. cast a string or object with "__toString()" into an array
763
   * 7. throw a "InvalidArgumentException"-Exception
764
   *
765
   * @param $array
766
   *
767
   * @return array
768
   *
769
   * @throws \InvalidArgumentException
770
   */
771 728
  protected function fallbackForArray(&$array)
772
  {
773 728
    if (is_array($array)) {
774 725
      return $array;
775
    }
776
777 9
    if ($array instanceof self) {
778
      return $array->getArray();
779
    }
780
781 9
    if (!$array) {
782 6
      return array();
783
    }
784
785 8
    if ($array instanceof \ArrayAccess) {
786
      /** @noinspection ReferenceMismatchInspection */
787
      return self::createFromObject($array)->getArray();
788
    }
789
790 8
    if (is_object($array) && method_exists($array, '__toArray')) {
791
      return (array)$array->__toArray();
792
    }
793
794
    /** @noinspection ReferenceMismatchInspection */
795
    if (
796 8
        is_string($array)
797
        ||
798 8
        (is_object($array) && method_exists($array, '__toString'))
799
    ) {
800 6
      return (array)$array;
801
    }
802
803 2
    throw new \InvalidArgumentException(
804 2
        'Passed value should be a array'
805
    );
806
  }
807
808
  /**
809
   * Find all items in an array that pass the truth test.
810
   *
811
   * @param \Closure|null $closure
812
   *
813
   * @return Arrayy (Immutable)
814
   */
815 9
  public function filter($closure = null)
816
  {
817 9
    if (!$closure) {
818 1
      return $this->clean();
819
    }
820
821 9
    $array = array_filter($this->array, $closure);
822
823 9
    return static::create($array);
824
  }
825
826
  /**
827
   * Filters an array of objects (or a numeric array of associative arrays) based on the value of a particular property
828
   * within that.
829
   *
830
   * @param        $property
831
   * @param        $value
832
   * @param string $comparisonOp
833
   *                            'eq' (equals),<br />
834
   *                            'gt' (greater),<br />
835
   *                            'gte' || 'ge' (greater or equals),<br />
836
   *                            'lt' (less),<br />
837
   *                            'lte' || 'le' (less or equals),<br />
838
   *                            'ne' (not equals),<br />
839
   *                            'contains',<br />
840
   *                            'notContains',<br />
841
   *                            'newer' (via strtotime),<br />
842
   *                            'older' (via strtotime),<br />
843
   *
844
   * @return Arrayy (Immutable)
845
   */
846 1
  public function filterBy($property, $value, $comparisonOp = null)
847
  {
848 1
    if (!$comparisonOp) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $comparisonOp of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
849 1
      $comparisonOp = is_array($value) ? 'contains' : 'eq';
850
    }
851
852
    $ops = array(
853
        'eq'          => function ($item, $prop, $value) {
854 1
          return $item[$prop] === $value;
855 1
        },
856
        'gt'          => function ($item, $prop, $value) {
857
          return $item[$prop] > $value;
858 1
        },
859
        'ge'          => function ($item, $prop, $value) {
860
          return $item[$prop] >= $value;
861 1
        },
862
        'gte'         => function ($item, $prop, $value) {
863
          return $item[$prop] >= $value;
864 1
        },
865
        'lt'          => function ($item, $prop, $value) {
866 1
          return $item[$prop] < $value;
867 1
        },
868
        'le'          => function ($item, $prop, $value) {
869
          return $item[$prop] <= $value;
870 1
        },
871
        'lte'         => function ($item, $prop, $value) {
872
          return $item[$prop] <= $value;
873 1
        },
874
        'ne'          => function ($item, $prop, $value) {
875
          return $item[$prop] !== $value;
876 1
        },
877
        'contains'    => function ($item, $prop, $value) {
878 1
          return in_array($item[$prop], (array)$value, true);
879 1
        },
880
        'notContains' => function ($item, $prop, $value) {
881
          return !in_array($item[$prop], (array)$value, true);
882 1
        },
883
        'newer'       => function ($item, $prop, $value) {
884
          return strtotime($item[$prop]) > strtotime($value);
885 1
        },
886
        'older'       => function ($item, $prop, $value) {
887
          return strtotime($item[$prop]) < strtotime($value);
888 1
        },
889
    );
890
891 1
    $result = array_values(
892
        array_filter(
893 1
            (array)$this->array,
894
            function ($item) use (
895 1
                $property,
896 1
                $value,
897 1
                $ops,
898 1
                $comparisonOp
899
            ) {
900 1
              $item = (array)$item;
901 1
              $itemArrayy = new Arrayy($item);
902 1
              $item[$property] = $itemArrayy->get($property, array());
903
904 1
              return $ops[$comparisonOp]($item, $property, $value);
905 1
            }
906
        )
907
    );
908
909 1
    return static::create($result);
910
  }
911
912
  /**
913
   * Find the first item in an array that passes the truth test,
914
   *  otherwise return false
915
   *
916
   * @param \Closure $closure
917
   *
918
   * @return mixed|false false if we did not find the value
919
   */
920 8
  public function find(\Closure $closure)
921
  {
922 8
    foreach ($this->array as $key => $value) {
923 6
      if ($closure($value, $key)) {
924 6
        return $value;
925
      }
926
    }
927
928 3
    return false;
929
  }
930
931
  /**
932
   * find by ...
933
   *
934
   * @param        $property
935
   * @param        $value
936
   * @param string $comparisonOp
937
   *
938
   * @return Arrayy (Immutable)
939
   */
940
  public function findBy($property, $value, $comparisonOp = 'eq')
941
  {
942
    return $this->filterBy($property, $value, $comparisonOp);
943
  }
944
945
  /**
946
   * Get the first value from the current array.
947
   *
948
   * @return mixed Return null if there wasn't a element.
949
   */
950 13
  public function first()
951
  {
952 13
    $tmpArray = $this->array;
953 13
    $result = array_shift($tmpArray);
954
955 13
    if (null === $result) {
956 3
      return null;
957
    } else {
958 10
      return $result;
959
    }
960
  }
961
962
  /**
963
   * Get the first value(s) from the current array.
964
   *
965
   * @param int|null $number how many values you will take?
966
   *
967
   * @return Arrayy (Immutable)
968
   */
969 28
  public function firstsImmutable($number = null)
970
  {
971 28
    if ($number === null) {
972 7
      $arrayTmp = $this->array;
973 7
      $array = (array)array_shift($arrayTmp);
974
    } else {
975 21
      $number = (int)$number;
976 21
      $arrayTmp = $this->array;
977 21
      $array = array_splice($arrayTmp, 0, $number, true);
978
    }
979
980 28
    return static::create($array);
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 self (Mutable)
989
   */
990 26
  public function firstsMutable($number = null)
991
  {
992 26
    if ($number === null) {
993 11
      $this->array = (array)array_shift($this->array);
994
    } else {
995 15
      $number = (int)$number;
996 15
      $this->array = array_splice($this->array, 0, $number, true);
997
    }
998
999 26
    return $this;
1000
  }
1001
1002
  /**
1003
   * Exchanges all keys with their associated values in an array.
1004
   *
1005
   * @return Arrayy (Immutable)
1006
   */
1007 1
  public function flip()
1008
  {
1009 1
    $result = array_flip($this->array);
1010
1011 1
    return static::create($result);
1012
  }
1013
1014
  /**
1015
   * Get a value from an array (optional using dot-notation).
1016
   *
1017
   * @param string $key     The key to look for.
1018
   * @param mixed  $default Default value to fallback to.
1019
   * @param array  $array   The array to get from, if it's set to "null" we use the current array from the class.
1020
   *
1021
   * @return mixed
1022
   */
1023 54
  public function get($key, $default = null, &$array = null)
1024
  {
1025 54
    if (is_array($array) === true) {
1026 3
      $usedArray = &$array;
1027
    } else {
1028 52
      $usedArray = &$this->array;
1029
    }
1030
1031 54
    if (null === $key) {
1032 1
      return $usedArray;
1033
    }
1034
1035 54
    if (isset($usedArray[$key])) {
1036 42
      return $usedArray[$key];
1037
    }
1038
1039
    // Crawl through array, get key according to object or not
1040 20
    foreach (explode($this->pathSeparator, $key) as $segment) {
1041 20
      if (!isset($usedArray[$segment])) {
1042 17
        return $default instanceof \Closure ? $default() : $default;
1043
      }
1044
1045 3
      $usedArray = $usedArray[$segment];
1046
    }
1047
1048 3
    return $usedArray;
1049
  }
1050
1051
  /**
1052
   * Get the current array from the "Arrayy"-object.
1053
   *
1054
   * @return array
1055
   */
1056 481
  public function getArray()
1057
  {
1058 481
    return $this->array;
1059
  }
1060
1061
  /**
1062
   * Returns the values from a single column of the input array, identified by
1063
   * the $columnKey, can be used to extract data-columns from multi-arrays.
1064
   *
1065
   * Info: Optionally, you may provide an $indexKey to index the values in the returned
1066
   * array by the values from the $indexKey column in the input array.
1067
   *
1068
   * @param mixed $columnKey
1069
   * @param mixed $indexKey
1070
   *
1071
   * @return Arrayy (Immutable)
1072
   */
1073 1
  public function getColumn($columnKey = null, $indexKey = null)
1074
  {
1075 1
    $result = array_column($this->array, $columnKey, $indexKey);
1076
1077 1
    return static::create($result);
1078
  }
1079
1080
  /**
1081
   * Get correct PHP constant for direction.
1082
   *
1083
   * @param int|string $direction
1084
   *
1085
   * @return int
1086
   */
1087 38
  protected function getDirection($direction)
1088
  {
1089 38
    if (is_string($direction)) {
1090 10
      $direction = strtolower($direction);
1091
1092 10
      if ($direction === 'desc') {
1093 2
        $direction = SORT_DESC;
1094
      } else {
1095 8
        $direction = SORT_ASC;
1096
      }
1097
    }
1098
1099
    if (
1100 38
        $direction !== SORT_DESC
1101
        &&
1102 38
        $direction !== SORT_ASC
1103
    ) {
1104
      $direction = SORT_ASC;
1105
    }
1106
1107 38
    return $direction;
1108
  }
1109
1110
  /**
1111
   * alias: for "Arrayy->keys()"
1112
   *
1113
   * @see Arrayy::keys()
1114
   *
1115
   * @return Arrayy (Immutable)
1116
   */
1117 1
  public function getKeys()
1118
  {
1119 1
    return $this->keys();
1120
  }
1121
1122
  /**
1123
   * alias: for "Arrayy->randomImmutable()"
1124
   *
1125
   * @see Arrayy::randomImmutable()
1126
   *
1127
   * @return Arrayy (Immutable)
1128
   */
1129 3
  public function getRandom()
1130
  {
1131 3
    return $this->randomImmutable();
1132
  }
1133
1134
  /**
1135
   * alias: for "Arrayy->randomKey()"
1136
   *
1137
   * @see Arrayy::randomKey()
1138
   *
1139
   * @return mixed get a key/index or null if there wasn't a key/index
1140
   */
1141 3
  public function getRandomKey()
1142
  {
1143 3
    return $this->randomKey();
1144
  }
1145
1146
  /**
1147
   * alias: for "Arrayy->randomKeys()"
1148
   *
1149
   * @see Arrayy::randomKeys()
1150
   *
1151
   * @param int $number
1152
   *
1153
   * @return Arrayy (Immutable)
1154
   */
1155 9
  public function getRandomKeys($number)
1156
  {
1157 9
    return $this->randomKeys($number);
1158
  }
1159
1160
  /**
1161
   * alias: for "Arrayy->randomValue()"
1162
   *
1163
   * @see Arrayy::randomValue()
1164
   *
1165
   * @return mixed get a random value or null if there wasn't a value
1166
   */
1167 3
  public function getRandomValue()
1168
  {
1169 3
    return $this->randomValue();
1170
  }
1171
1172
  /**
1173
   * alias: for "Arrayy->randomValues()"
1174
   *
1175
   * @see Arrayy::randomValues()
1176
   *
1177
   * @param int $number
1178
   *
1179
   * @return Arrayy (Immutable)
1180
   */
1181 6
  public function getRandomValues($number)
1182
  {
1183 6
    return $this->randomValues($number);
1184
  }
1185
1186
  /**
1187
   * Group values from a array according to the results of a closure.
1188
   *
1189
   * @param string $grouper a callable function name
1190
   * @param bool   $saveKeys
1191
   *
1192
   * @return Arrayy (Immutable)
1193
   */
1194 3
  public function group($grouper, $saveKeys = false)
1195
  {
1196 3
    $array = (array)$this->array;
1197 3
    $result = array();
1198
1199
    // Iterate over values, group by property/results from closure
1200 3
    foreach ($array as $key => $value) {
1201 3
      $groupKey = is_callable($grouper) ? $grouper($value, $key) : $this->get($grouper, null, $value);
1202 3
      $newValue = $this->get($groupKey, null, $result);
1203
1204
      // Add to results
1205 3
      if ($groupKey !== null) {
1206 2
        if ($saveKeys) {
1207 1
          $result[$groupKey] = $newValue;
1208 1
          $result[$groupKey][$key] = $value;
1209
        } else {
1210 1
          $result[$groupKey] = $newValue;
1211 3
          $result[$groupKey][] = $value;
1212
        }
1213
      }
1214
1215
    }
1216
1217 3
    return static::create($result);
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type null; however, Arrayy\Arrayy::create() does only seem to accept array, maybe add an additional type check?

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

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

    return array();
}

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

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

Loading history...
1218
  }
1219
1220
  /**
1221
   * Check if an array has a given key.
1222
   *
1223
   * @param mixed $key
1224
   *
1225
   * @return bool
1226
   */
1227 19
  public function has($key)
1228
  {
1229
    // Generate unique string to use as marker.
1230 19
    $unFound = (string)uniqid('arrayy', true);
1231
1232 19
    return $this->get($key, $unFound) !== $unFound;
1233
  }
1234
1235
  /**
1236
   * Implodes an array.
1237
   *
1238
   * @param string $with What to implode it with
1239
   *
1240
   * @return string
1241
   */
1242 27
  public function implode($with = '')
1243
  {
1244 27
    return implode($with, $this->array);
1245
  }
1246
1247
  /**
1248
   * Given a list and an iterate-function that returns
1249
   * a key for each element in the list (or a property name),
1250
   * returns an object with an index of each item.
1251
   *
1252
   * Just like groupBy, but for when you know your keys are unique.
1253
   *
1254
   * @param mixed $key
1255
   *
1256
   * @return Arrayy (Immutable)
1257
   */
1258 3
  public function indexBy($key)
1259
  {
1260 3
    $results = array();
1261
1262 3
    foreach ($this->array as $a) {
1263 3
      if (isset($a[$key])) {
1264 3
        $results[$a[$key]] = $a;
1265
      }
1266
    }
1267
1268 3
    return static::create($results);
1269
  }
1270
1271
  /**
1272
   * alias: for "Arrayy->searchIndex()"
1273
   *
1274
   * @see Arrayy::searchIndex()
1275
   *
1276
   * @param mixed $value Value to search for
1277
   *
1278
   * @return mixed
1279
   */
1280 4
  public function indexOf($value)
1281
  {
1282 4
    return $this->searchIndex($value);
1283
  }
1284
1285
  /**
1286
   * Get everything but the last..$to items.
1287
   *
1288
   * @param int $to
1289
   *
1290
   * @return Arrayy (Immutable)
1291
   */
1292 12
  public function initial($to = 1)
1293
  {
1294 12
    $slice = count($this->array) - $to;
1295
1296 12
    return $this->firstsImmutable($slice);
1297
  }
1298
1299
  /**
1300
   * Internal mechanics of remove method.
1301
   *
1302
   * @param $key
1303
   *
1304
   * @return boolean
1305
   */
1306 18
  protected function internalRemove($key)
1307
  {
1308 18
    $path = explode($this->pathSeparator, $key);
1309
1310
    // Crawl though the keys
1311 18
    while (count($path) > 1) {
1312
      $key = array_shift($path);
1313
1314
      if (!$this->has($key)) {
1315
        return false;
1316
      }
1317
1318
      $this->array = &$this->array[$key];
1319
    }
1320
1321 18
    $key = array_shift($path);
1322
1323 18
    unset($this->array[$key]);
1324
1325 18
    return true;
1326
  }
1327
1328
  /**
1329
   * Internal mechanic of set method.
1330
   *
1331
   * @param string $key
1332
   * @param mixed  $value
1333
   *
1334
   * @return bool
1335
   */
1336 27
  protected function internalSet($key, $value)
1337
  {
1338 27
    if (null === $key) {
1339
      return false;
1340
    }
1341
1342
    // init
1343 27
    $array = &$this->array;
1344 27
    $path = explode($this->pathSeparator, $key);
1345
1346
    // Crawl through the keys
1347 27
    while (count($path) > 1) {
1348 2
      $key = array_shift($path);
1349
      // If the key doesn't exist at this depth, we will just create an empty array
1350
      // to hold the next value, allowing us to create the arrays to hold final
1351
      // values at the correct depth. Then we'll keep digging into the array.
1352 2
      if (!isset($array[$key]) || !is_array($array[$key])) {
1353
        $array[$key] = array();
1354
      }
1355 2
      $array = &$array[$key];
1356
    }
1357
1358 27
    $array[array_shift($path)] = $value;
1359
1360 27
    return true;
1361
  }
1362
1363
  /**
1364
   * Return an array with all elements found in input array.
1365
   *
1366
   * @param array $search
1367
   *
1368
   * @return Arrayy (Immutable)
1369
   */
1370 2
  public function intersection(array $search)
1371
  {
1372 2
    return static::create(array_values(array_intersect($this->array, $search)));
1373
  }
1374
1375
  /**
1376
   * Return a boolean flag which indicates whether the two input arrays have any common elements.
1377
   *
1378
   * @param array $search
1379
   *
1380
   * @return bool
1381
   */
1382 1
  public function intersects(array $search)
1383
  {
1384 1
    return count($this->intersection($search)->array) > 0;
1385
  }
1386
1387
  /**
1388
   * Invoke a function on all of an array's values.
1389
   *
1390
   * @param mixed $callable
1391
   * @param mixed $arguments
1392
   *
1393
   * @return Arrayy (Immutable)
1394
   */
1395 1
  public function invoke($callable, $arguments = array())
1396
  {
1397
    // If one argument given for each iteration, create an array for it.
1398 1
    if (!is_array($arguments)) {
1399 1
      $arguments = StaticArrayy::repeat($arguments, count($this->array))->getArray();
1400
    }
1401
1402
    // If the callable has arguments, pass them.
1403 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...
1404 1
      $array = array_map($callable, $this->array, $arguments);
1405
    } else {
1406 1
      $array = array_map($callable, $this->array);
1407
    }
1408
1409 1
    return static::create($array);
1410
  }
1411
1412
  /**
1413
   * Check whether array is associative or not.
1414
   *
1415
   * @return bool Returns true if associative, false otherwise
1416
   */
1417 15
  public function isAssoc()
1418
  {
1419 15
    if ($this->isEmpty()) {
1420 3
      return false;
1421
    }
1422
1423 13
    foreach ($this->keys()->getArray() as $key) {
1424 13
      if (!is_string($key)) {
1425 13
        return false;
1426
      }
1427
    }
1428
1429 3
    return true;
1430
  }
1431
1432
  /**
1433
   * Check whether the array is empty or not.
1434
   *
1435
   * @return bool Returns true if empty, false otherwise
1436
   */
1437 25
  public function isEmpty()
1438
  {
1439 25
    return !$this->array;
1440
  }
1441
1442
  /**
1443
   * Check if the current array is equal to the given "$array" or not.
1444
   *
1445
   * @param array $array
1446
   *
1447
   * @return bool
1448
   */
1449
  public function isEqual(array $array)
1450
  {
1451
    return ($this->array === $array);
1452
  }
1453
1454
  /**
1455
   * Check if the current array is a multi-array.
1456
   *
1457
   * @return bool
1458
   */
1459 14
  public function isMultiArray()
1460
  {
1461 14
    return !(count($this->array) === count($this->array, COUNT_RECURSIVE));
1462
  }
1463
1464
  /**
1465
   * Check whether array is numeric or not.
1466
   *
1467
   * @return bool Returns true if numeric, false otherwise
1468
   */
1469 5
  public function isNumeric()
1470
  {
1471 5
    if ($this->isEmpty()) {
1472 2
      return false;
1473
    }
1474
1475 4
    foreach ($this->keys() as $key) {
1476 4
      if (!is_int($key)) {
1477 4
        return false;
1478
      }
1479
    }
1480
1481 2
    return true;
1482
  }
1483
1484
  /**
1485
   * Check if the current array is sequential [0, 1, 2, 3, 4, 5 ...] or not.
1486
   *
1487
   * @return bool
1488
   */
1489 1
  public function isSequential()
1490
  {
1491 1
    return array_keys($this->array) === range(0, count($this->array) - 1);
1492
  }
1493
1494
  /**
1495
   * Get all keys from the current array.
1496
   *
1497
   * @return Arrayy (Immutable)
1498
   */
1499 25
  public function keys()
1500
  {
1501 25
    return static::create(array_keys($this->array));
1502
  }
1503
1504
  /**
1505
   * Get the last value from the current array.
1506
   *
1507
   * @return mixed Return null if there wasn't a element.
1508
   */
1509 4
  public function last()
1510
  {
1511 4
    $result = $this->pop();
1512
1513 4
    if (null === $result) {
1514 1
      return null;
1515
    } else {
1516 3
      return $result;
1517
    }
1518
  }
1519
1520
  /**
1521
   * Get the last value(s) from the current array.
1522
   *
1523
   * @param int|null $number
1524
   *
1525
   * @return Arrayy (Immutable)
1526
   */
1527 12
  public function lastsImmutable($number = null)
1528
  {
1529 12
    if ($number === null) {
1530 8
      $poppedValue = (array)$this->pop();
1531 8
      $arrayy = static::create($poppedValue);
1532
    } else {
1533 4
      $number = (int)$number;
1534 4
      $arrayy = $this->rest(-$number);
1535
    }
1536
1537 12
    return $arrayy;
1538
  }
1539
1540
  /**
1541
   * Get the last value(s) from the current array.
1542
   *
1543
   * @param int|null $number
1544
   *
1545
   * @return self (Mutable)
1546
   */
1547 12
  public function lastsMutable($number = null)
1548
  {
1549 12
    if ($number === null) {
1550 8
      $poppedValue = (array)$this->pop();
1551 8
      $this->array = static::create($poppedValue)->array;
1552
    } else {
1553 4
      $number = (int)$number;
1554 4
      $this->array = $this->rest(-$number)->array;
1555
    }
1556
1557 12
    return $this;
1558
  }
1559
1560
  /**
1561
   * Count the values from the current array.
1562
   *
1563
   * alias: for "Arrayy->size()"
1564
   *
1565
   * @see Arrayy::size()
1566
   *
1567
   * @return int
1568
   */
1569 10
  public function length()
1570
  {
1571 10
    return $this->size();
1572
  }
1573
1574
  /**
1575
   * Apply the given function to the every element of the array,
1576
   * collecting the results.
1577
   *
1578
   * @param callable $callable
1579
   *
1580
   * @return Arrayy (Immutable) Arrayy object with modified elements
1581
   */
1582 4
  public function map($callable)
1583
  {
1584 4
    $result = array_map($callable, $this->array);
1585
1586 4
    return static::create($result);
1587
  }
1588
1589
  /**
1590
   * Check if all items in current array match a truth test.
1591
   *
1592
   * @param \Closure $closure
1593
   *
1594
   * @return bool
1595
   */
1596 9 View Code Duplication
  public function matches(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1597
  {
1598
    // Reduce the array to only booleans
1599 9
    $array = $this->each($closure);
1600
1601
    // Check the results
1602 9
    if (count($array) === 0) {
1603 2
      return true;
1604
    }
1605
1606 7
    $array = array_search(false, $array->toArray(), false);
1607
1608 7
    return is_bool($array);
1609
  }
1610
1611
  /**
1612
   * Check if any item in the current array matches a truth test.
1613
   *
1614
   * @param \Closure $closure
1615
   *
1616
   * @return bool
1617
   */
1618 9 View Code Duplication
  public function matchesAny(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1619
  {
1620
    // Reduce the array to only booleans
1621 9
    $array = $this->each($closure);
1622
1623
    // Check the results
1624 9
    if (count($array) === 0) {
1625 2
      return true;
1626
    }
1627
1628 7
    $array = array_search(true, $array->toArray(), false);
1629
1630 7
    return is_int($array);
1631
  }
1632
1633
  /**
1634
   * Get the max value from an array.
1635
   *
1636
   * @return mixed
1637
   */
1638 10
  public function max()
1639
  {
1640 10
    if ($this->count() === 0) {
1641 1
      return false;
1642
    }
1643
1644 9
    return max($this->array);
1645
  }
1646
1647
  /**
1648
   * Merge the new $array into the current array.
1649
   *
1650
   * - keep key,value from the current array, also if the index is in the new $array
1651
   *
1652
   * @param array $array
1653
   * @param bool  $recursive
1654
   *
1655
   * @return Arrayy (Immutable)
1656
   */
1657 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...
1658
  {
1659 25
    if (true === $recursive) {
1660 4
      $result = array_replace_recursive($this->array, $array);
1661
    } else {
1662 21
      $result = array_replace($this->array, $array);
1663
    }
1664
1665 25
    return static::create($result);
1666
  }
1667
1668
  /**
1669
   * Merge the new $array into the current array.
1670
   *
1671
   * - replace duplicate assoc-keys from the current array with the key,values from the new $array
1672
   * - create new indexes
1673
   *
1674
   * @param array $array
1675
   * @param bool  $recursive
1676
   *
1677
   * @return Arrayy (Immutable)
1678
   */
1679 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...
1680
  {
1681 16
    if (true === $recursive) {
1682 4
      $result = array_merge_recursive($this->array, $array);
1683
    } else {
1684 12
      $result = array_merge($this->array, $array);
1685
    }
1686
1687 16
    return static::create($result);
1688
  }
1689
1690
  /**
1691
   * Merge the the current array into the $array.
1692
   *
1693
   * - use key,value from the new $array, also if the index is in the current array
1694
   *
1695
   * @param array $array
1696
   * @param bool  $recursive
1697
   *
1698
   * @return Arrayy (Immutable)
1699
   */
1700 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...
1701
  {
1702 16
    if (true === $recursive) {
1703 4
      $result = array_replace_recursive($array, $this->array);
1704
    } else {
1705 12
      $result = array_replace($array, $this->array);
1706
    }
1707
1708 16
    return static::create($result);
1709
  }
1710
1711
  /**
1712
   * Merge the current array into the new $array.
1713
   *
1714
   * - replace duplicate assoc-keys from new $array with the key,values from the current array
1715
   * - create new indexes
1716
   *
1717
   * @param array $array
1718
   * @param bool  $recursive
1719
   *
1720
   * @return Arrayy (Immutable)
1721
   */
1722 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...
1723
  {
1724 16
    if (true === $recursive) {
1725 4
      $result = array_merge_recursive($array, $this->array);
1726
    } else {
1727 12
      $result = array_merge($array, $this->array);
1728
    }
1729
1730 16
    return static::create($result);
1731
  }
1732
1733
  /**
1734
   * Get the min value from an array.
1735
   *
1736
   * @return mixed
1737
   */
1738 10
  public function min()
1739
  {
1740 10
    if ($this->count() === 0) {
1741 1
      return false;
1742
    }
1743
1744 9
    return min($this->array);
1745
  }
1746
1747
  /**
1748
   * Get a subset of the items from the given array.
1749
   *
1750
   * @param mixed[] $keys
1751
   *
1752
   * @return Arrayy (Immutable)
1753
   */
1754
  public function only(array $keys)
1755
  {
1756
    $array = $this->array;
1757
1758
    return static::create(array_intersect_key($array, array_flip($keys)));
1759
  }
1760
1761
  /**
1762
   * Pad array to the specified size with a given value.
1763
   *
1764
   * @param int   $size  Size of the result array
1765
   * @param mixed $value Empty value by default
1766
   *
1767
   * @return Arrayy (Immutable) Arrayy object padded to $size with $value
1768
   */
1769 4
  public function pad($size, $value)
1770
  {
1771 4
    $result = array_pad($this->array, $size, $value);
1772
1773 4
    return static::create($result);
1774
  }
1775
1776
  /**
1777
   * Pop a specified value off the end of the current array.
1778
   *
1779
   * @return mixed The popped element from the current array. (Mutable)
1780
   */
1781 16
  public function pop()
1782
  {
1783 16
    return array_pop($this->array);
1784
  }
1785
1786
  /**
1787
   * Prepend a value to the current array.
1788
   *
1789
   * @param mixed $value
1790
   * @param mixed $key
1791
   *
1792
   * @return self (Mutable) Return this Arrayy object, with the prepended value.
1793
   */
1794 8
  public function prepend($value, $key = null)
1795
  {
1796 8
    if ($key === null) {
1797 8
      array_unshift($this->array, $value);
1798
    } else {
1799
      /** @noinspection AdditionOperationOnArraysInspection */
1800 1
      $this->array = array($key => $value) + $this->array;
1801
    }
1802
1803 8
    return $this;
1804
  }
1805
1806
  /**
1807
   * Push one or more values onto the end of array at once.
1808
   *
1809
   * @return self (Mutable) Return this Arrayy object, with pushed elements to the end of array.
1810
   */
1811 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...
1812
  {
1813 4
    if (func_num_args()) {
1814 4
      $args = array_merge(array(&$this->array), func_get_args());
1815 4
      call_user_func_array('array_push', $args);
1816
    }
1817
1818 4
    return $this;
1819
  }
1820
1821
  /**
1822
   * Get a random value from the current array.
1823
   *
1824
   * @param null|int $number how many values you will take?
1825
   *
1826
   * @return Arrayy (Immutable)
1827
   */
1828 17
  public function randomImmutable($number = null)
1829
  {
1830 17
    if ($this->count() === 0) {
1831
      return static::create();
1832
    }
1833
1834 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...
1835 14
      $arrayRandValue = (array)$this->array[array_rand($this->array)];
1836
1837 14
      return static::create($arrayRandValue);
1838
    }
1839
1840 5
    $arrayTmp = $this->array;
1841 5
    shuffle($arrayTmp);
1842
1843 5
    return self::create($arrayTmp)->firstsImmutable($number);
1844
  }
1845
1846
  /**
1847
   * Pick a random key/index from the keys of this array.
1848
   *
1849
   *
1850
   * @return mixed get a key/index or null if there wasn't a key/index
1851
   *
1852
   * @throws \RangeException If array is empty
1853
   */
1854 4
  public function randomKey()
1855
  {
1856 4
    $result = $this->randomKeys(1);
1857
1858 4
    if (!isset($result[0])) {
1859
      $result[0] = null;
1860
    }
1861
1862 4
    return $result[0];
1863
  }
1864
1865
  /**
1866
   * Pick a given number of random keys/indexes out of this array.
1867
   *
1868
   * @param int $number The number of keys/indexes (should be <= $this->count())
1869
   *
1870
   * @return Arrayy (Immutable)
1871
   *
1872
   * @throws \RangeException If array is empty
1873
   */
1874 14
  public function randomKeys($number)
1875
  {
1876 14
    $number = (int)$number;
1877 14
    $count = $this->count();
1878
1879 14
    if ($number === 0 || $number > $count) {
1880 3
      throw new \RangeException(
1881
          sprintf(
1882 3
              'Number of requested keys (%s) must be equal or lower than number of elements in this array (%s)',
1883
              $number,
1884
              $count
1885
          )
1886
      );
1887
    }
1888
1889 11
    $result = (array)array_rand($this->array, $number);
1890
1891 11
    return static::create($result);
1892
  }
1893
1894
  /**
1895
   * Get a random value from the current array.
1896
   *
1897
   * @param null|int $number how many values you will take?
1898
   *
1899
   * @return Arrayy (Mutable)
1900
   */
1901 16
  public function randomMutable($number = null)
1902
  {
1903 16
    if ($this->count() === 0) {
1904
      return static::create();
1905
    }
1906
1907 16 View Code Duplication
    if ($number === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

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

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

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

Loading history...
2665
  {
2666 4
    if (func_num_args()) {
2667 4
      $args = array_merge(array(&$this->array), func_get_args());
2668 4
      call_user_func_array('array_unshift', $args);
2669
    }
2670
2671 4
    return $this;
2672
  }
2673
2674
  /**
2675
   * Get all values from a array.
2676
   *
2677
   * @return Arrayy (Immutable)
2678
   */
2679 2
  public function values()
2680
  {
2681 2
    return static::create(array_values((array)$this->array));
2682
  }
2683
2684
  /**
2685
   * Apply the given function to every element in the array, discarding the results.
2686
   *
2687
   * @param callable $callable
2688
   * @param bool     $recursive Whether array will be walked recursively or no
2689
   *
2690
   * @return self (Mutable) Return this Arrayy object, with modified elements
2691
   */
2692 9
  public function walk($callable, $recursive = false)
2693
  {
2694 9
    if (true === $recursive) {
2695 4
      array_walk_recursive($this->array, $callable);
2696
    } else {
2697 5
      array_walk($this->array, $callable);
2698
    }
2699
2700 9
    return $this;
2701
  }
2702
2703
}
2704