Completed
Push — master ( d5cb12...67271f )
by Lars
08:07
created

Arrayy::reindex()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Arrayy;
4
5
use ArrayAccess;
6
use Closure;
7
use voku\helper\UTF8;
8
9
/**
10
 * Methods to manage arrays.
11
 *
12
 * For the full copyright and license information, please view the LICENSE
13
 * file that was distributed with this source code.
14
 */
15
class Arrayy extends \ArrayObject implements \Countable, \IteratorAggregate, \ArrayAccess, \Serializable
16
{
17
  /**
18
   * @var array
19
   */
20
  protected $array = array();
21
22
  /**
23
   * Initializes
24
   *
25
   * @param array $array
26
   */
27 667
  public function __construct($array = array())
28
  {
29 667
    $array = $this->fallbackForArray($array);
30
31 665
    $this->array = $array;
32 665
  }
33
34
  /**
35
   * create a fallback for array
36
   *
37
   * 1. fallback to empty array, if there is nothing
38
   * 2. cast a String or Object with "__toString" into an array
39
   * 3. call "__toArray" on Object, if the method exists
40
   * 4. throw a "InvalidArgumentException"-Exception
41
   *
42
   * @param $array
43
   *
44
   * @return array
45
   */
46 667
  protected function fallbackForArray(&$array)
47
  {
48 667
    if (is_array($array)) {
49 665
      return $array;
50
    }
51
52 5
    if ($array instanceof self) {
53 1
      return $array->getArray();
54
    }
55
56 4
    if (!$array) {
57 1
      return array();
58
    }
59
60
    if (
61 3
        is_string($array)
62
        ||
63 2
        (is_object($array) && method_exists($array, '__toString'))
64 3
    ) {
65 1
      return (array)$array;
66
    }
67
68 2
    if (is_object($array) && method_exists($array, '__toArray')) {
69
      return (array)$array->__toArray();
70
    }
71
72 2
    throw new \InvalidArgumentException(
73
        'Passed value must be a array'
74 2
    );
75
  }
76
77
  /**
78
   * Get the current array from the "Arrayy"-object
79
   *
80
   * @return array
81
   */
82 470
  public function getArray()
83
  {
84 470
    return $this->array;
85
  }
86
87
  /**
88
   * Create a new Arrayy object via string.
89
   *
90
   * @param string      $str       The input string.
91
   * @param string|null $delimiter The boundary string.
92
   * @param string|null $regEx     Use the $delimiter or the $regEx, so if $pattern is null, $delimiter will be used.
93
   *
94
   * @return Arrayy Returns created instance
95
   */
96 8
  public static function createFromString($str, $delimiter, $regEx = null)
97
  {
98 8
    if ($regEx) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $regEx of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

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

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

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

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
99 1
      preg_match_all($regEx, $str, $array);
100
101 1
      if (count($array) > 0) {
102 1
        $array = $array[0];
103 1
      }
104
105 1
    } else {
106 7
      $array = explode($delimiter, $str);
107
    }
108
109
    // trim all string in the array
110 8
    array_walk(
111 8
        $array,
112
        function (&$val) {
113 8
          if (is_string($val)) {
114 8
            $val = trim($val);
115 8
          }
116 8
        }
117 8
    );
118
119 8
    return static::create($array);
120
  }
121
122
  /**
123
   * Creates a Arrayy object.
124
   *
125
   * @param array $array
126
   *
127
   * @return Arrayy Returns created instance
128
   */
129 433
  public static function create($array = array())
130
  {
131 433
    return new static($array);
132
  }
133
134
  /**
135
   * create a new Arrayy object via JSON,
136
   *
137
   * @param string $json
138
   *
139
   * @return Arrayy Returns created instance
140
   */
141 5
  public static function createFromJson($json)
142
  {
143 5
    $array = UTF8::json_decode($json, true);
144
145 5
    return static::create($array);
146
  }
147
148
  /**
149
   * Create a new instance filled with values from an object implementing ArrayAccess.
150
   *
151
   * @param ArrayAccess $elements Object that implements ArrayAccess
152
   *
153
   * @return Arrayy Returns created instance
154
   */
155 4
  public static function createFromObject(ArrayAccess $elements)
156
  {
157 4
    $array = new static();
158 4
    foreach ($elements as $key => $value) {
159
      /** @noinspection OffsetOperationsInspection */
160 3
      $array[$key] = $value;
161 4
    }
162
163 4
    return $array;
164
  }
165
166
  /**
167
   * Create a new instance containing a range of elements.
168
   *
169
   * @param mixed $low  First value of the sequence
170
   * @param mixed $high The sequence is ended upon reaching the end value
171
   * @param int   $step Used as the increment between elements in the sequence
172
   *
173
   * @return Arrayy The created array
174
   */
175 1
  public static function createWithRange($low, $high, $step = 1)
176
  {
177 1
    return static::create(range($low, $high, $step));
178
  }
179
180
  /**
181
   * alias: for "Arrayy->random()"
182
   *
183
   * @return Arrayy
184
   */
185 3
  public function getRandom()
186
  {
187 3
    return $this->random();
188
  }
189
190
  /**
191
   * Get a random value from the current array.
192
   *
193
   * @param null|int $number how many values you will take?
194
   *
195
   * @return Arrayy
196
   */
197 27
  public function random($number = null)
198
  {
199 27
    if ($this->count() === 0) {
200
      return static::create();
201
    }
202
203 27
    if ($number === null) {
204 15
      $arrayRandValue = (array)$this->array[array_rand($this->array)];
205
206 15
      return static::create($arrayRandValue);
207
    }
208
209 14
    shuffle($this->array);
210
211 14
    return $this->first($number);
212
  }
213
214
  /**
215
   * Count the values from the current array.
216
   *
217
   * INFO: only a alias for "$arrayy->size()"
218
   *
219
   * @return int
220
   */
221 102
  public function count()
222
  {
223 102
    return $this->size();
224
  }
225
226
  /**
227
   * Get the size of an array.
228
   *
229
   * @return int
230
   */
231 102
  public function size()
232
  {
233 102
    return count($this->array);
234
  }
235
236
  /**
237
   * Get the first value(s) from the current array.
238
   *
239
   * @param int|null $number how many values you will take?
240
   *
241
   * @return Arrayy
242
   */
243 43
  public function first($number = null)
244
  {
245 43
    if ($number === null) {
246 12
      $array = (array)array_shift($this->array);
247 12
    } else {
248 31
      $number = (int)$number;
249 31
      $array = array_splice($this->array, 0, $number, true);
250
    }
251
252 43
    return static::create($array);
253
  }
254
255
  /**
256
   * Append a value to an array.
257
   *
258
   * @param mixed $value
259
   *
260
   * @return Arrayy
261
   */
262 8
  public function append($value)
263
  {
264 8
    $this->array[] = $value;
265
266 8
    return static::create($this->array);
267
  }
268
269
  /**
270
   * @return mixed
271
   */
272
  public function serialize()
273
  {
274
    return serialize($this->array);
275
  }
276
277
  /**
278
   * @param string $array
279
   */
280
  public function unserialize($array)
281
  {
282
    $this->array = unserialize($array);
283
  }
284
285
  /**
286
   * Assigns a value to the specified offset.
287
   *
288
   * @param mixed $offset
289
   * @param mixed $value
290
   */
291 13
  public function offsetSet($offset, $value)
292
  {
293 13
    if (null === $offset) {
294 4
      $this->array[] = $value;
295 4
    } else {
296 9
      $this->array[$offset] = $value;
297
    }
298 13
  }
299
300
  /**
301
   * alias: for "Arrayy->randomValue()"
302
   *
303
   * @return mixed get a random value or null if there wasn't a value
304
   */
305
  public function getRandomValue()
306
  {
307
    return $this->randomValue();
308
  }
309
310
  /**
311
   * Pick a random value from the values of this array.
312
   *
313
   * @return mixed get a random value or null if there wasn't a value
314
   */
315 View Code Duplication
  public function randomValue()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
316
  {
317
    $result = $this->random(1);
318
319
    if (!isset($result[0])) {
320
      $result[0] = null;
321
    }
322
323
    return $result[0];
324
  }
325
326
  /**
327
   * alias: for "Arrayy->randomValues()"
328
   *
329
   * @param int $number
330
   *
331
   * @return Arrayy
332
   */
333 6
  public function getRandomValues($number)
334
  {
335 6
    return $this->randomValues($number);
336
  }
337
338
  /**
339
   * Pick a given number of random values out of this array.
340
   *
341
   * @param int $number
342
   *
343
   * @return Arrayy
344
   */
345 6
  public function randomValues($number)
346
  {
347 6
    $number = (int)$number;
348
349 6
    return $this->random($number);
350
  }
351
352
  /**
353
   * alias: for "Arrayy->randomKey()"
354
   *
355
   * @return mixed get a key/index or null if there wasn't a key/index
356
   */
357 3
  public function getRandomKey()
358
  {
359 3
    return $this->randomKey();
360
  }
361
362
  /**
363
   * Pick a random key/index from the keys of this array.
364
   *
365
   *
366
   * @return mixed get a key/index or null if there wasn't a key/index
367
   *
368
   * @throws \RangeException If array is empty
369
   */
370 3 View Code Duplication
  public function randomKey()
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...
371
  {
372 3
    $result = $this->randomKeys(1);
373
374 3
    if (!isset($result[0])) {
375
      $result[0] = null;
376
    }
377
378 3
    return $result[0];
379
  }
380
381
  /**
382
   * Pick a given number of random keys/indexes out of this array.
383
   *
384
   * @param int $number The number of keys/indexes (should be <= $this->count())
385
   *
386
   * @return Arrayy
387
   *
388
   * @throws \RangeException If array is empty
389
   */
390 12
  public function randomKeys($number)
391
  {
392 12
    $number = (int)$number;
393 12
    $count = $this->count();
394
395 12
    if ($number === 0 || $number > $count) {
396 3
      throw new \RangeException(
397 3
          sprintf(
398 3
              'Number of requested keys (%s) must be equal or lower than number of elements in this array (%s)',
399 3
              $number,
400
              $count
401 3
          )
402 3
      );
403
    }
404
405 9
    $result = (array)array_rand($this->array, $number);
406
407 9
    return static::create($result);
408
  }
409
410
  /**
411
   * alias: for "Arrayy->randomKeys()"
412
   *
413
   * @param int $number
414
   *
415
   * @return Arrayy
416
   */
417 9
  public function getRandomKeys($number)
418
  {
419 9
    return $this->randomKeys($number);
420
  }
421
422
  /**
423
   * find by ...
424
   *
425
   * @param        $property
426
   * @param        $value
427
   * @param string $comparisonOp
428
   *
429
   * @return Arrayy
430
   */
431
  public function findBy($property, $value, $comparisonOp = 'eq')
432
  {
433
    $array = $this->filterBy($property, $value, $comparisonOp);
434
435
    return static::create($array);
0 ignored issues
show
Documentation introduced by
$array is of type object<Arrayy\Arrayy>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
436
  }
437
438
  /**
439
   * Filters an array of objects (or a numeric array of associative arrays) based on the value of a particular property
440
   * within that.
441
   *
442
   * @param        $property
443
   * @param        $value
444
   * @param string $comparisonOp
445
   *
446
   * @return Arrayy
447
   */
448 1
  public function filterBy($property, $value, $comparisonOp = null)
449
  {
450 1
    if (!$comparisonOp) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $comparisonOp of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

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

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

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

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
451 1
      $comparisonOp = is_array($value) ? 'contains' : 'eq';
452 1
    }
453
454
    $ops = array(
455
        'eq'          => function ($item, $prop, $value) {
456 1
          return $item[$prop] === $value;
457 1
        },
458
        'gt'          => function ($item, $prop, $value) {
459
          return $item[$prop] > $value;
460 1
        },
461
        'gte'         => function ($item, $prop, $value) {
462
          return $item[$prop] >= $value;
463 1
        },
464
        'lt'          => function ($item, $prop, $value) {
465 1
          return $item[$prop] < $value;
466 1
        },
467
        'lte'         => function ($item, $prop, $value) {
468
          return $item[$prop] <= $value;
469 1
        },
470
        'ne'          => function ($item, $prop, $value) {
471
          return $item[$prop] !== $value;
472 1
        },
473
        'contains'    => function ($item, $prop, $value) {
474 1
          return in_array($item[$prop], (array)$value, true);
475 1
        },
476
        'notContains' => function ($item, $prop, $value) {
477
          return !in_array($item[$prop], (array)$value, true);
478 1
        },
479
        'newer'       => function ($item, $prop, $value) {
480
          return strtotime($item[$prop]) > strtotime($value);
481 1
        },
482
        'older'       => function ($item, $prop, $value) {
483
          return strtotime($item[$prop]) < strtotime($value);
484 1
        },
485 1
    );
486
487 1
    $result = array_values(
488 1
        array_filter(
489 1
            (array)$this->array,
490
            function ($item) use (
491 1
                $property,
492 1
                $value,
493 1
                $ops,
494 1
                $comparisonOp
495
            ) {
496 1
              $item = (array)$item;
497 1
              $itemArrayy = new Arrayy($item);
498 1
              $item[$property] = $itemArrayy->get($property, array());
499
500 1
              return $ops[$comparisonOp]($item, $property, $value);
501
            }
502 1
        )
503 1
    );
504
505 1
    return static::create($result);
506
  }
507
508
  /**
509
   * Get a value from an array (optional using dot-notation).
510
   *
511
   * @param string $key     The key to look for
512
   * @param mixed  $default Default value to fallback to
513
   * @param array  $array   The array to get from,
514
   *                        if it's set to "null" we use the current array from the class
515
   *
516
   * @return mixed
517
   */
518 31
  public function get($key, $default = null, $array = null)
519
  {
520 31
    if (is_array($array) === true) {
521 3
      $usedArray = $array;
522 3
    } else {
523 29
      $usedArray = $this->array;
524
    }
525
526 31
    if (null === $key) {
527 1
      return $usedArray;
528
    }
529
530 31
    if (isset($usedArray[$key])) {
531 22
      return $usedArray[$key];
532
    }
533
534
    // Crawl through array, get key according to object or not
535 16
    foreach (explode('.', $key) as $segment) {
536 16
      if (!isset($usedArray[$segment])) {
537 16
        return $default instanceof Closure ? $default() : $default;
538
      }
539
540
      $usedArray = $usedArray[$segment];
541
    }
542
543
    return $usedArray;
544
  }
545
546
  /**
547
   * WARNING: Creates a Arrayy object by reference.
548
   *
549
   * @param array $array
550
   *
551
   * @return $this
552
   */
553
  public function createByReference(&$array = array())
554
  {
555
    $array = $this->fallbackForArray($array);
556
557
    $this->array = &$array;
558
559
    return $this;
560
  }
561
562
  /**
563
   * Get all values from a array.
564
   *
565
   * @return Arrayy
566
   */
567 1
  public function values()
568
  {
569 1
    $array = array_values((array)$this->array);
570
571 1
    return static::create($array);
572
  }
573
574
  /**
575
   * Group values from a array according to the results of a closure.
576
   *
577
   * @param string $grouper a callable function name
578
   * @param bool   $saveKeys
579
   *
580
   * @return Arrayy
581
   */
582 3
  public function group($grouper, $saveKeys = false)
583
  {
584 3
    $array = (array)$this->array;
585 3
    $result = array();
586
587
    // Iterate over values, group by property/results from closure
588 3
    foreach ($array as $key => $value) {
589 3
      $groupKey = is_callable($grouper) ? $grouper($value, $key) : $this->get($grouper, null, $value);
590 3
      $newValue = $this->get($groupKey, null, $result);
591
592
      // Add to results
593 3
      if ($groupKey !== null) {
594 2
        if ($saveKeys) {
595 1
          $result[$groupKey] = $newValue;
596 1
          $result[$groupKey][$key] = $value;
597 1
        } else {
598 1
          $result[$groupKey] = $newValue;
599 1
          $result[$groupKey][] = $value;
600
        }
601 2
      }
602
603 3
    }
604
605 3
    return static::create($result);
606
  }
607
608
  /**
609
   * Given a list and an iterate-function that returns
610
   * a key for each element in the list (or a property name),
611
   * returns an object with an index of each item.
612
   *
613
   * Just like groupBy, but for when you know your keys are unique.
614
   *
615
   * @param mixed $key
616
   *
617
   * @return Arrayy
618
   */
619 3
  public function indexBy($key)
620
  {
621 3
    $results = array();
622
623 3
    foreach ($this->array as $a) {
624 3
      if (isset($a[$key])) {
625 2
        $results[$a[$key]] = $a;
626 2
      }
627 3
    }
628
629 3
    return static::create($results);
630
  }
631
632
  /**
633
   * magic to string
634
   *
635
   * @return string
636
   */
637 17
  public function __toString()
638
  {
639 17
    return $this->toString();
640
  }
641
642
  /**
643
   * Implodes array to a string with specified separator.
644
   *
645
   * @param string $separator The element's separator
646
   *
647
   * @return string The string representation of array, separated by ","
648
   */
649 17
  public function toString($separator = ',')
650
  {
651 17
    return $this->implode($separator);
652
  }
653
654
  /**
655
   * Implodes an array.
656
   *
657
   * @param string $with What to implode it with
658
   *
659
   * @return string
660
   */
661 25
  public function implode($with = '')
662
  {
663 25
    return implode($with, $this->array);
664
  }
665
666
  /**
667
   * Push one or more values onto the end of array at once.
668
   *
669
   * @return $this An Arrayy object with pushed elements to the end of array
670
   */
671 4 View Code Duplication
  public function push(/* variadic arguments allowed */)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
672
  {
673 4
    if (func_num_args()) {
674 4
      $args = array_merge(array(&$this->array), func_get_args());
675 4
      call_user_func_array('array_push', $args);
676 4
    }
677
678 4
    return $this;
679
  }
680
681
  /**
682
   * Shifts a specified value off the beginning of array.
683
   *
684
   * @return mixed A shifted element from the current array.
685
   */
686 4
  public function shift()
687
  {
688 4
    return array_shift($this->array);
689
  }
690
691
  /**
692
   * Prepends one or more values to the beginning of array at once.
693
   *
694
   * @return Arrayy Array object with prepended elements to the beginning of array
695
   */
696 4 View Code Duplication
  public function unshift(/* variadic arguments allowed */)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
697
  {
698 4
    if (func_num_args()) {
699 4
      $args = array_merge(array(&$this->array), func_get_args());
700 4
      call_user_func_array('array_unshift', $args);
701 4
    }
702
703 4
    return $this;
704
  }
705
706
  /**
707
   * Get a value by key.
708
   *
709
   * @param $key
710
   *
711
   * @return mixed
712
   */
713
  public function &__get($key)
714
  {
715
    return $this->array[$key];
716
  }
717
718
  /**
719
   * Assigns a value to the specified element.
720
   *
721
   * @param $key
722
   * @param $value
723
   */
724
  public function __set($key, $value)
725
  {
726
    $this->array[$key] = $value;
727
  }
728
729
  /**
730
   * Whether or not an element exists by key.
731
   *
732
   * @param $key
733
   *
734
   * @return bool
735
   */
736
  public function __isset($key)
737
  {
738
    return isset($this->array[$key]);
739
  }
740
741
  /**
742
   * Unset element by key
743
   *
744
   * @param mixed $key
745
   */
746
  public function __unset($key)
747
  {
748
    unset($this->array[$key]);
749
  }
750
  /**
751
   * Call object as function.
752
   *
753
   * @param mixed $key
754
   *
755
   * @return mixed
756
   */
757
  public function __invoke($key = null)
758
  {
759
    if ($key !== null) {
760
      if (isset($this->array[$key])) {
761
        return $this->array[$key];
762
      } else {
763
        return false;
764
      }
765
    }
766
767
    return (array)$this->array;
768
  }/**
769
   * Whether or not an offset exists.
770
   *
771
   * @param mixed $offset
772
   *
773
   * @return bool
774
   */
775 24
  public function offsetExists($offset)
776
  {
777 24
    return isset($this->array[$offset]);
778
  }
779
780
  /**
781
   * Search for the value of the current array via $index.
782
   *
783
   * @param mixed $index
784
   *
785
   * @return Arrayy will return a empty Arrayy if the value wasn't found
786
   */
787 7
  public function searchValue($index)
788
  {
789
    // init
790 7
    $return = array();
791
792 7
    if (null !== $index) {
793 7
      $keyExists = isset($this->array[$index]);
794
795 7
      if ($keyExists !== false) {
796 5
        $return = array($this->array[$index]);
797 5
      }
798 7
    }
799
800 7
    return static::create($return);
801
  }
802
803
  /**
804
   * Check if all items in current array match a truth test.
805
   *
806
   * @param \Closure $closure
807
   *
808
   * @return bool
809
   */
810 9 View Code Duplication
  public function matches(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
811
  {
812
    // Reduce the array to only booleans
813 9
    $array = $this->each($closure);
814
815
    // Check the results
816 9
    if (count($array) === 0) {
817 2
      return true;
818
    }
819
820 7
    $array = array_search(false, $array->toArray(), false);
821
822 7
    return is_bool($array);
823
  }
824
825
  /**
826
   * Iterate over the current array and modify the array's value.
827
   *
828
   * @param \Closure $closure
829
   *
830
   * @return Arrayy
831
   */
832 22 View Code Duplication
  public function each(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
833
  {
834 22
    $array = $this->array;
835
836 22
    foreach ($array as $key => &$value) {
837 18
      $value = $closure($value, $key);
838 22
    }
839
840 22
    return static::create($array);
841
  }
842
843
  /**
844
   * alias: for "Arrayy->getArray()"
845
   */
846 153
  public function toArray()
847
  {
848 153
    return $this->getArray();
849
  }
850
851
  /**
852
   * Check if any item in the current array matches a truth test.
853
   *
854
   * @param \Closure $closure
855
   *
856
   * @return bool
857
   */
858 9 View Code Duplication
  public function matchesAny(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
859
  {
860
    // Reduce the array to only booleans
861 9
    $array = $this->each($closure);
862
863
    // Check the results
864 9
    if (count($array) === 0) {
865 2
      return true;
866
    }
867
868 7
    $array = array_search(true, $array->toArray(), false);
869
870 7
    return is_int($array);
871
  }
872
873
  /**
874
   * Check whether array is associative or not.
875
   *
876
   * @return bool Returns true if associative, false otherwise
877
   */
878 14
  public function isAssoc()
879
  {
880 14
    if ($this->isEmpty()) {
881 2
      return false;
882
    }
883
884 12
    foreach ($this->getKeys()->getArray() as $key) {
885 12
      if (!is_string($key)) {
886 10
        return false;
887
      }
888 2
    }
889
890 2
    return true;
891
  }
892
893
  /**
894
   * Check whether the array is empty or not.
895
   *
896
   * @return bool Returns true if empty, false otherwise
897
   */
898 22
  public function isEmpty()
899
  {
900 22
    return !$this->array;
901
  }
902
903
/**
904
   * alias: for "Arrayy->keys()"
905
   *
906
   * @return Arrayy
907
   */
908 15
  public function getKeys()
909
  {
910 15
    return $this->keys();
911
  }
912
913
    /**
914
   * Get all keys from the current array.
915
   *
916
   * @return Arrayy
917
   */
918 20
  public function keys()
919
  {
920 20
    $array = array_keys((array)$this->array);
921
922 20
    return static::create($array);
923
  }
924
  /**
925
   * Check whether array is numeric or not.
926
   *
927
   * @return bool Returns true if numeric, false otherwise
928
   */
929 4
  public function isNumeric()
930
  {
931 4
    if ($this->isEmpty()) {
932 1
      return false;
933
    }
934
935 3
    foreach ($this->getKeys() as $key) {
936 3
      if (!is_int($key)) {
937 2
        return false;
938
      }
939 2
    }
940
941 1
    return true;
942
  }/**
943
   * Unset an offset.
944
   *
945
   * @param mixed $offset
946
   */
947 5
  public function offsetUnset($offset)
948
  {
949 5
    if ($this->offsetExists($offset)) {
950 3
      unset($this->array[$offset]);
951 3
    }
952 5
  }
953
954
  /**
955
   * Check if the current array is a multi-array.
956
   *
957
   * @return bool
958
   */
959 13
  public function isMultiArray()
960
  {
961 13
    return !(count($this->array) === count($this->array, COUNT_RECURSIVE));
962
  }
963
964
  /**
965
   * Check if an item is in the current array.
966
   *
967
   * @param mixed $value
968
   *
969
   * @return bool
970
   */
971 13
  public function contains($value)
972
  {
973 13
    return in_array($value, $this->array, true);
974
  }
975
976
  /**
977
   * Check if the given key/index exists in the array.
978
   *
979
   * @param mixed $key Key/index to search for
980
   *
981
   * @return bool Returns true if the given key/index exists in the array, false otherwise
982
   */
983 4
  public function containsKey($key)
984
  {
985 4
    return array_key_exists($key, $this->array);
986
  }
987
988
  /**
989
   * Returns the average value of the current array.
990
   *
991
   * @param int $decimals The number of decimals to return
992
   *
993
   * @return int|double The average value
994
   */
995 10
  public function average($decimals = null)
996
  {
997 10
    $count = $this->count();
998
999 10
    if (!$count) {
1000 2
      return 0;
1001
    }
1002
1003 8
    if (!is_int($decimals)) {
1004 3
      $decimals = null;
1005 3
    }
1006
1007 8
    return round(array_sum($this->array) / $count, $decimals);
1008
  }
1009
1010
  /**
1011
   * Count the values from the current array.
1012
   *
1013
   * INFO: only a alias for "$arrayy->size()"
1014
   *
1015
   * @return int
1016
   */
1017 10
  public function length()
1018
  {
1019 10
    return $this->size();
1020
  }
1021
1022
  /**
1023
   * Get the max value from an array.
1024
   *
1025
   * @return mixed
1026
   */
1027 10
  public function max()
1028
  {
1029 10
    if ($this->count() === 0) {
1030 1
      return false;
1031
    }
1032
1033 9
    return max($this->array);
1034
  }
1035
1036
/**
1037
   * Get the min value from an array.
1038
   *
1039
   * @return mixed
1040
   */
1041 10
  public function min()
1042
  {
1043 10
    if ($this->count() === 0) {
1044 1
      return false;
1045
    }
1046
1047 9
    return min($this->array);
1048
  }
1049
1050
  /**
1051
   * Find the first item in an array that passes the truth test,
1052
   *  otherwise return false
1053
   *
1054
   * @param \Closure $closure
1055
   *
1056
   * @return mixed|false false if we did not find the value
1057
   */
1058 8
  public function find(\Closure $closure)
1059
  {
1060 8
    foreach ($this->array as $key => $value) {
1061 6
      if ($closure($value, $key)) {
1062 5
        return $value;
1063
      }
1064 5
    }
1065
1066 3
    return false;
1067
  }
1068
1069
    /**
1070
   * WARNING!!! -> Clear the current array.
1071
   *
1072
   * @return $this will always return an empty Arrayy object
1073
   */
1074 4
  public function clear()
1075
  {
1076 4
    $this->array = array();
1077
1078 4
    return $this;
1079
  }
1080
  /**
1081
   * Clean all falsy values from an array.
1082
   *
1083
   * @return Arrayy
1084
   */
1085 8
  public function clean()
1086
  {
1087 8
    return $this->filter(
1088
        function ($value) {
1089 7
          return (bool)$value;
1090
        }
1091 8
    );
1092
  }/**
1093
   * Returns the value at specified offset.
1094
   *
1095
   * @param mixed $offset
1096
   *
1097
   * @return mixed return null if the offset did not exists
1098
   */
1099 15
  public function offsetGet($offset)
1100
  {
1101 15
    return $this->offsetExists($offset) ? $this->array[$offset] : null;
1102
  }
1103
1104
  /**
1105
   * Find all items in an array that pass the truth test.
1106
   *
1107
   * @param \Closure|null $closure
1108
   *
1109
   * @return Arrayy
1110
   */
1111 8
  public function filter($closure = null)
1112
  {
1113 8
    if (!$closure) {
1114 1
      return $this->clean();
1115
    }
1116
1117 8
    $array = array_filter($this->array, $closure);
1118
1119 8
    return static::create($array);
1120
  }
1121
1122
  /**
1123
   * Get a random value from an array, with the ability to skew the results.
1124
   *
1125
   * Example: randomWeighted(['foo' => 1, 'bar' => 2]) has a 66% chance of returning bar.
1126
   *
1127
   * @param array    $array
1128
   * @param null|int $number how many values you will take?
1129
   *
1130
   * @return Arrayy
1131
   */
1132 9
  public function randomWeighted(array $array, $number = null)
1133
  {
1134 9
    $options = array();
1135 9
    foreach ($array as $option => $weight) {
1136 9
      if ($this->searchIndex($option) !== false) {
1137 2
        for ($i = 0; $i < $weight; ++$i) {
1138 1
          $options[] = $option;
1139 1
        }
1140 2
      }
1141 9
    }
1142
1143 9
    return $this->mergeAppendKeepIndex($options)->random($number);
1144
  }
1145
1146
  /**
1147
   * Search for the first index of the current array via $value.
1148
   *
1149
   * @param mixed $value
1150
   *
1151
   * @return mixed
1152
   */
1153 20
  public function searchIndex($value)
1154
  {
1155 20
    return array_search($value, $this->array, true);
1156
  }
1157
1158
  /**
1159
   * Merge the new $array into the current array.
1160
   *
1161
   * - keep key,value from the current array, also if the index is in the new $array
1162
   *
1163
   * @param array $array
1164
   * @param bool  $recursive
1165
   *
1166
   * @return Arrayy
1167
   */
1168 25 View Code Duplication
  public function mergeAppendKeepIndex(array $array = array(), $recursive = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1169
  {
1170 25
    if (true === $recursive) {
1171 4
      $result = array_replace_recursive($this->array, $array);
1172 4
    } else {
1173 21
      $result = array_replace($this->array, $array);
1174
    }
1175
1176 25
    return static::create($result);
1177
  }
1178
1179
  /**
1180
   * alias: for "Arrayy->searchIndex()"
1181
   *
1182
   * @param mixed $value Value to search for
1183
   *
1184
   * @return mixed
1185
   */
1186 4
  public function indexOf($value)
1187
  {
1188 4
    return $this->searchIndex($value);
1189
  }
1190
1191
/**
1192
   * Return a boolean flag which indicates whether the two input arrays have any common elements.
1193
   *
1194
   * @param array $search
1195
   *
1196
   * @return bool
1197
   */
1198 1
  public function intersects(array $search)
1199
  {
1200 1
    return count($this->intersection($search)->array) > 0;
1201
  }
1202
1203
  /**
1204
   * Return an array with all elements found in input array.
1205
   *
1206
   * @param array $search
1207
   *
1208
   * @return Arrayy
1209
   */
1210 2
  public function intersection(array $search)
1211
  {
1212 2
    $result = array_values(array_intersect($this->array, $search));
1213
1214 2
    return static::create($result);
1215
  }
1216
1217
  /**
1218
   * Get the last value(s) from the current array.
1219
   *
1220
   * @param int|null $number
1221
   *
1222
   * @return Arrayy
1223
   */
1224 15
  public function last($number = null)
1225
  {
1226 15
    if ($number === null) {
1227 11
      $poppedValue = (array)$this->pop();
1228 11
      $arrayy = static::create($poppedValue);
1229 11
    } else {
1230 4
      $number = (int)$number;
1231 4
      $arrayy = $this->rest(-$number);
1232
    }
1233
1234 15
    return $arrayy;
1235
  }
1236
1237
    /**
1238
   * Pop a specified value off the end of the current array.
1239
   *
1240
   * @return mixed The popped element from the current array.
1241
   */
1242 15
  public function pop()
1243
  {
1244 15
    return array_pop($this->array);
1245
  }
1246
  /**
1247
   * Get the last elements from index $from until the end of this array.
1248
   *
1249
   * @param int $from
1250
   *
1251
   * @return Arrayy
1252
   */
1253 16
  public function rest($from = 1)
1254
  {
1255 16
    $result = array_splice($this->array, $from);
1256
1257 16
    return static::create($result);
1258
  }/**
1259
   * Returns a new ArrayIterator, thus implementing the IteratorAggregate interface.
1260
   *
1261
   * @return \ArrayIterator An iterator for the values in the array.
1262
   */
1263 16
  public function getIterator()
1264
  {
1265 16
    return new \ArrayIterator($this->array);
1266
  }
1267
1268
  /**
1269
   * Get everything but the last..$to items.
1270
   *
1271
   * @param int $to
1272
   *
1273
   * @return Arrayy
1274
   */
1275 12
  public function initial($to = 1)
1276
  {
1277 12
    $slice = count($this->array) - $to;
1278
1279 12
    return $this->first($slice);
1280
  }
1281
1282
  /**
1283
   * Extract a slice of the array.
1284
   *
1285
   * @param int      $offset       Slice begin index
1286
   * @param int|null $length       Length of the slice
1287
   * @param bool     $preserveKeys Whether array keys are preserved or no
1288
   *
1289
   * @return static A slice of the original array with length $length
1290
   */
1291 4
  public function slice($offset, $length = null, $preserveKeys = false)
1292
  {
1293 4
    $result = array_slice($this->array, $offset, $length, $preserveKeys);
1294
1295 4
    return static::create($result);
1296
  }
1297
1298
  /**
1299
   * Iterate over an array and execute a callback for each loop.
1300
   *
1301
   * @param \Closure $closure
1302
   *
1303
   * @return Arrayy
1304
   */
1305 2 View Code Duplication
  public function at(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1306
  {
1307 2
    $array = $this->array;
1308
1309 2
    foreach ($array as $key => $value) {
1310 2
      $closure($value, $key);
1311 2
    }
1312
1313 2
    return static::create($array);
1314
  }
1315
1316
  /**
1317
   * Merge the new $array into the current array.
1318
   *
1319
   * - replace duplicate assoc-keys from the current array with the key,values from the new $array
1320
   * - create new indexes
1321
   *
1322
   * @param array $array
1323
   * @param bool  $recursive
1324
   *
1325
   * @return Arrayy
1326
   */
1327 16 View Code Duplication
  public function mergeAppendNewIndex(array $array = array(), $recursive = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1328
  {
1329 16
    if (true === $recursive) {
1330 4
      $result = array_merge_recursive($this->array, $array);
1331 4
    } else {
1332 12
      $result = array_merge($this->array, $array);
1333
    }
1334
1335 16
    return static::create($result);
1336
  }
1337
1338
  /**
1339
   * Merge the current array into the new $array.
1340
   *
1341
   * - replace duplicate assoc-keys from new $array with the key,values from the current array
1342
   * - create new indexes
1343
   *
1344
   * @param array $array
1345
   * @param bool  $recursive
1346
   *
1347
   * @return Arrayy
1348
   */
1349 16 View Code Duplication
  public function mergePrependNewIndex(array $array = array(), $recursive = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1350
  {
1351 16
    if (true === $recursive) {
1352 4
      $result = array_merge_recursive($array, $this->array);
1353 4
    } else {
1354 12
      $result = array_merge($array, $this->array);
1355
    }
1356
1357 16
    return static::create($result);
1358
  }
1359
1360
  /**
1361
   * Merge the the current array into the $array.
1362
   *
1363
   * - use key,value from the new $array, also if the index is in the current array
1364
   *
1365
   * @param array $array
1366
   * @param bool  $recursive
1367
   *
1368
   * @return Arrayy
1369
   */
1370 16 View Code Duplication
  public function mergePrependKeepIndex(array $array = array(), $recursive = false)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1371
  {
1372 16
    if (true === $recursive) {
1373 4
      $result = array_replace_recursive($array, $this->array);
1374 4
    } else {
1375 12
      $result = array_replace($array, $this->array);
1376
    }
1377
1378 16
    return static::create($result);
1379
  }
1380
1381
  /**
1382
   * Return values that are only in the current array.
1383
   *
1384
   * @param array $array
1385
   *
1386
   * @return Arrayy
1387
   */
1388 12
  public function diff(array $array = array())
1389
  {
1390 12
    $result = array_diff($this->array, $array);
1391
1392 12
    return static::create($result);
1393
  }
1394
1395
  /**
1396
   * Return values that are only in the new $array.
1397
   *
1398
   * @param array $array
1399
   *
1400
   * @return Arrayy
1401
   */
1402 8
  public function diffReverse(array $array = array())
1403
  {
1404 8
    $result = array_diff($array, $this->array);
1405
1406 8
    return static::create($result);
1407
  }
1408
1409
  /**
1410
   * Replace the first matched value in an array.
1411
   *
1412
   * @param mixed $search
1413
   * @param mixed $replacement
1414
   *
1415
   * @return Arrayy
1416
   */
1417 3
  public function replaceOneValue($search, $replacement = '')
1418
  {
1419 3
    $array = $this->array;
1420 3
    $key = array_search($search, $array, true);
1421
1422 3
    if ($key !== false) {
1423 3
      $array[$key] = $replacement;
1424 3
    }
1425
1426 3
    return static::create($array);
1427
  }
1428
1429
  /**
1430
   * Replace values in the current array.
1431
   *
1432
   * @param string $search      The string to replace.
1433
   * @param string $replacement What to replace it with.
1434
   *
1435
   * @return Arrayy
1436
   */
1437 1
  public function replaceValues($search, $replacement = '')
1438
  {
1439 1
    $array = $this->each(
1440
        function ($value) use ($search, $replacement) {
1441 1
          return UTF8::str_replace($search, $replacement, $value);
1442
        }
1443 1
    );
1444
1445 1
    return static::create($array);
0 ignored issues
show
Documentation introduced by
$array is of type object<Arrayy\Arrayy>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1446
  }
1447
1448
  /**
1449
   * Replace the keys in an array with another set.
1450
   *
1451
   * @param array $keys An array of keys matching the array's size
1452
   *
1453
   * @return Arrayy
1454
   */
1455 1
  public function replaceKeys(array $keys)
1456
  {
1457 1
    $values = array_values($this->array);
1458 1
    $result = array_combine($keys, $values);
1459
1460 1
    return static::create($result);
1461
  }
1462
1463
  /**
1464
   * Create an array using the current array as keys and the other array as values.
1465
   *
1466
   * @param array $array Values array
1467
   *
1468
   * @return Arrayy Arrayy object with values from the other array.
1469
   */
1470 1
  public function replaceAllValues(array $array)
1471
  {
1472 1
    $result = array_combine($this->array, $array);
1473
1474 1
    return static::create($result);
1475
  }
1476
1477
  /**
1478
   * Create an array using the current array as values and the other array as keys.
1479
   *
1480
   * @param array $keys Keys array
1481
   *
1482
   * @return Arrayy Arrayy object with keys from the other array.
1483
   */
1484 1
  public function replaceAllKeys(array $keys)
1485
  {
1486 1
    $result = array_combine($keys, $this->array);
1487
1488 1
    return static::create($result);
1489
  }
1490
1491
  /**
1492
   * Shuffle the current array.
1493
   *
1494
   * @return Arrayy
1495
   */
1496 1
  public function shuffle()
1497
  {
1498 1
    $array = $this->array;
1499
1500 1
    shuffle($array);
1501
1502 1
    return static::create($array);
1503
  }
1504
1505
  /**
1506
   * Split an array in the given amount of pieces.
1507
   *
1508
   * @param int  $numberOfPieces
1509
   * @param bool $keepKeys
1510
   *
1511
   * @return array
1512
   */
1513 1
  public function split($numberOfPieces = 2, $keepKeys = false)
1514
  {
1515 1
    if (count($this->array) === 0) {
1516 1
      $result = array();
1517 1
    } else {
1518 1
      $numberOfPieces = (int)$numberOfPieces;
1519 1
      $splitSize = ceil(count($this->array) / $numberOfPieces);
1520 1
      $result = array_chunk($this->array, $splitSize, $keepKeys);
1521
    }
1522
1523 1
    return static::create($result);
1524
  }
1525
1526
  /**
1527
   * Create a chunked version of this array.
1528
   *
1529
   * @param int  $size         Size of each chunk
1530
   * @param bool $preserveKeys Whether array keys are preserved or no
1531
   *
1532
   * @return static A new array of chunks from the original array
1533
   */
1534 4
  public function chunk($size, $preserveKeys = false)
1535
  {
1536 4
    $result = array_chunk($this->array, $size, $preserveKeys);
1537
1538 4
    return static::create($result);
1539
  }
1540
1541
  /**
1542
   * Returns the values from a single column of the input array, identified by
1543
   * the $columnKey, can be used to extract data-columns from multi-arrays.
1544
   *
1545
   * Info: Optionally, you may provide an $indexKey to index the values in the returned
1546
   * array by the values from the $indexKey column in the input array.
1547
   *
1548
   * @param mixed $columnKey
1549
   * @param mixed $indexKey
1550
   *
1551
   * @return Arrayy
1552
   */
1553 1
  public function getColumn($columnKey = null, $indexKey = null)
1554
  {
1555 1
    $result = array_column($this->array, $columnKey, $indexKey);
1556
1557 1
    return static::create($result);
0 ignored issues
show
Bug introduced by
It seems like $result defined by array_column($this->array, $columnKey, $indexKey) on line 1555 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...
1558
  }
1559
1560
  /**
1561
   * Invoke a function on all of an array's values.
1562
   *
1563
   * @param mixed $callable
1564
   * @param array $arguments
1565
   *
1566
   * @return Arrayy
1567
   */
1568 1
  public function invoke($callable, $arguments = array())
1569
  {
1570
    // If one argument given for each iteration, create an array for it.
1571 1
    if (!is_array($arguments)) {
1572 1
      $arguments = StaticArrayy::repeat($arguments, count($this->array))->getArray();
1573 1
    }
1574
1575
    // If the callable has arguments, pass them.
1576 1
    if ($arguments) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $arguments of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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

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

Loading history...
1577 1
      $array = array_map($callable, $this->array, $arguments);
1578 1
    } else {
1579 1
      $array = array_map($callable, $this->array);
1580
    }
1581
1582 1
    return static::create($array);
1583
  }
1584
1585
  /**
1586
   * Apply the given function to the every element of the array,
1587
   * collecting the results.
1588
   *
1589
   * @param callable $callable
1590
   *
1591
   * @return Arrayy Arrayy object with modified elements
1592
   */
1593 4
  public function map($callable)
1594
  {
1595 4
    $result = array_map($callable, $this->array);
1596
1597 4
    return static::create($result);
1598
  }
1599
1600
  /**
1601
   * Check if a value is in the current array using a closure.
1602
   *
1603
   * @param \Closure $closure
1604
   *
1605
   * @return bool Returns true if the given value is found, false otherwise
1606
   */
1607 4
  public function exists(\Closure $closure)
1608
  {
1609 4
    $isExists = false;
1610 4
    foreach ($this->array as $key => $value) {
1611 3
      if ($closure($value, $key)) {
1612 1
        $isExists = true;
1613 1
        break;
1614
      }
1615 4
    }
1616
1617 4
    return $isExists;
1618
  }
1619
1620
  /**
1621
   * Return all items that fail the truth test.
1622
   *
1623
   * @param \Closure $closure
1624
   *
1625
   * @return Arrayy
1626
   */
1627 1 View Code Duplication
  public function reject(\Closure $closure)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1628
  {
1629 1
    $filtered = array();
1630
1631 1
    foreach ($this->array as $key => $value) {
1632 1
      if (!$closure($value, $key)) {
1633 1
        $filtered[$key] = $value;
1634 1
      }
1635 1
    }
1636
1637 1
    return static::create($filtered);
1638
  }
1639
1640
  /**
1641
   * Replace a key with a new key/value pair.
1642
   *
1643
   * @param $replace
1644
   * @param $key
1645
   * @param $value
1646
   *
1647
   * @return Arrayy
1648
   */
1649 1
  public function replace($replace, $key, $value)
1650
  {
1651 1
    $this->remove($replace);
1652
1653 1
    return $this->set($key, $value);
1654
  }
1655
1656
  /**
1657
   * Remove a value from the current array (optional using dot-notation).
1658
   *
1659
   * @param mixed $key
1660
   *
1661
   * @return Arrayy
1662
   */
1663 17
  public function remove($key)
1664
  {
1665
    // Recursive call
1666 17
    if (is_array($key)) {
1667
      foreach ($key as $k) {
1668
        $this->internalRemove($k);
1669
      }
1670
1671
      return static::create($this->array);
1672
    }
1673
1674 17
    $this->internalRemove($key);
1675
1676 17
    return static::create($this->array);
1677
  }
1678
1679
  /**
1680
   * Internal mechanics of remove method.
1681
   *
1682
   * @param $key
1683
   *
1684
   * @return boolean
1685
   */
1686 17
  protected function internalRemove($key)
1687
  {
1688
    // Explode keys
1689 17
    $keys = explode('.', $key);
1690
1691
    // Crawl though the keys
1692 17 View Code Duplication
    while (count($keys) > 1) {
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...
1693
      $key = array_shift($keys);
1694
1695
      if (!$this->has($key)) {
1696
        return false;
1697
      }
1698
1699
      $this->array = &$this->array[$key];
1700
    }
1701
1702 17
    $key = array_shift($keys);
1703
1704 17
    unset($this->array[$key]);
1705
1706 17
    return true;
1707
  }
1708
1709
  /**
1710
   * Check if an array has a given key.
1711
   *
1712
   * @param mixed $key
1713
   *
1714
   * @return bool
1715
   */
1716 18
  public function has($key)
1717
  {
1718
    // Generate unique string to use as marker.
1719 18
    $unFound = (string)uniqid('arrayy', true);
1720
1721 18
    return $this->get($key, $unFound) !== $unFound;
1722
  }
1723
1724
  /**
1725
   * Set a value for the current array (optional using dot-notation).
1726
   *
1727
   * @param string $key   The key to set
1728
   * @param mixed  $value Its value
1729
   *
1730
   * @return Arrayy
1731
   */
1732 14
  public function set($key, $value)
1733
  {
1734 14
    $this->internalSet($key, $value);
1735
1736 14
    return static::create($this->array);
1737
  }
1738
1739
  /**
1740
   * Internal mechanic of set method.
1741
   *
1742
   * @param mixed $key
1743
   * @param mixed $value
1744
   *
1745
   * @return bool
1746
   */
1747 14
  protected function internalSet($key, $value)
1748
  {
1749 14
    if (null === $key) {
1750
      return false;
1751
    }
1752
1753
    // Explode the keys
1754 14
    $keys = explode('.', $key);
1755
1756
    // Crawl through the keys
1757 14 View Code Duplication
    while (count($keys) > 1) {
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...
1758
      $key = array_shift($keys);
1759
1760
      $this->array[$key] = $this->get(array(), null, $key);
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1761
      $this->array = &$this->array[$key];
1762
    }
1763
1764
    // Bind final tree on the array
1765 14
    $key = array_shift($keys);
1766
1767 14
    $this->array[$key] = $value;
1768
1769 14
    return true;
1770
  }
1771
1772
  /**
1773
   * Get a value from a array and set it if it was not.
1774
   *
1775
   * WARNING: this method only set the value, if the $key is not already set
1776
   *
1777
   * @param string $key     The key
1778
   * @param mixed  $default The default value to set if it isn't
1779
   *
1780
   * @return mixed
1781
   */
1782 9
  public function setAndGet($key, $default = null)
1783
  {
1784
    // If the key doesn't exist, set it
1785 9
    if (!$this->has($key)) {
1786 4
      $this->array = $this->set($key, $default)->getArray();
1787 4
    }
1788
1789 9
    return $this->get($key);
1790
  }
1791
1792
  /**
1793
   * Remove the first value from the current array.
1794
   *
1795
   * @return Arrayy
1796
   */
1797 7
  public function removeFirst()
1798
  {
1799 7
    array_shift($this->array);
1800
1801 7
    return static::create($this->array);
1802
  }
1803
1804
  /**
1805
   * Remove the last value from the current array.
1806
   *
1807
   * @return Arrayy
1808
   */
1809 7
  public function removeLast()
1810
  {
1811 7
    array_pop($this->array);
1812
1813 7
    return static::create($this->array);
1814
  }
1815
1816
  /**
1817
   * Removes a particular value from an array (numeric or associative).
1818
   *
1819
   * @param mixed $value
1820
   *
1821
   * @return Arrayy
1822
   */
1823 7
  public function removeValue($value)
1824
  {
1825 7
    $isNumericArray = true;
1826 7
    foreach ($this->array as $key => $item) {
1827 6
      if ($item === $value) {
1828 6
        if (!is_int($key)) {
1829
          $isNumericArray = false;
1830
        }
1831 6
        unset($this->array[$key]);
1832 6
      }
1833 7
    }
1834
1835 7
    if ($isNumericArray) {
1836 7
      $this->array = array_values($this->array);
1837 7
    }
1838
1839 7
    return static::create($this->array);
1840
  }
1841
1842
  /**
1843
   * Pad array to the specified size with a given value.
1844
   *
1845
   * @param int   $size  Size of the result array
1846
   * @param mixed $value Empty value by default
1847
   *
1848
   * @return Arrayy Arrayy object padded to $size with $value
1849
   */
1850 4
  public function pad($size, $value)
1851
  {
1852 4
    $result = array_pad($this->array, $size, $value);
1853
1854 4
    return static::create($result);
1855
  }
1856
1857
  /**
1858
   * Prepend a value to an array.
1859
   *
1860
   * @param mixed $value
1861
   *
1862
   * @return Arrayy
1863
   */
1864 7
  public function prepend($value)
1865
  {
1866 7
    array_unshift($this->array, $value);
1867
1868 7
    return static::create($this->array);
1869
  }
1870
1871
  /**
1872
   * alias: for "Arrayy->append()"
1873
   *
1874
   * @param $value
1875
   *
1876
   * @return $this
1877
   */
1878 1
  public function add($value)
1879
  {
1880 1
    $this->array[] = $value;
1881
1882 1
    return $this;
1883
  }
1884
1885
  /**
1886
   * Create a numerically re-indexed Arrayy object.
1887
   *
1888
   * @return Arrayy The new instance with re-indexed array-elements
1889
   */
1890 8
  public function reindex()
1891
  {
1892 8
    $this->array = array_values($this->array);
1893
1894 8
    return static::create($this->array);
1895
  }
1896
1897
  /**
1898
   * Return the array in the reverse order.
1899
   *
1900
   * @return Arrayy
1901
   */
1902 7
  public function reverse()
1903
  {
1904 7
    $this->array = array_reverse($this->array);
1905
1906 7
    return static::create($this->array);
1907
  }
1908
1909
  /**
1910
   * Custom sort by value via "usort"
1911
   *
1912
   * @link http://php.net/manual/en/function.usort.php
1913
   *
1914
   * @param callable $func
1915
   *
1916
   * @return $this
1917
   */
1918 4
  public function customSortValues($func)
1919
  {
1920 4
    usort($this->array, $func);
1921
1922 4
    return $this;
1923
  }
1924
1925
  /**
1926
   * Custom sort by index via "uksort"
1927
   *
1928
   * @link http://php.net/manual/en/function.uksort.php
1929
   *
1930
   * @param callable $func
1931
   *
1932
   * @return $this
1933
   */
1934 4
  public function customSortKeys($func)
1935
  {
1936 4
    uksort($this->array, $func);
1937
1938 4
    return $this;
1939
  }
1940
1941
  /**
1942
   * Sort the current array by key.
1943
   *
1944
   * @link http://php.net/manual/en/function.ksort.php
1945
   * @link http://php.net/manual/en/function.krsort.php
1946
   *
1947
   * @param int|string $direction use SORT_ASC or SORT_DESC
1948
   * @param int        $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
1949
   *
1950
   * @return $this
1951
   */
1952 18
  public function sortKeys($direction = SORT_ASC, $strategy = SORT_REGULAR)
1953
  {
1954 18
    $this->sorterKeys($this->array, $direction, $strategy);
1955
1956 18
    return $this;
1957
  }
1958
1959
  /**
1960
   * sorting keys
1961
   *
1962
   * @param array $elements
1963
   * @param int   $direction
1964
   * @param int   $strategy
1965
   */
1966 18
  protected function sorterKeys(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR)
1967
  {
1968 18
    $direction = $this->getDirection($direction);
1969
1970
    switch ($direction) {
1971 18
      case 'desc':
1972 18
      case SORT_DESC:
1973 6
        krsort($elements, $strategy);
1974 6
        break;
1975 13
      case 'asc':
1976 13
      case SORT_ASC:
1977 13
      default:
1978 13
        ksort($elements, $strategy);
1979 13
    }
1980 18
  }
1981
1982
  /**
1983
   * Get correct PHP constant for direction.
1984
   *
1985
   * @param int|string $direction
1986
   *
1987
   * @return int
1988
   */
1989 38
  protected function getDirection($direction)
1990
  {
1991 38
    if (is_string($direction)) {
1992 10
      $direction = strtolower($direction);
1993
1994 10
      if ($direction === 'desc') {
1995 2
        $direction = SORT_DESC;
1996 2
      } else {
1997 8
        $direction = SORT_ASC;
1998
      }
1999 10
    }
2000
2001
    if (
2002
        $direction !== SORT_DESC
2003 38
        &&
2004
        $direction !== SORT_ASC
2005 38
    ) {
2006
      $direction = SORT_ASC;
2007
    }
2008
2009 38
    return $direction;
2010
  }
2011
2012
  /**
2013
   * Sort the current array by value.
2014
   *
2015
   * @param int $direction use SORT_ASC or SORT_DESC
2016
   * @param int $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
2017
   *
2018
   * @return Arrayy
2019
   */
2020 1
  public function sortValueKeepIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
2021
  {
2022 1
    return $this->sort($direction, $strategy, true);
2023
  }
2024
2025
  /**
2026
   * Sort the current array and optional you can keep the keys.
2027
   *
2028
   * @param string|int $direction use SORT_ASC or SORT_DESC
2029
   * @param int|string $strategy
2030
   * @param bool       $keepKeys
2031
   *
2032
   * @return Arrayy
2033
   */
2034 19
  public function sort($direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
2035
  {
2036 19
    $this->sorting($this->array, $direction, $strategy, $keepKeys);
2037
2038 19
    return $this;
2039
  }
2040
2041
  /**
2042
   * @param array      &$elements
2043
   * @param int|string $direction
2044
   * @param int        $strategy
2045
   * @param bool       $keepKeys
2046
   */
2047 19
  protected function sorting(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
2048
  {
2049 19
    $direction = $this->getDirection($direction);
2050
2051 19
    if (!$strategy) {
2052 19
      $strategy = SORT_REGULAR;
2053 19
    }
2054
2055
    switch ($direction) {
2056 19
      case 'desc':
2057 19
      case SORT_DESC:
2058 9
        if ($keepKeys) {
2059 5
          arsort($elements, $strategy);
2060 5
        } else {
2061 4
          rsort($elements, $strategy);
2062
        }
2063 9
        break;
2064 10
      case 'asc':
2065 10
      case SORT_ASC:
2066 10
      default:
2067 10
        if ($keepKeys) {
2068 4
          asort($elements, $strategy);
2069 4
        } else {
2070 6
          sort($elements, $strategy);
2071
        }
2072 10
    }
2073 19
  }
2074
2075
  /**
2076
   * Sort the current array by value.
2077
   *
2078
   * @param int $direction use SORT_ASC or SORT_DESC
2079
   * @param int $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
2080
   *
2081
   * @return Arrayy
2082
   */
2083 1
  public function sortValueNewIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
2084
  {
2085 1
    return $this->sort($direction, $strategy, false);
2086
  }
2087
2088
  /**
2089
   * Sort a array by value, by a closure or by a property.
2090
   *
2091
   * - If the sorter is null, the array is sorted naturally.
2092
   * - Associative (string) keys will be maintained, but numeric keys will be re-indexed.
2093
   *
2094
   * @param null       $sorter
2095
   * @param string|int $direction
2096
   * @param int        $strategy
2097
   *
2098
   * @return Arrayy
2099
   */
2100 1
  public function sorter($sorter = null, $direction = SORT_ASC, $strategy = SORT_REGULAR)
2101
  {
2102 1
    $array = (array)$this->array;
2103 1
    $direction = $this->getDirection($direction);
2104
2105
    // Transform all values into their results.
2106 1
    if ($sorter) {
2107 1
      $arrayy = new self($array);
2108
2109 1
      $that = $this;
2110 1
      $results = $arrayy->each(
2111
          function ($value) use ($sorter, $that) {
2112 1
            return is_callable($sorter) ? $sorter($value) : $that->get($sorter, null, $value);
2113
          }
2114 1
      );
2115
2116 1
      $results = $results->getArray();
2117 1
    } else {
2118 1
      $results = $array;
2119
    }
2120
2121
    // Sort by the results and replace by original values
2122 1
    array_multisort($results, $direction, $strategy, $array);
2123
2124 1
    return static::create($array);
2125
  }
2126
2127
  /**
2128
   * Exchanges all keys with their associated values in an array.
2129
   *
2130
   * @return Arrayy
2131
   */
2132 1
  public function flip()
2133
  {
2134 1
    $this->array = array_flip($this->array);
2135
2136 1
    return static::create($this->array);
2137
  }
2138
2139
  /**
2140
   * Apply the given function to every element in the array,
2141
   * discarding the results.
2142
   *
2143
   * @param callable $callable
2144
   * @param bool     $recursive Whether array will be walked recursively or no
2145
   *
2146
   * @return Arrayy An Arrayy object with modified elements
2147
   */
2148 8
  public function walk($callable, $recursive = false)
2149
  {
2150 8
    if (true === $recursive) {
2151 4
      array_walk_recursive($this->array, $callable);
2152 4
    } else {
2153 4
      array_walk($this->array, $callable);
2154
    }
2155
2156 8
    return $this;
2157
  }
2158
2159
  /**
2160
   * Reduce the current array via callable e.g. anonymous-function.
2161
   *
2162
   * @param mixed $callable
2163
   * @param array $init
2164
   *
2165
   * @return Arrayy
2166
   */
2167 2
  public function reduce($callable, array $init = array())
2168
  {
2169 2
    $this->array = array_reduce($this->array, $callable, $init);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_reduce($this->array, $callable, $init) 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...
2170
2171 2
    return static::create($this->array);
2172
  }
2173
2174
  /**
2175
   * Return a duplicate free copy of the current array.
2176
   *
2177
   * @return Arrayy
2178
   */
2179 7
  public function unique()
2180
  {
2181 7
    $this->array = array_reduce(
0 ignored issues
show
Documentation Bug introduced by
It seems like array_reduce($this->arra...esultArray; }, array()) of type * is incompatible with the declared type array of property $array.

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

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

Loading history...
2182 7
        $this->array,
2183 7
        function ($resultArray, $value) {
2184 6
          if (in_array($value, $resultArray, true) === false) {
2185 6
            $resultArray[] = $value;
2186 6
          }
2187
2188 6
          return $resultArray;
2189 7
        },
2190 7
        array()
2191 7
    );
2192
2193 7
    return static::create($this->array);
2194
  }
2195
2196
  /**
2197
   * Convert the current array to JSON.
2198
   *
2199
   * @param null $options e.g. JSON_PRETTY_PRINT
2200
   *
2201
   * @return string
2202
   */
2203 5
  public function toJson($options = null)
2204
  {
2205 5
    return UTF8::json_encode($this->array, $options);
2206
  }
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
}
2226