Completed
Push — master ( 07f9b2...639365 )
by Lars
02:28
created

Arrayy::appendToEachValue()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 17
Code Lines 12

Duplication

Lines 17
Ratio 100 %

Code Coverage

Tests 6
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 5
nop 1
dl 17
loc 17
ccs 6
cts 6
cp 1
crap 5
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace Arrayy;
4
5
use voku\helper\Bootup;
6
use voku\helper\UTF8;
7
8
/** @noinspection ClassReImplementsParentInterfaceInspection */
9
10
/**
11
 * Methods to manage arrays.
12
 *
13
 * For the full copyright and license information, please view the LICENSE
14
 * file that was distributed with this source code.
15
 */
16
class Arrayy extends \ArrayObject implements \IteratorAggregate, \ArrayAccess, \Serializable, \Countable
17
{
18
  /**
19
   * @var array
20
   */
21
  protected $array = array();
22
23
  /**
24
   * @var string
25
   */
26
  protected $iteratorClass;
27
28
  /**
29
   * @var string
30
   */
31
  protected $pathSeparator = '.';
32
33
  /** @noinspection MagicMethodsValidityInspection */
34
  /**
35
   * Initializes
36
   *
37
   * @param array  $array
38
   * @param string $iteratorClass
39
   */
40 775
  public function __construct($array = array(), $iteratorClass = '\\Arrayy\\ArrayyIterator')
41
  {
42 775
    $array = $this->fallbackForArray($array);
43 773
    $this->array = $array;
44
45 773
    $this->setIteratorClass($iteratorClass);
46 773
  }
47
48
  /**
49
   * Get a value by key.
50
   *
51
   * @param $key
52
   *
53
   * @return mixed <p>Get a Value from the current array.</p>
54
   */
55 2
  public function &__get($key)
56
  {
57 2
    $return = $this->get($key);
58
59 2
    if (is_array($return)) {
60
      return static::create($return);
61
    }
62
63 2
    return $return;
64
  }
65
66
  /**
67
   * Call object as function.
68
   *
69
   * @param mixed $key
70
   *
71
   * @return mixed
72
   */
73 1
  public function __invoke($key = null)
74
  {
75 1
    if ($key !== null) {
76 1
      if (isset($this->array[$key])) {
77 1
        return $this->array[$key];
78
      }
79
80
      return false;
81
    }
82
83
    return (array)$this->array;
84
  }
85
86
  /**
87
   * Whether or not an element exists by key.
88
   *
89
   * @param mixed $key
90
   *
91
   * @return bool <p>True is the key/index exists, otherwise false.</p>
92
   */
93
  public function __isset($key)
94
  {
95
    return $this->offsetExists($key);
96
  }
97
98
  /**
99
   * Assigns a value to the specified element.
100
   *
101
   * @param mixed $key
102
   * @param mixed $value
103
   */
104 2
  public function __set($key, $value)
105
  {
106 2
    $this->internalSet($key, $value);
107 2
  }
108
109
  /**
110
   * magic to string
111
   *
112
   * @return string
113
   */
114 16
  public function __toString()
115
  {
116 16
    return $this->toString();
117
  }
118
119
  /**
120
   * Unset element by key.
121
   *
122
   * @param mixed $key
123
   */
124
  public function __unset($key)
125
  {
126
    $this->internalRemove($key);
127
  }
128
129
  /**
130
   * alias: for "Arrayy->append()"
131
   *
132
   * @see Arrayy::append()
133
   *
134
   * @param mixed $value
135
   *
136
   * @return static <p>(Mutable) Return this Arrayy object, with the appended values.</p>
137
   */
138 1
  public function add($value)
139
  {
140 1
    return $this->append($value);
141
  }
142
143
  /**
144
   * Append a (key) + value to the current array.
145
   *
146
   * @param mixed $value
147
   * @param mixed $key
148
   *
149
   * @return static <p>(Mutable) Return this Arrayy object, with the appended values.</p>
150 9
   */
151
  public function append($value, $key = null)
152 9
  {
153
    if ($key !== null) {
154 9
      $this->array[$key] = $value;
155
    } else {
156
      $this->array[] = $value;
157
    }
158
159
    return $this;
160
  }
161
162
  /**
163
   * Sort the entries by value.
164
   *
165
   * @param int $sort_flags [optional] <p>
166
   *                        You may modify the behavior of the sort using the optional
167
   *                        parameter sort_flags, for details
168 4
   *                        see sort.
169
   *                        </p>
170 4
   *
171
   * @return static <p>(Mutable) Return this Arrayy object.</p>
172 4
   */
173
  public function asort($sort_flags = null)
174
  {
175
    asort($this->array, $sort_flags);
176
177
    return $this;
178
  }
179
180
  /**
181
   * Count the values from the current array.
182
   *
183
   * alias: for "Arrayy->size()"
184 93
   *
185
   * @see Arrayy::size()
186 93
   *
187
   * @return int
188
   */
189
  public function count()
190
  {
191
    return $this->size();
192
  }
193
194
  /**
195
   * Exchange the array for another one.
196
   *
197
   * @param array|Arrayy $data
198
   *
199
   * @return array
200 1
   */
201
  public function exchangeArray($data)
202 1
  {
203
    $this->array = $this->fallbackForArray($data);
204
205
    return $this->array;
206
  }
207
208
  /**
209
   * Creates a copy of the ArrayyObject.
210
   *
211
   * @return array
212 1
   */
213
  public function getArrayCopy()
214 1
  {
215
    return $this->array;
216 1
  }
217
218
  /**
219
   * Returns a new ArrayyIterator, thus implementing the IteratorAggregate interface.
220
   *
221
   * @return ArrayyIterator <p>An iterator for the values in the array.</p>
222
   */
223
  public function getIterator()
224 1
  {
225
    $iterator = $this->getIteratorClass();
226 1
227
    return new $iterator($this->array);
228
  }
229
230
  /**
231
   * Gets the iterator classname for the ArrayObject.
232
   *
233
   * @return string
234 20
   */
235
  public function getIteratorClass()
236 20
  {
237
    return $this->iteratorClass;
238 20
  }
239
240
  /**
241
   * Sort the entries by key
242
   *
243
   * @param int $sort_flags [optional] <p>
244
   *                        You may modify the behavior of the sort using the optional
245
   *                        parameter sort_flags, for details
246 20
   *                        see sort.
247
   *                        </p>
248 20
   *
249
   * @return static <p>(Mutable) Return this Arrayy object.</p>
250
   */
251
  public function ksort($sort_flags = null)
252
  {
253
    ksort($this->array, $sort_flags);
254
255
    return $this;
256
  }
257
258
  /**
259
   * Sort an array using a case insensitive "natural order" algorithm
260
   *
261
   * @return static <p>(Mutable) Return this Arrayy object.</p>
262 4
   */
263
  public function natcasesort()
264 4
  {
265
    natcasesort($this->array);
266 4
267
    return $this;
268
  }
269
270
  /**
271
   * Sort entries using a "natural order" algorithm
272
   *
273
   * @return static <p>(Mutable) Return this Arrayy object.</p>
274
   */
275
  public function natsort()
276
  {
277
    natsort($this->array);
278
279
    return $this;
280
  }
281
282
  /**
283
   * Whether or not an offset exists.
284
   *
285
   * @param int|float|string $offset
286 1
   *
287
   * @return bool
288 1
   */
289
  public function offsetExists($offset)
290 1
  {
291
    if ($this->isEmpty()) {
292
      return false;
293
    }
294
295
    // php cast "bool"-index into "int"-index
296
    if ((bool)$offset === $offset) {
297
      $offset = (int)$offset;
298
    }
299
300 40
    $tmpReturn = \array_key_exists($offset, $this->array);
301
302 40
    if (
303 4
        $tmpReturn === true
304
        ||
305
        (
306
            $tmpReturn === false
307 36
            &&
308 1
            strpos((string)$offset, $this->pathSeparator) === false
309 1
        )
310
    ) {
311 36
      return $tmpReturn;
312
    }
313
314
    $offsetExists = false;
315 36
316
    if (strpos((string)$offset, $this->pathSeparator) !== false) {
317
318 12
      $offsetExists = false;
319 12
      $explodedPath = explode($this->pathSeparator, (string)$offset);
320 12
      $lastOffset = \array_pop($explodedPath);
321 36
      $containerPath = implode($this->pathSeparator, $explodedPath);
322 34
323
      $this->callAtPath(
324
          $containerPath,
325 3
          function ($container) use ($lastOffset, &$offsetExists) {
326
            $offsetExists = \array_key_exists($lastOffset, $container);
327 3
          }
328
      );
329 3
    }
330 3
331 3
    return $offsetExists;
332 3
  }
333
334 3
  /**
335 3
   * Returns the value at specified offset.
336
   *
337 3
   * @param mixed $offset
338 3
   *
339 3
   * @return mixed <p>Will return null if the offset did not exists.</p>
340 3
   */
341
  public function offsetGet($offset)
342 3
  {
343
    return $this->offsetExists($offset) ? $this->get($offset) : null;
344
  }
345
346
  /**
347
   * Assigns a value to the specified offset.
348
   *
349
   * @param mixed $offset
350
   * @param mixed $value
351
   */
352 26
  public function offsetSet($offset, $value)
353
  {
354 26
    if ($offset === null) {
355
      $this->array[] = $value;
356
    } else {
357
      $this->internalSet($offset, $value);
358
    }
359
  }
360
361
  /**
362
   * Unset an offset.
363 17
   *
364
   * @param mixed $offset
365 17
   */
366 4
  public function offsetUnset($offset)
367 4
  {
368 13
    if ($this->isEmpty()) {
369
      return;
370 17
    }
371
372
    if (\array_key_exists($offset, $this->array)) {
373
      unset($this->array[$offset]);
374
375
      return;
376
    }
377 7
378
    if (strpos((string)$offset, $this->pathSeparator) !== false) {
379 7
380 1
      $path = explode($this->pathSeparator, (string)$offset);
381
      $pathToUnset = \array_pop($path);
382
383 6
      $this->callAtPath(
384 4
          implode($this->pathSeparator, $path),
385
          function (&$offset) use ($pathToUnset) {
386 4
            unset($offset[$pathToUnset]);
387
          }
388
      );
389 3
390
    }
391 2
  }
392 2
393
  /**
394 2
   * Serialize the current "Arrayy"-object.
395 2
   *
396
   * @return string
397 2
   */
398 2
  public function serialize()
399 2
  {
400
    return parent::serialize();
401 2
  }
402 3
403
  /**
404
   * Sets the iterator classname for the current "Arrayy"-object.
405
   *
406
   * @param  string $class
407
   *
408
   * @return void
409 1
   *
410
   * @throws \InvalidArgumentException
411 1
   */
412
  public function setIteratorClass($class)
413
  {
414
    if (class_exists($class)) {
415
      $this->iteratorClass = $class;
416
417
      return;
418
    }
419
420
    if (strpos($class, '\\') === 0) {
421
      $class = '\\' . $class;
422
      if (class_exists($class)) {
423 773
        $this->iteratorClass = $class;
424
425 773
        return;
426 773
      }
427
    }
428 773
429
    throw new \InvalidArgumentException('The iterator class does not exist: ' . $class);
430
  }
431
432
  /**
433
   * Sort the entries with a user-defined comparison function and maintain key association.
434
   *
435
   * @param callable $function
436
   *
437
   * @return static <p>(Mutable) Return this Arrayy object.</p>
438
   *
439
   * @throws \InvalidArgumentException
440
   */
441 View Code Duplication
  public function uasort($function)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
442
  {
443
    if (!is_callable($function)) {
444
      throw new \InvalidArgumentException(
445
          'Passed function must be callable'
446
      );
447
    }
448
449
    uasort($this->array, $function);
450
451
    return $this;
452
  }
453
454
  /**
455
   * Sort the entries by keys using a user-defined comparison function.
456
   *
457
   * @param callable $function
458
   *
459
   * @return static <p>(Mutable) Return this Arrayy object.</p>
460
   *
461
   * @throws \InvalidArgumentException
462
   */
463
  public function uksort($function)
464
  {
465
    return $this->customSortKeys($function);
466
  }
467
468
  /**
469
   * Unserialize an string and return this object.
470
   *
471
   * @param string $string
472
   *
473
   * @return static <p>(Mutable)</p>
474 5
   */
475
  public function unserialize($string)
476 5
  {
477
    parent::unserialize($string);
478
479
    return $this;
480
  }
481
482
  /**
483
   * Add a suffix to each key.
484
   *
485
   * @param string $prefix
486 1
   *
487
   * @return static <p>(Immutable) Return an Arrayy object, with the prefixed keys.</p>
488 1
   */
489 View Code Duplication
  public function appendToEachKey($prefix)
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...
490 1
  {
491
    $result = array();
492
    foreach ($this->array as $key => $item) {
493
      if ($item instanceof self) {
494
        $result[$prefix . $key] = $item->appendToEachKey($prefix);
495
      } else if (is_array($item)) {
496
        $result[$prefix . $key] = self::create($item)->appendToEachKey($prefix)->toArray();
497
      } else {
498 4
        $result[$prefix . $key] = $item;
499
      }
500 4
    }
501
502 4
    return self::create($result);
503
  }
504
505
  /**
506
   * Add a prefix to each value.
507
   *
508
   * @param mixed $prefix
509
   *
510
   * @return static <p>(Immutable) Return an Arrayy object, with the prefixed values.</p>
511
   */
512 2 View Code Duplication
  public function appendToEachValue($prefix)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
513
  {
514 2
    $result = array();
515
    foreach ($this->array as $key => $item) {
516 2
      if ($item instanceof self) {
517 2
        $result[$key] = $item->appendToEachValue($prefix);
518 2
      } else if (is_array($item)) {
519
        $result[$key] = self::create($item)->appendToEachValue($prefix)->toArray();
520 2
      } else if (is_object($item)) {
521
        $result[$key] = $item;
522
      } else {
523
        $result[$key] = $prefix . $item;
524
      }
525
    }
526
527
    return self::create($result);
528
  }
529
530 10
  /**
531
   * Convert an array into a object.
532 10
   *
533
   * @param array $array PHP array
534 10
   *
535 2
   * @return \stdClass (object)
536
   */
537
  protected static function arrayToObject(array $array = array())
538 8
  {
539 3
    $object = new \stdClass();
540 3
541
    if (!is_array($array) || count($array) < 1) {
542 8
      return $object;
543
    }
544
545
    foreach ($array as $name => $value) {
546
      if (is_array($value)) {
547
        $object->$name = self::arrayToObject($value);
548
        continue;
549
      }
550 4
      $object->{$name} = $value;
551
    }
552 4
553 4
    return $object;
554 4
  }
555
556 4
  /**
557 4
   * Sort an array in reverse order and maintain index association.
558
   *
559 4
   * @return static <p>(Mutable) Return this Arrayy object.</p>
560
   */
561
  public function arsort()
562
  {
563 4
    arsort($this->array);
564 1
565 1
    return $this;
566 1
  }
567 1
568 1
  /**
569 1
   * Iterate over the current array and execute a callback for each loop.
570 4
   *
571
   * @param \Closure $closure
572 4
   *
573
   * @return static <p>(Immutable)</p>
574
   */
575 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...
576
  {
577
    $array = $this->array;
578
579
    foreach ($array as $key => $value) {
580
      $closure($value, $key);
581
    }
582 1
583
    return static::create($array);
584 1
  }
585
586
  /**
587
   * Returns the average value of the current array.
588
   *
589
   * @param int $decimals <p>The number of decimal-numbers to return.</p>
590
   *
591
   * @return int|double <p>The average value.</p>
592
   */
593
  public function average($decimals = 0)
594
  {
595
    $count = $this->count();
596 1
597
    if (!$count) {
598 1
      return 0;
599
    }
600 1
601
    if (!is_int($decimals)) {
602
      $decimals = 0;
603
    }
604
605
    return round(\array_sum($this->array) / $count, $decimals);
606
  }
607
608
  /**
609
   * @param mixed      $path
610
   * @param callable   $callable
611 4
   * @param null|array $currentOffset
612
   */
613 4
  protected function callAtPath($path, $callable, &$currentOffset = null)
614
  {
615 4
    if ($currentOffset === null) {
616
      $currentOffset = &$this->array;
617
    }
618
619
    $explodedPath = explode($this->pathSeparator, $path);
620
    $nextPath = \array_shift($explodedPath);
621
622
    if (!isset($currentOffset[$nextPath])) {
623 8
      return;
624
    }
625 8
626
    if (!empty($explodedPath)) {
627 7
      $this->callAtPath(
628
          implode($this->pathSeparator, $explodedPath),
629 8
          $callable,
630
          $currentOffset[$nextPath]
631
      );
632
    } else {
633
      $callable($currentOffset[$nextPath]);
634
    }
635
  }
636
637 4
  /**
638
   * Changes all keys in an array.
639 4
   *
640
   * @param int $case [optional] <p> Either <strong>CASE_UPPER</strong><br />
641 4
   *                  or <strong>CASE_LOWER</strong> (default)</p>
642
   *
643
   * @return static <p>(Immutable)</p>
644
   */
645
  public function changeKeyCase($case = CASE_LOWER)
646
  {
647
    return static::create(UTF8::array_change_key_case($this->array, $case));
0 ignored issues
show
Security Bug introduced by
It seems like \voku\helper\UTF8::array...se($this->array, $case) targeting voku\helper\UTF8::array_change_key_case() can also be of type false; however, Arrayy\Arrayy::create() does only seem to accept array, did you maybe forget to handle an error condition?
Loading history...
648
  }
649
650
  /**
651 13
   * Change the path separator of the array wrapper.
652
   *
653 13
   * By default, the separator is: "."
654
   *
655
   * @param string $separator <p>Separator to set.</p>
656
   *
657
   * @return static <p>Mutable</p>
658
   */
659
  public function changeSeparator($separator)
660
  {
661
    $this->pathSeparator = $separator;
662
663 13
    return $this;
664
  }
665 13
666 13
  /**
667 13
   * Create a chunked version of the current array.
668
   *
669 13
   * @param int  $size         <p>Size of each chunk.</p>
670 13
   * @param bool $preserveKeys <p>Whether array keys are preserved or no.</p>
671 13
   *
672 13
   * @return static <p>(Immutable) A new array of chunks from the original array.</p>
673 13
   */
674
  public function chunk($size, $preserveKeys = false)
675 13
  {
676
    $result = \array_chunk($this->array, $size, $preserveKeys);
677
678
    return static::create($result);
679
  }
680
681
  /**
682
   * Clean all falsy values from the current array.
683
   *
684
   * @return static <p>(Immutable)</p>
685 4
   */
686
  public function clean()
687 4
  {
688
    return $this->filter(
689
        function ($value) {
690
          return (bool)$value;
691
        }
692
    );
693
  }
694
695
  /**
696
   * WARNING!!! -> Clear the current array.
697 1
   *
698
   * @return static <p>(Mutable) Return this Arrayy object, with an empty array.</p>
699 1
   */
700
  public function clear()
701
  {
702
    $this->array = array();
703
704
    return $this;
705
  }
706
707
  /**
708
   * Check if an item is in the current array.
709
   *
710
   * @param string|int|float $value
711 9
   *
712
   * @return bool
713 9
   */
714
  public function contains($value)
715
  {
716
    return in_array($value, $this->array, true);
717
  }
718
719
  /**
720
   * Check if an (case-insensitive) string is in the current array.
721
   *
722
   * @param string $value
723 1
   *
724
   * @return bool
725 1
   */
726
  public function containsCaseInsensitive($value)
727
  {
728
    return in_array(
729
        UTF8::strtolower($value),
730
        \array_map(
731
            array(
732
                new UTF8(),
733
                'strtolower',
734
            ),
735 482
            $this->array
736
        ),
737 482
        true
738
    );
739
  }
740
741
  /**
742
   * Check if the given key/index exists in the array.
743
   *
744
   * @param string|int|float $key <p>key/index to search for</p>
745
   *
746
   * @return bool <p>Returns true if the given key/index exists in the array, false otherwise.</p>
747 1
   */
748
  public function containsKey($key)
749 1
  {
750
    return $this->offsetExists($key);
751 1
  }
752
753 1
  /**
754
   * Check if all given needles are present in the array as key/index.
755
   *
756
   * @param array $needles
757
   *
758
   * @return bool <p>Returns true if the given keys/indexes exists in the array, false otherwise.</p>
759
   */
760
  public function containsKeys(array $needles)
761
  {
762
    return count(\array_intersect($needles, $this->keys()->getArray())) === count($needles);
763 5
  }
764
765 5
  /**
766
   * alias: for "Arrayy->contains()"
767 5
   *
768
   * @see Arrayy::contains()
769
   *
770
   * @param string|int|float $value
771
   *
772
   * @return bool
773
   */
774
  public function containsValue($value)
775
  {
776
    return $this->contains($value);
777 4
  }
778
779 4
  /**
780 4
   * Check if all given needles are present in the array.
781
   *
782 3
   * @param array $needles
783 4
   *
784
   * @return bool <p>Returns true if the given values exists in the array, false otherwise.</p>
785 4
   */
786
  public function containsValues(array $needles)
787
  {
788
    return count(\array_intersect($needles, $this->array)) === count($needles);
789
  }
790
791
  /**
792
   * Counts all the values of an array
793
   *
794
   * @link http://php.net/manual/en/function.array-count-values.php
795 5
   *
796
   * @return static <p>
797 5
   *                (Immutable)
798
   *                An associative Arrayy-object of values from input as
799
   *                keys and their count as value.
800
   *                </p>
801
   */
802
  public function countValues()
803
  {
804
    return new static(\array_count_values($this->array));
805
  }
806
807 5
  /**
808
   * Creates an Arrayy object.
809 5
   *
810 4
   * @param array $array
811
   *
812
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
813 5
   */
814 5
  public static function create($array = array())
815 5
  {
816 5
    return new static($array);
817
  }
818
819
  /**
820
   * WARNING: Creates an Arrayy object by reference.
821
   *
822
   * @param array $array
823
   *
824
   * @return static <p>(Mutable) Return this Arrayy object.</p>
825
   */
826
  public function createByReference(&$array = array())
827
  {
828
    $array = $this->fallbackForArray($array);
829 8
830
    $this->array = &$array;
831 8
832 1
    return $this;
833
  }
834 1
835 1
  /**
836 1
   * Create an new Arrayy object via JSON.
837
   *
838 1
   * @param string $json
839 7
   *
840
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
841
   */
842
  public static function createFromJson($json)
843 8
  {
844
    $array = UTF8::json_decode($json, true);
845
846
    return static::create($array);
847 8
  }
848 8
849 8
  /**
850 8
   * Create an new instance filled with values from an object that have implemented ArrayAccess.
851 8
   *
852
   * @param \ArrayAccess $object <p>Object that implements ArrayAccess</p>
853 8
   *
854
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
855
   */
856
  public static function createFromObject(\ArrayAccess $object)
857
  {
858
    $array = new static();
859
    foreach ($object as $key => $value) {
860
      /** @noinspection OffsetOperationsInspection */
861
      $array[$key] = $value;
862
    }
863
864
    return $array;
865 1
  }
866
867 1
  /**
868
   * Create an new instance filled with values from an object.
869
   *
870
   * @param object $object
871
   *
872
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
873
   */
874
  public static function createFromObjectVars($object)
875
  {
876
    return new static(self::objectToArray($object));
877
  }
878
879
  /**
880
   * Create an new Arrayy object via string.
881 5
   *
882
   * @param string      $str       <p>The input string.</p>
883 5
   * @param string|null $delimiter <p>The boundary string.</p>
884
   * @param string|null $regEx     <p>Use the $delimiter or the $regEx, so if $pattern is null, $delimiter will be
885
   *                               used.</p>
886
   *
887
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
888
   */
889 5
  public static function createFromString($str, $delimiter, $regEx = null)
890
  {
891 5
    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...
892
      preg_match_all($regEx, $str, $array);
893
894
      if (!empty($array)) {
895
        $array = $array[0];
896
      }
897
898
    } else {
899
      $array = explode($delimiter, $str);
900
    }
901
902
    // trim all string in the array
903
    \array_walk(
904
        $array,
905 5
        function (&$val) {
906
          /** @noinspection ReferenceMismatchInspection */
907 5
          if (is_string($val)) {
908
            $val = trim($val);
909
          }
910
        }
911
    );
912
913 5
    return static::create($array);
914
  }
915 5
916
  /**
917
   * Create an new instance containing a range of elements.
918
   *
919
   * @param mixed $low  <p>First value of the sequence.</p>
920
   * @param mixed $high <p>The sequence is ended upon reaching the end value.</p>
921
   * @param int   $step <p>Used as the increment between elements in the sequence.</p>
922
   *
923
   * @return static <p>(Immutable) Returns an new instance of the Arrayy object.</p>
924
   */
925 12
  public static function createWithRange($low, $high, $step = 1)
926
  {
927 12
    return static::create(range($low, $high, $step));
928
  }
929 12
930
  /**
931
   * Custom sort by index via "uksort".
932
   *
933
   * @link http://php.net/manual/en/function.uksort.php
934
   *
935
   * @param callable $function
936
   *
937
   * @return static <p>(Mutable) Return this Arrayy object.</p>
938
   *
939
   * @throws \InvalidArgumentException
940 1
   */
941 View Code Duplication
  public function customSortKeys($function)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
942 1
  {
943
    if (!is_callable($function)) {
944
      throw new \InvalidArgumentException(
945
          'Passed function must be callable'
946 1
      );
947 1
    }
948 1
949 1
    uksort($this->array, $function);
950 1
951 1
    return $this;
952
  }
953
954 1
  /**
955 1
   * Custom sort by value via "usort".
956 1
   *
957 1
   * @link http://php.net/manual/en/function.usort.php
958 1
   *
959 1
   * @param callable $function
960 1
   *
961 1
   * @return static <p>(Mutable) Return this Arrayy object.</p>
962 1
   *
963 1
   * @throws \InvalidArgumentException
964 1
   */
965 View Code Duplication
  public function customSortValues($function)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
966 1
  {
967 1
    if (!is_callable($function)) {
968
      throw new \InvalidArgumentException(
969 1
          'Passed function must be callable'
970
      );
971 1
    }
972
973
    usort($this->array, $function);
974
975
    return $this;
976
  }
977
978
  /**
979
   * Return values that are only in the current array.
980
   *
981 8
   * @param array $array
982
   *
983 8
   * @return static <p>(Immutable)</p>
984
   */
985 8
  public function diff(array $array = array())
986
  {
987
    $result = \array_diff($this->array, $array);
988
989
    return static::create($result);
990
  }
991
992
  /**
993 1
   * Return values that are only in the current multi-dimensional array.
994
   *
995 1
   * @param array      $array
996
   * @param null|array $helperVariableForRecursion <p>(only for internal usage)</p>
997 1
   *
998 1
   * @return static <p>(Immutable)</p>
999
   */
1000 1
  public function diffRecursive(array $array = array(), $helperVariableForRecursion = null)
1001
  {
1002
    $result = array();
1003
1004
    if (
1005
        $helperVariableForRecursion !== null
1006
        &&
1007
        is_array($helperVariableForRecursion)
1008
    ) {
1009
      $arrayForTheLoop = $helperVariableForRecursion;
1010 4
    } else {
1011
      $arrayForTheLoop = $this->array;
1012 4
    }
1013
1014 4
    foreach ($arrayForTheLoop as $key => $value) {
1015 4
      if (\array_key_exists($key, $array)) {
1016 4
        if (is_array($value)) {
1017
          $recursiveDiff = $this->diffRecursive($array[$key], $value);
1018 4
          if (!empty($recursiveDiff)) {
1019
            $result[$key] = $recursiveDiff;
1020
          }
1021
        } else {
1022
          if ($value != $array[$key]) {
1023
            $result[$key] = $value;
1024
          }
1025
        }
1026
      } else {
1027
        $result[$key] = $value;
1028 4
      }
1029
    }
1030 4
1031 4
    return static::create($result);
1032 3
  }
1033 1
1034 1
  /**
1035
   * Return values that are only in the new $array.
1036 4
   *
1037
   * @param array $array
1038 4
   *
1039
   * @return static <p>(Immutable)</p>
1040
   */
1041
  public function diffReverse(array $array = array())
1042
  {
1043
    $result = \array_diff($array, $this->array);
1044
1045
    return static::create($result);
1046
  }
1047
1048
  /**
1049
   * Divide an array into two arrays. One with keys and the other with values.
1050
   *
1051
   * @return static <p>(Immutable)</p>
1052
   */
1053
  public function divide()
1054
  {
1055
    return static::create(
1056
        array(
1057
            $this->keys(),
1058 775
            $this->values(),
1059
        )
1060 775
    );
1061 772
  }
1062
1063
  /**
1064 11
   * Iterate over the current array and modify the array's value.
1065 1
   *
1066
   * @param \Closure $closure
1067
   *
1068 10
   * @return static <p>(Immutable)</p>
1069 6
   */
1070 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...
1071
  {
1072 9
    $array = $this->array;
1073
1074 9
    foreach ($array as $key => $value) {
1075
      $array[$key] = $closure($value, $key);
1076
    }
1077
1078
    return static::create($array);
1079 9
  }
1080
1081
  /**
1082
   * Check if a value is in the current array using a closure.
1083 9
   *
1084
   * @param \Closure $closure
1085
   *
1086
   * @return bool <p>Returns true if the given value is found, false otherwise.</p>
1087
   */
1088
  public function exists(\Closure $closure)
1089 9
  {
1090
    $isExists = false;
1091 2
    foreach ($this->array as $key => $value) {
1092 9
      if ($closure($value, $key)) {
1093 7
        $isExists = true;
1094
        break;
1095
      }
1096 2
    }
1097
1098 2
    return $isExists;
1099
  }
1100
1101
  /**
1102
   * create a fallback for array
1103
   *
1104
   * 1. use the current array, if it's a array
1105
   * 2. call "getArray()" on object, if there is a "Arrayy"-object
1106
   * 3. fallback to empty array, if there is nothing
1107
   * 4. call "createFromObject()" on object, if there is a "\ArrayAccess"-object
1108
   * 5. call "__toArray()" on object, if the method exists
1109
   * 6. cast a string or object with "__toString()" into an array
1110
   * 7. throw a "InvalidArgumentException"-Exception
1111
   *
1112
   * @param $array
1113
   *
1114
   * @return array
1115
   *
1116
   * @throws \InvalidArgumentException
1117
   */
1118
  protected function fallbackForArray(&$array)
1119
  {
1120
    if (is_array($array)) {
1121
      return $array;
1122
    }
1123
1124
    if ($array instanceof self) {
1125
      return $array->getArray();
1126
    }
1127
1128
    if (!$array) {
1129 9
      return array();
1130
    }
1131 9
1132 1
    $isObject = is_object($array);
1133
1134
    if ($isObject && $array instanceof \ArrayAccess) {
1135 9
      /** @noinspection ReferenceMismatchInspection */
1136
      return static::createFromObject($array)->getArray();
1137
    }
1138
1139 9
    if ($isObject && $array instanceof \ArrayObject) {
1140
      return $array->getArrayCopy();
1141 9
    }
1142
1143
    if ($isObject && method_exists($array, '__toArray')) {
1144
      return (array)$array->__toArray();
1145
    }
1146
1147
    /** @noinspection ReferenceMismatchInspection */
1148
    if (
1149
        is_string($array)
1150
        ||
1151 1
        ($isObject && method_exists($array, '__toString'))
1152
    ) {
1153 1
      return array((string)$array);
1154 1
    }
1155 1
1156 1
    throw new \InvalidArgumentException(
1157 1
        'Passed value should be a array'
1158 1
    );
1159 1
  }
1160 1
1161 1
  /**
1162 1
   * Find all items in an array that pass the truth test.
1163 1
   *
1164 1
   * @param \Closure|null $closure [optional] <p>
1165 1
   *                               The callback function to use
1166
   *                               </p>
1167
   *                               <p>
1168 9
   *                               If no callback is supplied, all entries of
1169
   *                               input equal to false (see
1170
   *                               converting to
1171
   *                               boolean) will be removed.
1172
   *                               </p>
1173
   *
1174
   *  * @param int $flag [optional] <p>
1175
   *                               Flag determining what arguments are sent to <i>callback</i>:
1176
   *                               </p><ul>
1177
   *                               <li>
1178
   *                               <b>ARRAY_FILTER_USE_KEY</b> [1] - pass key as the only argument
1179
   *                               to <i>callback</i> instead of the value</span>
1180
   *                               </li>
1181
   *                               <li>
1182
   *                               <b>ARRAY_FILTER_USE_BOTH</b> [2] - pass both value and key as
1183
   *                               arguments to <i>callback</i> instead of the value</span>
1184
   *                               </li>
1185
   *                               </ul>
1186
   *
1187
   * @return static <p>(Immutable)</p>
1188
   */
1189
  public function filter($closure = null, $flag = 0)
1190
  {
1191
    if (!$closure) {
1192
      return $this->clean();
1193 1
    }
1194
1195 1
    if ($flag === 0) {
1196 1
1197 1
      // working for all php-versions
1198
1199
      $array = \array_filter($this->array, $closure);
1200
1201 1
    } elseif ($flag !== 0 && defined('HHVM_VERSION') === false && Bootup::is_php('5.6')) {
1202 1
1203
      // working only with php >= 5.6 and not via HHVM
1204
1205 1
      $array = \array_filter($this->array, $closure, $flag);
1206
1207
    } else {
1208 1
1209
      // fallback for old php-versions
1210
1211 1
      $array = $this->array;
1212
1213 1
      if ($flag === 2 /* ARRAY_FILTER_USE_KEY */) {
1214 1
        foreach ($array as $key => $value) {
1215
          if (!call_user_func($closure, $key)) {
1216
            unset($array[$key]);
1217 1
          }
1218
        }
1219
      } elseif ($flag === 1 /* ARRAY_FILTER_USE_BOTH */) {
1220 1
        foreach ($array as $key => $value) {
1221
          if (!call_user_func($closure, $key, $value)) {
1222
            unset($array[$key]);
1223 1
          }
1224
        }
1225 1
      }
1226 1
    }
1227
1228
    return static::create($array);
1229 1
  }
1230
1231
  /**
1232 1
   * Filters an array of objects (or a numeric array of associative arrays) based on the value of a particular property
1233
   * within that.
1234
   *
1235 1
   * @param string $property
1236 1
   * @param string $value
1237
   * @param string $comparisonOp
1238 1
   *                            <p>
1239 1
   *                            'eq' (equals),<br />
1240 1
   *                            'gt' (greater),<br />
1241
   *                            'gte' || 'ge' (greater or equals),<br />
1242 1
   *                            'lt' (less),<br />
1243 1
   *                            'lte' || 'le' (less or equals),<br />
1244 1
   *                            'ne' (not equals),<br />
1245 1
   *                            'contains',<br />
1246
   *                            'notContains',<br />
1247 1
   *                            'newer' (via strtotime),<br />
1248 1
   *                            'older' (via strtotime),<br />
1249 1
   *                            </p>
1250
   *
1251 1
   * @return static <p>(Immutable)</p>
1252
   */
1253 1
  public function filterBy($property, $value, $comparisonOp = null)
1254 1
  {
1255
    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...
1256 1
      $comparisonOp = is_array($value) ? 'contains' : 'eq';
1257
    }
1258
1259
    $ops = array(
1260
        'eq'          => function ($item, $prop, $value) {
1261
          return $item[$prop] === $value;
1262
        },
1263
        'gt'          => function ($item, $prop, $value) {
1264
          return $item[$prop] > $value;
1265
        },
1266
        'ge'          => function ($item, $prop, $value) {
1267 8
          return $item[$prop] >= $value;
1268
        },
1269 8
        'gte'         => function ($item, $prop, $value) {
1270 6
          return $item[$prop] >= $value;
1271 5
        },
1272
        'lt'          => function ($item, $prop, $value) {
1273 5
          return $item[$prop] < $value;
1274
        },
1275 3
        'le'          => function ($item, $prop, $value) {
1276
          return $item[$prop] <= $value;
1277
        },
1278
        'lte'         => function ($item, $prop, $value) {
1279
          return $item[$prop] <= $value;
1280
        },
1281
        'ne'          => function ($item, $prop, $value) {
1282
          return $item[$prop] !== $value;
1283
        },
1284
        'contains'    => function ($item, $prop, $value) {
1285
          return in_array($item[$prop], (array)$value, true);
1286
        },
1287
        'notContains' => function ($item, $prop, $value) {
1288
          return !in_array($item[$prop], (array)$value, true);
1289
        },
1290
        'newer'       => function ($item, $prop, $value) {
1291
          return strtotime($item[$prop]) > strtotime($value);
1292
        },
1293
        'older'       => function ($item, $prop, $value) {
1294
          return strtotime($item[$prop]) < strtotime($value);
1295
        },
1296
    );
1297 13
1298
    $result = \array_values(
1299 13
        \array_filter(
1300 13
            (array)$this->array,
1301
            function ($item) use (
1302 13
                $property,
1303 3
                $value,
1304
                $ops,
1305
                $comparisonOp
1306 10
            ) {
1307
              $item = (array)$item;
1308
              $itemArrayy = new Arrayy($item);
1309
              $item[$property] = $itemArrayy->get($property, array());
1310
1311
              return $ops[$comparisonOp]($item, $property, $value);
1312
            }
1313
        )
1314
    );
1315
1316 28
    return static::create($result);
1317
  }
1318 28
1319 7
  /**
1320 7
   * Find the first item in an array that passes the truth test,
1321 7
   *  otherwise return false
1322 21
   *
1323 21
   * @param \Closure $closure
1324 21
   *
1325
   * @return mixed|false <p>Return false if we did not find the value.</p>
1326
   */
1327 28
  public function find(\Closure $closure)
1328
  {
1329
    foreach ($this->array as $key => $value) {
1330
      if ($closure($value, $key)) {
1331
        return $value;
1332
      }
1333
    }
1334
1335
    return false;
1336
  }
1337 26
1338
  /**
1339 26
   * find by ...
1340 11
   *
1341 11
   * @param string $property
1342 15
   * @param string $value
1343 15
   * @param string $comparisonOp
1344
   *
1345
   * @return static <p>(Immutable)</p>
1346 26
   */
1347
  public function findBy($property, $value, $comparisonOp = 'eq')
1348
  {
1349
    return $this->filterBy($property, $value, $comparisonOp);
1350
  }
1351
1352
  /**
1353
   * Get the first value from the current array.
1354 1
   *
1355
   * @return mixed <p>Return null if there wasn't a element.</p>
1356 1
   */
1357
  public function first()
1358 1
  {
1359
    $tmpArray = $this->array;
1360
    $result = \array_shift($tmpArray);
1361
1362
    if ($result === null) {
1363
      return null;
1364
    }
1365
1366
    return $result;
1367
  }
1368
1369
  /**
1370
   * Get the first value(s) from the current array.
1371 61
   *
1372
   * @param int|null $number <p>How many values you will take?</p>
1373
   *
1374
   * @return static <p>(Immutable)</p>
1375 61
   */
1376 3
  public function firstsImmutable($number = null)
1377 61
  {
1378 3
    if ($number === null) {
1379 3
      $arrayTmp = $this->array;
1380 59
      $array = (array)\array_shift($arrayTmp);
1381
    } else {
1382
      $number = (int)$number;
1383 61
      $arrayTmp = $this->array;
1384 1
      $array = \array_splice($arrayTmp, 0, $number, true);
1385
    }
1386
1387
    return static::create($array);
1388 61
  }
1389 2
1390 2
  /**
1391
   * Get the first value(s) from the current array.
1392 61
   *
1393 51
   * @param int|null $number <p>How many values you will take?</p>
1394 6
   *
1395
   * @return static <p>(Mutable)</p>
1396
   */
1397 47
  public function firstsMutable($number = null)
1398
  {
1399
    if ($number === null) {
1400
      $this->array = (array)\array_shift($this->array);
1401 20
    } else {
1402 20
      $number = (int)$number;
1403 19
      $this->array = \array_splice($this->array, 0, $number, true);
1404
    }
1405
1406 5
    return $this;
1407 5
  }
1408
1409 5
  /**
1410
   * Exchanges all keys with their associated values in an array.
1411
   *
1412
   * @return static <p>(Immutable)</p>
1413 5
   */
1414
  public function flip()
1415
  {
1416
    $result = \array_flip($this->array);
1417
1418
    return static::create($result);
1419
  }
1420
1421 496
  /**
1422
   * Get a value from an array (optional using dot-notation).
1423 496
   *
1424
   * @param string $key      <p>The key to look for.</p>
1425 496
   * @param mixed  $fallback <p>Value to fallback to.</p>
1426
   * @param array  $array    <p>The array to get from, if it's set to "null" we use the current array from the
1427
   *                         class.</p>
1428
   *
1429
   * @return mixed
1430
   */
1431
  public function get($key, $fallback = null, $array = null)
1432
  {
1433 4
    if (
1434
        $array !== null
1435 4
        &&
1436
        is_array($array)
1437
    ) {
1438
      $usedArray = $array;
1439
    } else {
1440
      $usedArray = $this->array;
1441
    }
1442
1443
    if ($key === null) {
1444
      return static::create($usedArray);
1445 4
    }
1446
1447 4
    // php cast "bool"-index into "int"-index
1448
    if ((bool)$key === $key) {
1449 4
      $key = (int)$key;
1450 1
    }
1451
1452
    if (\array_key_exists($key, $usedArray) === true) {
1453 3
      if (is_array($usedArray[$key])) {
1454 3
        return static::create($usedArray[$key]);
1455 1
      }
1456 1
1457
      return $usedArray[$key];
1458 3
    }
1459 3
1460
    // Crawl through array, get key according to object or not
1461 3
    foreach (explode($this->pathSeparator, (string)$key) as $segment) {
1462
      if (!isset($usedArray[$segment])) {
1463
        return $fallback instanceof \Closure ? $fallback() : $fallback;
1464
      }
1465
1466
      $usedArray = $usedArray[$segment];
1467
    }
1468
1469
    if (is_array($usedArray)) {
1470
      return static::create($usedArray);
1471
    }
1472
1473
    return $usedArray;
1474
  }
1475
1476 1
  /**
1477
   * Get the current array from the "Arrayy"-object.
1478 1
   *
1479
   * @return array
1480 1
   */
1481
  public function getArray()
1482
  {
1483
    \array_map(array('self', 'internalGetArray'), $this->array);
1484
1485
    return $this->array;
1486
  }
1487
1488
  /**
1489
   * Returns the values from a single column of the input array, identified by
1490 38
   * the $columnKey, can be used to extract data-columns from multi-arrays.
1491
   *
1492 38
   * Info: Optionally, you may provide an $indexKey to index the values in the returned
1493 10
   * array by the values from the $indexKey column in the input array.
1494
   *
1495 10
   * @param mixed $columnKey
1496 2
   * @param mixed $indexKey
1497 2
   *
1498 8
   * @return static <p>(Immutable)</p>
1499
   */
1500 10
  public function getColumn($columnKey = null, $indexKey = null)
1501
  {
1502
    $result = \array_column($this->array, $columnKey, $indexKey);
1503
1504 38
    return static::create($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by \array_column($this->arr... $columnKey, $indexKey) on line 1502 can also be of type false or null; however, Arrayy\Arrayy::create() does only seem to accept array, maybe add an additional type check?

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

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

    return array();
}

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

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

Loading history...
1505
  }
1506 38
1507
  /**
1508
   * Get correct PHP constant for direction.
1509
   *
1510 38
   * @param int|string $direction
1511
   *
1512
   * @return int
1513
   */
1514
  protected function getDirection($direction)
1515
  {
1516
    if (is_string($direction)) {
1517
      $direction = strtolower($direction);
1518
1519
      if ($direction === 'desc') {
1520 1
        $direction = SORT_DESC;
1521
      } else {
1522 1
        $direction = SORT_ASC;
1523
      }
1524
    }
1525
1526
    if (
1527
        $direction !== SORT_DESC
1528
        &&
1529
        $direction !== SORT_ASC
1530
    ) {
1531
      $direction = SORT_ASC;
1532 3
    }
1533
1534 3
    return $direction;
1535
  }
1536
1537
  /**
1538
   * alias: for "Arrayy->keys()"
1539
   *
1540
   * @see Arrayy::keys()
1541
   *
1542
   * @return static <p>(Immutable)</p>
1543
   */
1544 3
  public function getKeys()
1545
  {
1546 3
    return $this->keys();
1547
  }
1548
1549
  /**
1550
   * Get the current array from the "Arrayy"-object as object.
1551
   *
1552
   * @return \stdClass (object)
1553
   */
1554
  public function getObject()
1555
  {
1556
    return self::arrayToObject($this->getArray());
1557
  }
1558 9
1559
  /**
1560 9
   * alias: for "Arrayy->randomImmutable()"
1561
   *
1562
   * @see Arrayy::randomImmutable()
1563
   *
1564
   * @return static <p>(Immutable)</p>
1565
   */
1566
  public function getRandom()
1567
  {
1568
    return $this->randomImmutable();
1569
  }
1570 3
1571
  /**
1572 3
   * alias: for "Arrayy->randomKey()"
1573
   *
1574
   * @see Arrayy::randomKey()
1575
   *
1576
   * @return mixed <p>Get a key/index or null if there wasn't a key/index.</p>
1577
   */
1578
  public function getRandomKey()
1579
  {
1580
    return $this->randomKey();
1581
  }
1582
1583
  /**
1584 6
   * alias: for "Arrayy->randomKeys()"
1585
   *
1586 6
   * @see Arrayy::randomKeys()
1587
   *
1588
   * @param int $number
1589
   *
1590
   * @return static <p>(Immutable)</p>
1591
   */
1592
  public function getRandomKeys($number)
1593
  {
1594
    return $this->randomKeys($number);
1595
  }
1596
1597 3
  /**
1598
   * alias: for "Arrayy->randomValue()"
1599 3
   *
1600 3
   * @see Arrayy::randomValue()
1601
   *
1602
   * @return mixed <p>get a random value or null if there wasn't a value.</p>
1603 3
   */
1604
  public function getRandomValue()
1605 3
  {
1606 3
    return $this->randomValue();
1607
  }
1608 3
1609
  /**
1610
   * alias: for "Arrayy->randomValues()"
1611
   *
1612 3
   * @see Arrayy::randomValues()
1613 3
   *
1614 3
   * @param int $number
1615
   *
1616
   * @return static <p>(Immutable)</p>
1617 3
   */
1618 2
  public function getRandomValues($number)
1619 1
  {
1620 1
    return $this->randomValues($number);
1621 1
  }
1622 1
1623 1
  /**
1624
   * Group values from a array according to the results of a closure.
1625 2
   *
1626
   * @param string $grouper <p>A callable function name.</p>
1627 3
   * @param bool   $saveKeys
1628
   *
1629 3
   * @return static <p>(Immutable)</p>
1630
   */
1631
  public function group($grouper, $saveKeys = false)
1632
  {
1633
    $array = (array)$this->array;
1634
    $result = array();
1635
1636
    // Iterate over values, group by property/results from closure
1637
    foreach ($array as $key => $value) {
1638
1639 22
      $groupKey = is_callable($grouper) ? $grouper($value, $key) : $this->get($grouper, null, $value);
1640
      $newValue = $this->get($groupKey, null, $result);
1641
1642 22
      if ($groupKey instanceof self) {
1643
        $groupKey = $groupKey->getArray();
1644 22
      }
1645
1646
      if ($newValue instanceof self) {
1647
        $newValue = $newValue->getArray();
1648
      }
1649
1650
      // Add to results
1651
      if ($groupKey !== null) {
1652
        if ($saveKeys) {
1653
          $result[$groupKey] = $newValue;
1654 28
          $result[$groupKey][$key] = $value;
1655
        } else {
1656 28
          $result[$groupKey] = $newValue;
1657
          $result[$groupKey][] = $value;
1658
        }
1659
      }
1660
1661
    }
1662
1663
    return static::create($result);
1664
  }
1665 28
1666 28
  /**
1667 28
   * Check if an array has a given key.
1668
   *
1669 28
   * @param mixed $key
1670 28
   *
1671 28
   * @return bool
1672 28
   */
1673 28
  public function has($key)
1674
  {
1675 28
    // Generate unique string to use as marker.
1676 28
    $unFound = (string)uniqid('arrayy', true);
1677
1678
    return $this->get($key, $unFound) !== $unFound;
1679 28
  }
1680
1681
  /**
1682
   * Implodes an array.
1683
   *
1684
   * @param string $glue
1685
   *
1686
   * @return string
1687
   */
1688
  public function implode($glue = '')
1689
  {
1690
    return self::implode_recursive($glue, $this->array);
1691
  }
1692
1693 3
  /**
1694
   * @param string       $glue
1695 3
   * @param string|array $pieces
1696
   *
1697 3
   * @return string
1698 3
   */
1699 2
  protected static function implode_recursive($glue = '', $pieces)
1700 2
  {
1701 3
    if (is_array($pieces)) {
1702
      $pieces_count = count($pieces);
1703 3
1704
      return implode(
1705
          $glue,
1706
          array_map(
1707
              array('self', 'implode_recursive'),
1708
              array_fill(0, ($pieces_count > 0 ? $pieces_count : 1), $glue),
1709
              $pieces
1710
          )
1711
      );
1712
    }
1713
1714
    return $pieces;
1715 4
  }
1716
1717 4
  /**
1718
   * Given a list and an iterate-function that returns
1719
   * a key for each element in the list (or a property name),
1720
   * returns an object with an index of each item.
1721
   *
1722
   * Just like groupBy, but for when you know your keys are unique.
1723
   *
1724
   * @param mixed $key
1725
   *
1726
   * @return static <p>(Immutable)</p>
1727 12
   */
1728
  public function indexBy($key)
1729 12
  {
1730
    $results = array();
1731 12
1732
    foreach ($this->array as $a) {
1733
      if (\array_key_exists($key, $a) === true) {
1734
        $results[$a[$key]] = $a;
1735
      }
1736
    }
1737 410
1738
    return static::create($results);
1739 410
  }
1740
1741
  /**
1742
   * alias: for "Arrayy->searchIndex()"
1743
   *
1744
   * @see Arrayy::searchIndex()
1745
   *
1746
   * @param mixed $value <p>The value to search for.</p>
1747
   *
1748
   * @return mixed
1749 410
   */
1750
  public function indexOf($value)
1751
  {
1752
    return $this->searchIndex($value);
1753 410
  }
1754
1755
  /**
1756
   * Get everything but the last..$to items.
1757
   *
1758
   * @param int $to
1759
   *
1760
   * @return static <p>(Immutable)</p>
1761
   */
1762 18
  public function initial($to = 1)
1763
  {
1764 18
    $slice = count($this->array) - $to;
1765
1766
    return $this->firstsImmutable($slice);
1767 18
  }
1768
1769
  /**
1770
   * @param mixed $value
1771
   */
1772
  protected function internalGetArray(&$value)
1773
  {
1774
    if ($value instanceof self) {
1775
1776
      $valueTmp = $value->getArray();
1777 18
      if (count($valueTmp) === 0) {
1778
        $value = array();
1779 18
      } else {
1780
        /** @noinspection PhpUnusedLocalVariableInspection */
1781 18
        $value = &$valueTmp;
1782
      }
1783
1784
    } elseif ($value instanceof \JsonSerializable) {
0 ignored issues
show
Bug introduced by
The class JsonSerializable does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

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

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
3307
        $this->array,
3308
        function ($resultArray, $value) {
3309 9
          if (!in_array($value, $resultArray, true)) {
3310
            $resultArray[] = $value;
3311
          }
3312
3313
          return $resultArray;
3314
        },
3315
        array()
3316
    );
3317
3318 View Code Duplication
    if ($this->array === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
3319
      $this->array = array();
3320
    } else {
3321
      $this->array = (array)$this->array;
3322
    }
3323
3324
    return $this;
3325
  }
3326
3327
  /**
3328
   * Return a duplicate free copy of the current array. (with the old keys)
3329
   *
3330
   * @return static <p>(Mutable)</p>
3331
   */
3332
  public function uniqueKeepIndex()
3333
  {
3334
    // INFO: \array_unique() can't handle e.g. "stdClass"-values in an array
3335
3336
    // init
3337
    $array = $this->array;
3338
3339
    $this->array = \array_reduce(
0 ignored issues
show
Documentation Bug introduced by
It seems like \array_reduce(\array_key...esultArray; }, array()) of type * is incompatible with the declared type array of property $array.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
3340
        \array_keys($array),
3341
        function ($resultArray, $key) use ($array) {
3342
          if (!in_array($array[$key], $resultArray, true)) {
3343
            $resultArray[$key] = $array[$key];
3344
          }
3345
3346
          return $resultArray;
3347
        },
3348
        array()
3349
    );
3350
3351 View Code Duplication
    if ($this->array === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
3352
      $this->array = array();
3353
    } else {
3354
      $this->array = (array)$this->array;
3355
    }
3356
3357
    return $this;
3358
  }
3359
3360
  /**
3361
   * alias: for "Arrayy->unique()"
3362
   *
3363
   * @see Arrayy::unique()
3364
   *
3365
   * @return static <p>(Mutable) Return this Arrayy object, with the appended values.</p>
3366
   */
3367
  public function uniqueNewIndex()
3368
  {
3369
    return $this->unique();
3370
  }
3371
3372
  /**
3373
   * Prepends one or more values to the beginning of array at once.
3374
   *
3375
   * @return static <p>(Mutable) Return this Arrayy object, with prepended elements to the beginning of array.</p>
3376
   */
3377 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...
3378
  {
3379
    if (func_num_args()) {
3380
      $args = \array_merge(array(&$this->array), func_get_args());
3381
      call_user_func_array('array_unshift', $args);
3382
    }
3383
3384
    return $this;
3385
  }
3386
3387
  /**
3388
   * Get all values from a array.
3389
   *
3390
   * @return static <p>(Immutable)</p>
3391
   */
3392
  public function values()
3393
  {
3394
    return static::create(\array_values((array)$this->array));
3395
  }
3396
3397
  /**
3398
   * Apply the given function to every element in the array, discarding the results.
3399
   *
3400
   * @param callable $callable
3401
   * @param bool     $recursive <p>Whether array will be walked recursively or no</p>
3402
   *
3403
   * @return static <p>(Mutable) Return this Arrayy object, with modified elements.</p>
3404
   */
3405
  public function walk($callable, $recursive = false)
3406
  {
3407
    if (true === $recursive) {
3408
      \array_walk_recursive($this->array, $callable);
3409
    } else {
3410
      \array_walk($this->array, $callable);
3411
    }
3412
3413
    return $this;
3414
  }
3415
}
3416