Completed
Push — master ( d84682...296916 )
by Lars
02:12
created

Arrayy::offsetUnset()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
cc 2
eloc 3
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Arrayy;
4
5
use voku\helper\UTF8;
6
7
/**
8
 * Methods to manage arrays.
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
class Arrayy extends ArrayyAbstract implements \Countable, \IteratorAggregate, \ArrayAccess, \Serializable
14
{
15
  /**
16
   * Initializes
17
   *
18
   * @param array $array
19
   */
20 407
  public function __construct($array = array())
21
  {
22 407
    if (!$array) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $array 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...
23 81
      $array = array();
24 81
    }
25
26
    if (
27 407
        is_string($array)
28
        ||
29 407
        (is_object($array) && method_exists($array, '__toString'))
30 407
    ) {
31 1
      $array = (array)$array;
32 1
    }
33
34 407
    if (!is_array($array)) {
35 2
      throw new \InvalidArgumentException(
36
          'Passed value must be a array'
37 2
      );
38
    }
39
40 405
    $this->array = $array;
41 405
  }
42
43
  /**
44
   * magic to string
45
   *
46
   * @return string
47
   */
48 14
  public function __toString()
49
  {
50 14
    return $this->implode(',');
51
  }
52
53
  /**
54
   * @return mixed
55
   */
56
  public function serialize()
57
  {
58
    return serialize($this->array);
59
  }
60
61
  /**
62
   * @param string $array
63
   */
64
  public function unserialize($array)
65
  {
66
    $this->array = unserialize($array);
67
  }
68
69
  /**
70
   * Get a value by key.
71
   *
72
   * @param $key
73
   *
74
   * @return mixed
75
   */
76
  public function &__get($key)
77
  {
78
    return $this->array[$key];
79
  }
80
81
  /**
82
   * Assigns a value to the specified element.
83
   *
84
   * @param $key
85
   * @param $value
86
   */
87
  public function __set($key, $value)
88
  {
89
    $this->array[$key] = $value;
90
  }
91
92
  /**
93
   * Whether or not an element exists by key.
94
   *
95
   * @param $key
96
   *
97
   * @return bool
98
   */
99
  public function __isset($key)
100
  {
101
    return isset($this->array[$key]);
102
  }
103
104
  /**
105
   * Unset element by key
106
   *
107
   * @param mixed $key
108
   */
109
  public function __unset($key)
110
  {
111
    unset($this->array[$key]);
112
  }
113
114
  /**
115
   * Assigns a value to the specified offset.
116
   *
117
   * @param mixed $offset
118
   * @param mixed $value
119
   */
120 2
  public function offsetSet($offset, $value)
121
  {
122 2
    if (null === $offset) {
123
      $this->array[] = $value;
124
    } else {
125 2
      $this->array[$offset] = $value;
126
    }
127 2
  }
128
129
  /**
130
   * Whether or not an offset exists.
131
   *
132
   * @param mixed $offset
133
   *
134
   * @return bool
135
   */
136 9
  public function offsetExists($offset)
137
  {
138 9
    return isset($this->array[$offset]);
139
  }
140
141
  /**
142
   * Unset an offset.
143
   *
144
   * @param mixed $offset
145
   */
146 1
  public function offsetUnset($offset)
147
  {
148 1
    if ($this->offsetExists($offset)) {
149 1
      unset($this->array[$offset]);
150 1
    }
151 1
  }
152
153
  /**
154
   * Returns the value at specified offset.
155
   *
156
   * @param mixed $offset
157
   *
158
   * @return null
159
   */
160 8
  public function offsetGet($offset)
161
  {
162 8
    return $this->offsetExists($offset) ? $this->array[$offset] : null;
163
  }
164
165
  /**
166
   * Returns a new ArrayIterator, thus implementing the IteratorAggregate
167
   * interface.
168
   *
169
   * @return \ArrayIterator An iterator for the values in the array
170
   */
171 2
  public function getIterator()
172
  {
173 2
    return new \ArrayIterator($this->array);
174
  }
175
176
  /**
177
   * call object as function
178
   *
179
   * @param mixed $key
180
   *
181
   * @return mixed
182
   */
183
  public function __invoke($key = null)
184
  {
185
    if ($key !== null) {
186
      if (isset($this->array[$key])) {
187
        return $this->array[$key];
188
      } else {
189
        return false;
190
      }
191
    }
192
193
    return (array)$this->array;
194
  }
195
196
  /**
197
   * get the current array from the "Arrayy"-object
198
   *
199
   * @return array
200
   */
201 235
  public function getArray()
202
  {
203 235
    return $this->array;
204
  }
205
206
  /**
207
   * Creates a Arrayy object
208
   *
209
   * @param array $array
210
   *
211
   * @return Arrayy
212
   */
213 310
  public static function create($array = array())
214
  {
215 310
    return new static($array);
216
  }
217
218
  /**
219
   * Create a new Arrayy object via string.
220
   *
221
   * @param string      $str       The input string.
222
   * @param string|null $delimiter The boundary string.
223
   * @param string|null $regEx     Use the $delimiter or the $regEx, so if $pattern is null, $delimiter will be used.
224
   *
225
   * @return Arrayy
226
   */
227 2
  public static function createFromString($str, $delimiter, $regEx = null)
228
  {
229 2
    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...
230 1
      preg_match_all($regEx, $str, $array);
231
232 1
      if (count($array) > 0) {
233 1
        $array = $array[0];
234 1
      }
235
236 1
    } else {
237 1
      $array = explode($delimiter, $str);
238
    }
239
240
    // trim all string in the array
241 2
    array_walk(
242 2
        $array,
243
        function (&$val) {
244 2
          if (is_string($val)) {
245 2
            $val = trim($val);
246 2
          }
247 2
        }
248 2
    );
249
250 2
    return self::create($array);
251
  }
252
253
  /**
254
   * create a new Arrayy object via JSON,
255
   *
256
   * @param string $json
257
   *
258
   * @return Arrayy
259
   */
260 1
  public static function createFromJson($json)
261
  {
262 1
    $array = UTF8::json_decode($json, true);
263
264 1
    return self::create($array);
265
  }
266
267
  ////////////////////////////////////////////////////////////////////
268
  ///////////////////////////// ANALYZE //////////////////////////////
269
  ////////////////////////////////////////////////////////////////////
270
271
  /**
272
   * Search for the value of the current array via $index.
273
   *
274
   * @param mixed $index
275
   *
276
   * @return Arrayy will return a empty Arrayy if the value wasn't found
277
   */
278 7
  public function searchValue($index)
279
  {
280
    // init
281 7
    $return = array();
282
283 7
    if (null !== $index) {
284 7
      $keyExists = isset($this->array[$index]);
285
286 7
      if ($keyExists !== false) {
287 5
        $return = array($this->array[$index]);
288 5
      }
289 7
    }
290
291 7
    return static::create((array)$return);
292
  }
293
294
  /**
295
   * Search for the first index of the current array via $value.
296
   *
297
   * @param mixed $value
298
   *
299
   * @return Arrayy will return a empty Arrayy if the index wasn't found
300
   */
301 16
  public function searchIndex($value)
302
  {
303 16
    $key = array_search($value, $this->array, true);
304
305 16
    if ($key === false) {
306 9
      $return = array();
307 9
    } else {
308 7
      $return = array($key);
309
    }
310
311 16
    return static::create((array)$return);
312
  }
313
314
  /**
315
   * Check if all items in current array match a truth test.
316
   *
317
   * @param \Closure $closure
318
   *
319
   * @return bool
320
   */
321 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...
322
  {
323
    // Reduce the array to only booleans
324 9
    $array = $this->each($closure);
325
326
    // Check the results
327 9
    if (count($array) === 0) {
328 2
      return true;
329
    }
330 7
    $array = array_search(false, $array, false);
331
332 7
    return is_bool($array);
333
  }
334
335
  /**
336
   * Check if any item in the current array matches a truth test.
337
   *
338
   * @param \Closure $closure
339
   *
340
   * @return bool
341
   */
342 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...
343
  {
344
    // Reduce the array to only booleans
345 9
    $array = $this->each($closure);
346
347
    // Check the results
348 9
    if (count($array) === 0) {
349 2
      return true;
350
    }
351 7
    $array = array_search(true, $array, false);
352
353 7
    return is_int($array);
354
  }
355
356
  /**
357
   * Check if we have named keys in the current array.
358
   *
359
   * @return bool
360
   */
361 12
  public function isAssoc()
362
  {
363 12
    if (count($this->array) === 0) {
364 1
      return false;
365
    }
366
367 11
    return (bool)count(array_filter(array_keys($this->array), 'is_string'));
368
  }
369
370
  /**
371
   * Check if the current array is a multi-array.
372
   *
373
   * @return bool
374
   */
375 13
  public function isMultiArray()
376
  {
377 13
    return !(count($this->array) === count($this->array, COUNT_RECURSIVE));
378
  }
379
380
  /**
381
   * Check if an item is in the current array.
382
   *
383
   * @param mixed $value
384
   *
385
   * @return bool
386
   */
387 9
  public function contains($value)
388
  {
389 9
    return in_array($value, $this->array, true);
390
  }
391
392
  /**
393
   * Returns the average value of the current array.
394
   *
395
   * @param int $decimals The number of decimals to return
396
   *
397
   * @return int|double The average value
398
   */
399 10
  public function average($decimals = null)
400
  {
401 10
    $count = $this->count();
402
403 10
    if (!$count) {
404 2
      return 0;
405
    }
406
407 8
    if (!is_int($decimals)) {
408 3
      $decimals = null;
409 3
    }
410
411 8
    return round(array_sum($this->array) / $count, $decimals);
412
  }
413
414
  /**
415
   * Count the values from the current array.
416
   *
417
   * INFO: only a alias for "$arrayy->size()"
418
   *
419
   * @return int
420
   */
421 10
  public function length()
422
  {
423 10
    return $this->size();
424
  }
425
426
  /**
427
   * Count the values from the current array.
428
   *
429
   * INFO: only a alias for "$arrayy->size()"
430
   *
431
   * @return int
432
   */
433 59
  public function count()
434
  {
435 59
    return $this->size();
436
  }
437
438
  /**
439
   * Get the size of an array.
440
   *
441
   * @return int
442
   */
443 59
  public function size()
444
  {
445 59
    return count($this->array);
446
  }
447
448
  /**
449
   * Get the max value from an array.
450
   *
451
   * @return mixed
452
   */
453 10
  public function max()
454
  {
455 10
    if ($this->count() === 0) {
456 1
      return false;
457
    }
458
459 9
    return max($this->array);
460
  }
461
462
  /**
463
   * Get the min value from an array.
464
   *
465
   * @return mixed
466
   */
467 10
  public function min()
468
  {
469 10
    if ($this->count() === 0) {
470 1
      return false;
471
    }
472
473 9
    return min($this->array);
474
  }
475
476
  ////////////////////////////////////////////////////////////////////
477
  //////////////////////////// FETCH FROM ////////////////////////////
478
  ////////////////////////////////////////////////////////////////////
479
480
  /**
481
   * Find the first item in an array that passes the truth test,
482
   *  otherwise return false
483
   *
484
   * @param \Closure $closure
485
   *
486
   * @return mixed|false false if we couldn't find the value
487
   */
488 7
  public function find(\Closure $closure)
489
  {
490 7
    foreach ($this->array as $key => $value) {
491 5
      if ($closure($value, $key)) {
492 4
        return $value;
493
      }
494 4
    }
495
496 3
    return false;
497
  }
498
499
  /**
500
   * Clean all falsy values from an array.
501
   *
502
   * @return Arrayy
503
   */
504 8
  public function clean()
505
  {
506 8
    return $this->filter(
507
        function ($value) {
508 7
          return (bool)$value;
509
        }
510 8
    );
511
  }
512
513
  /**
514
   * Get a random string from an array.
515
   *
516
   * @param null|int $take how many values you will take?
517
   *
518
   * @return Arrayy
519
   */
520 18
  public function random($take = null)
521
  {
522 18
    if ($this->count() === 0) {
523
      return self::create(array());
524
    }
525
526 18
    if ($take === null) {
527 12
      return static::create((array)$this->array[array_rand($this->array)]);
528
    }
529
530 8
    shuffle($this->array);
531
532 8
    return $this->first($take);
533
  }
534
535
  /**
536
   * Get a random value from an array, with the ability to skew the results.
537
   *
538
   * Example: randomWeighted(['foo' => 1, 'bar' => 2]) has a 66% chance of returning bar.
539
   *
540
   * @param array    $array
541
   * @param null|int $take how many values you will take?
542
   *
543
   * @return Arrayy
544
   */
545 9
  public function randomWeighted(array $array, $take = null)
546
  {
547 9
    $options = array();
548 9
    foreach ($array as $option => $weight) {
549 9
      if ($this->searchIndex($option)->count() > 0) {
550 2
        for ($i = 0; $i < $weight; ++$i) {
551 1
          $options[] = $option;
552 1
        }
553 2
      }
554 9
    }
555
556 9
    return $this->mergeAppendKeepIndex($options)->random($take);
557
  }
558
559
  /**
560
   * Return an array with all elements found in input array.
561
   *
562
   * @param array $search
563
   *
564
   * @return Arrayy
565
   */
566 2
  public function intersection(array $search)
567
  {
568 2
    return static::create(array_values(array_intersect($this->array, $search)));
569
  }
570
571
  /**
572
   * Return a boolean flag which indicates whether the two input arrays have any common elements.
573
   *
574
   * @param array $search
575
   *
576
   * @return bool
577
   */
578 1
  public function intersects(array $search)
579
  {
580 1
    return count($this->intersection($search)->array) > 0;
581
  }
582
583
  ////////////////////////////////////////////////////////////////////
584
  ///////////////////////////// SLICERS //////////////////////////////
585
  ////////////////////////////////////////////////////////////////////
586
587
  /**
588
   * Get the first value(s) from the current array.
589
   *
590
   * @param int|null $take how many values you will take?
591
   *
592
   * @return Arrayy
593
   */
594 33
  public function first($take = null)
595
  {
596 33
    if ($take === null) {
597 8
      $array = array_shift($this->array);
598 8
    } else {
599 25
      $array = array_splice($this->array, 0, $take, true);
600
    }
601
602 33
    return static::create((array)$array);
603
  }
604
605
  /**
606
   * Get the last value(s) from the current array.
607
   *
608
   * @param int|null $take
609
   *
610
   * @return Arrayy
611
   */
612 11
  public function last($take = null)
613
  {
614 11
    if ($take === null) {
615 7
      $array = static::create((array)array_pop($this->array));
616 7
    } else {
617 4
      $array = $this->rest(-$take);
618
    }
619
620 11
    return $array;
621
  }
622
623
  /**
624
   * Get everything but the last..$to items.
625
   *
626
   * @param int $to
627
   *
628
   * @return Arrayy
629
   */
630 12
  public function initial($to = 1)
631
  {
632 12
    $slice = count($this->array) - $to;
633
634 12
    return $this->first($slice);
635
  }
636
637
  /**
638
   * Get the last elements from index $from until the end of this array.
639
   *
640
   * @param int $from
641
   *
642
   * @return Arrayy
643
   */
644 16
  public function rest($from = 1)
645
  {
646 16
    return static::create(array_splice($this->array, $from));
647
  }
648
649
  ////////////////////////////////////////////////////////////////////
650
  ///////////////////////////// ACT UPON /////////////////////////////
651
  ////////////////////////////////////////////////////////////////////
652
653
  /**
654
   * Iterate over an array and execute a callback for each loop.
655
   *
656
   * @param \Closure $closure
657
   *
658
   * @return Arrayy
659
   */
660 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...
661
  {
662 2
    $array = $this->array;
663
664 2
    foreach ($array as $key => $value) {
665 2
      $closure($value, $key);
666 2
    }
667
668 2
    return static::create($array);
669
  }
670
671
  ////////////////////////////////////////////////////////////////////
672
  ////////////////////////////// ALTER ///////////////////////////////
673
  ////////////////////////////////////////////////////////////////////
674
675
  /**
676
   * Merge the new $array into the current array.
677
   *
678
   * - replace duplicate assoc-keys from the current array with the key,values from the new $array
679
   * - create new indexes
680
   *
681
   * @param array $array
682
   *
683
   * @return Arrayy
684
   */
685 8
  public function mergeAppendNewIndex(array $array = array())
686
  {
687 8
    return static::create(array_merge($this->array, $array));
688
  }
689
690
  /**
691
   * Merge the current array into the new $array.
692
   *
693
   * - replace duplicate assoc-keys from new $array with the key,values from the current array
694
   * - create new indexes
695
   *
696
   * @param array $array
697
   *
698
   * @return Arrayy
699
   */
700 8
  public function mergePrependNewIndex(array $array = array())
701
  {
702 8
    return static::create(array_merge($array, $this->array));
703
  }
704
705
  /**
706
   * Merge the new $array into the current array.
707
   *
708
   * - keep key,value from the current array, also if the index is in the new $array
709
   *
710
   * @param array $array
711
   *
712
   * @return Arrayy
713
   */
714 17
  public function mergeAppendKeepIndex(array $array = array())
715
  {
716 17
    return static::create(array_replace($this->array, $array));
717
  }
718
719
  /**
720
   * Merge the the current array into the $array.
721
   *
722
   * - use key,value from the new $array, also if the index is in the current array
723
   *
724
   * @param array $array
725
   *
726
   * @return Arrayy
727
   */
728 8
  public function mergePrependKeepIndex(array $array = array())
729
  {
730 8
    return static::create(array_replace($array, $this->array));
731
  }
732
733
  /**
734
   * Return values that are only in the current array.
735
   *
736
   * @param array $array
737
   *
738
   * @return Arrayy
739
   */
740 8
  public function diff(array $array = array())
741
  {
742 8
    return static::create(array_diff($this->array, $array));
743
  }
744
745
  /**
746
   * Return values that are only in the new $array.
747
   *
748
   * @param array $array
749
   *
750
   * @return Arrayy
751
   */
752 8
  public function diffReverse(array $array = array())
753
  {
754 8
    return static::create(array_diff($array, $this->array));
755
  }
756
757
  /**
758
   * Replace the first matched value in an array.
759
   *
760
   * @param mixed $search
761
   * @param mixed $replacement
762
   *
763
   * @return Arrayy
764
   */
765 3
  public function replaceOneValue($search, $replacement = '')
766
  {
767 3
    $array = $this->array;
768 3
    $key = array_search($search, $array, true);
769
770 3
    if ($key !== false) {
771 3
      $array[$key] = $replacement;
772 3
    }
773
774 3
    return static::create($array);
775
  }
776
777
  /**
778
   * Replace values in the current array.
779
   *
780
   * @param string $search      The string to replace.
781
   * @param string $replacement What to replace it with.
782
   *
783
   * @return Arrayy
784
   */
785 1
  public function replaceValues($search, $replacement = '')
786
  {
787 1
    $array = $this->each(
788
        function ($value) use ($search, $replacement) {
789 1
          return UTF8::str_replace($search, $replacement, $value);
790
        }
791 1
    );
792
793 1
    return static::create((array)$array);
794
  }
795
796
  /**
797
   * Replace the keys in an array with another set.
798
   *
799
   * @param array $keys An array of keys matching the array's size
800
   *
801
   * @return Arrayy
802
   */
803 1
  public function replaceKeys(array $keys)
804
  {
805 1
    $values = array_values($this->array);
806
807 1
    return static::create(array_combine($keys, $values));
808
  }
809
810
  /**
811
   * Iterate over the current array and modify the array's value.
812
   *
813
   * @param \Closure $closure
814
   *
815
   * @return array
816
   */
817 22
  public function each(\Closure $closure)
818
  {
819 22
    $array = $this->array;
820
821 22
    foreach ($array as $key => &$value) {
822 18
      $value = $closure($value, $key);
823 22
    }
824
825 22
    return $array;
826
  }
827
828
  /**
829
   * Shuffle the current array.
830
   *
831
   * @return Arrayy
832
   */
833 1
  public function shuffle()
834
  {
835 1
    $array = $this->array;
836
837 1
    shuffle($array);
838
839 1
    return static::create($array);
840
  }
841
842
843
  /**
844
   * Split an array in the given amount of pieces.
845
   *
846
   * @param int  $numberOfPieces
847
   * @param bool $keepKeys
848
   *
849
   * @return array
850
   */
851 1
  public function split($numberOfPieces = 2, $keepKeys = false)
852
  {
853 1
    if (count($this->array) === 0) {
854 1
      return self::create(array());
855
    }
856
857 1
    $splitSize = ceil(count($this->array) / $numberOfPieces);
858
859 1
    return self::create(array_chunk($this->array, $splitSize, $keepKeys));
860
  }
861
862
  /**
863
   * Implodes an array.
864
   *
865
   * @param string $with What to implode it with
866
   *
867
   * @return string
868
   */
869 22
  public function implode($with = '')
870
  {
871 22
    return implode($with, $this->array);
872
  }
873
874
  /**
875
   * Returns the values from a single column of the input array, identified by
876
   * the $columnKey, can be used to extract data-columns from multi-arrays.
877
   *
878
   * Info: Optionally, you may provide an $indexKey to index the values in the returned
879
   * array by the values from the $indexKey column in the input array.
880
   *
881
   * @param mixed $columnKey
882
   * @param mixed $indexKey
883
   *
884
   * @return Arrayy
885
   */
886 1
  public function getColumn($columnKey = null, $indexKey = null)
887
  {
888 1
    return self::create(array_column($this->array, $columnKey, $indexKey));
0 ignored issues
show
Bug introduced by
It seems like array_column($this->array, $columnKey, $indexKey) targeting array_column() can also be of type false or null; however, Arrayy\Arrayy::create() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
889
  }
890
891
  /**
892
   * Find all items in an array that pass the truth test.
893
   *
894
   * @param \Closure|null $closure
895
   *
896
   * @return Arrayy
897
   */
898 8
  public function filter($closure = null)
899
  {
900 8
    if (!$closure) {
901 1
      return $this->clean();
902
    }
903
904 8
    $array = array_filter($this->array, $closure);
905
906 8
    return static::create($array);
907
  }
908
909
  /**
910
   * Invoke a function on all of an array's values.
911
   *
912
   * @param mixed $callable
913
   * @param array $arguments
914
   *
915
   * @return Arrayy
916
   */
917 1
  public function invoke($callable, $arguments = array())
918
  {
919
    // If one argument given for each iteration, create an array for it.
920 1
    if (!is_array($arguments)) {
921 1
      $arguments = StaticArrayy::repeat($arguments, count($this->array))->getArray();
922 1
    }
923
924
    // If the callable has arguments, pass them.
925 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...
926 1
      $array = array_map($callable, $this->array, $arguments);
927 1
    } else {
928 1
      $array = array_map($callable, $this->array);
929
    }
930
931 1
    return static::create($array);
932
  }
933
934
  /**
935
   * Return all items that fail the truth test.
936
   *
937
   * @param \Closure $closure
938
   *
939
   * @return Arrayy
940
   */
941 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...
942
  {
943 1
    $filtered = array();
944
945 1
    foreach ($this->array as $key => $value) {
946 1
      if (!$closure($value, $key)) {
947 1
        $filtered[$key] = $value;
948 1
      }
949 1
    }
950
951 1
    return static::create($filtered);
952
  }
953
954
  /**
955
   * Remove the first value from the current array.
956
   *
957
   * @return Arrayy
958
   */
959 8
  public function removeFirst()
960
  {
961 8
    array_shift($this->array);
962
963 8
    return static::create($this->array);
964
  }
965
966
  /**
967
   * Remove the last value from the current array.
968
   *
969
   * @return Arrayy
970
   */
971 7
  public function removeLast()
972
  {
973 7
    array_pop($this->array);
974
975 7
    return static::create($this->array);
976
  }
977
978
  /**
979
   * Removes a particular value from an array (numeric or associative).
980
   *
981
   * @param mixed $value
982
   *
983
   * @return Arrayy
984
   */
985 7
  public function removeValue($value)
986
  {
987 7
    $isNumericArray = true;
988 7
    foreach ($this->array as $key => $item) {
989 6
      if ($item === $value) {
990 6
        if (!is_int($key)) {
991
          $isNumericArray = false;
992
        }
993 6
        unset($this->array[$key]);
994 6
      }
995 7
    }
996
997 7
    if ($isNumericArray) {
998 7
      $this->array = array_values($this->array);
999 7
    }
1000
1001 7
    return static::create($this->array);
1002
  }
1003
1004
  /**
1005
   * Prepend a value to an array.
1006
   *
1007
   * @param mixed $value
1008
   *
1009
   * @return Arrayy
1010
   */
1011 7
  public function prepend($value)
1012
  {
1013 7
    array_unshift($this->array, $value);
1014
1015 7
    return static::create($this->array);
1016
  }
1017
1018
  /**
1019
   * Append a value to an array.
1020
   *
1021
   * @param mixed $value
1022
   *
1023
   * @return Arrayy
1024
   */
1025 8
  public function append($value)
1026
  {
1027 8
    $this->array[] = $value;
1028
1029 8
    return static::create($this->array);
1030
  }
1031
1032
  /**
1033
   * Return the array in the reverse order.
1034
   *
1035
   * @return Arrayy
1036
   */
1037 7
  public function reverse()
1038
  {
1039 7
    $this->array = array_reverse($this->array);
1040
1041 7
    return static::create($this->array);
1042
  }
1043
1044
  /**
1045
   * Custom sort by value via "usort"
1046
   *
1047
   * @link http://php.net/manual/en/function.usort.php
1048
   *
1049
   * @param callable $func
1050
   *
1051
   * @return Arrayy
1052
   */
1053
  public function customSortValues(callable $func)
1054
  {
1055
    usort($this->array, $func);
1056
1057
    return static::create($this->array);
1058
  }
1059
1060
  /**
1061
   * Custom sort by index via "uksort"
1062
   *
1063
   * @link http://php.net/manual/en/function.uksort.php
1064
   *
1065
   * @param callable $func
1066
   *
1067
   * @return Arrayy
1068
   */
1069
  public function customSortKeys(callable $func)
1070
  {
1071
    uksort($this->array, $func);
1072
1073
    return static::create($this->array);
1074
  }
1075
1076
  /**
1077
   * sorting keys
1078
   *
1079
   * @param array $elements
1080
   * @param int   $direction
1081
   * @param int   $strategy
1082
   */
1083 10
  protected function sorterKeys(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR)
1084
  {
1085 10
    $direction = $this->getDirection($direction);
1086
1087
    switch ($direction) {
1088 10
      case 'desc':
1089 10
      case SORT_DESC:
1090 2
        krsort($elements, $strategy);
1091 2
        break;
1092 9
      case 'asc':
1093 9
      case SORT_ASC:
1094 9
      default:
1095 9
        ksort($elements, $strategy);
1096 9
    }
1097 10
  }
1098
1099
  /**
1100
   * Sort the current array by key.
1101
   *
1102
   * @link http://php.net/manual/en/function.ksort.php
1103
   * @link http://php.net/manual/en/function.krsort.php
1104
   *
1105
   * @param int|string $direction use SORT_ASC or SORT_DESC
1106
   * @param int        $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
1107
   *
1108
   * @return Arrayy
1109
   */
1110 10
  public function sortKeys($direction = SORT_ASC, $strategy = SORT_REGULAR)
1111
  {
1112 10
    $this->sorterKeys($this->array, $direction, $strategy);
1113
1114 10
    return static::create($this->array);
1115
  }
1116
1117
  /**
1118
   * Sort the current array by value.
1119
   *
1120
   * @param int $direction use SORT_ASC or SORT_DESC
1121
   * @param int $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
1122
   *
1123
   * @return Arrayy
1124
   */
1125 1
  public function sortValueKeepIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
1126
  {
1127 1
    return $this->sort($direction, $strategy, true);
1128
  }
1129
1130
  /**
1131
   * Sort the current array by value.
1132
   *
1133
   * @param int $direction use SORT_ASC or SORT_DESC
1134
   * @param int $strategy  use e.g.: SORT_REGULAR or SORT_NATURAL
1135
   *
1136
   * @return Arrayy
1137
   */
1138 1
  public function sortValueNewIndex($direction = SORT_ASC, $strategy = SORT_REGULAR)
1139
  {
1140 1
    return $this->sort($direction, $strategy, false);
1141
  }
1142
1143
  /**
1144
   * Get correct PHP constant for direction.
1145
   *
1146
   * @param int|string $direction
1147
   *
1148
   * @return int
1149
   */
1150 14
  protected function getDirection($direction)
1151
  {
1152 14
    if (is_string($direction)) {
1153 10
      $direction = strtolower($direction);
1154
1155 10
      if ($direction === 'desc') {
1156 2
        $direction = SORT_DESC;
1157 2
      } else {
1158 8
        $direction = SORT_ASC;
1159
      }
1160 10
    }
1161
1162
    if (
1163
        $direction !== SORT_DESC
1164 14
        &&
1165
        $direction !== SORT_ASC
1166 14
    ) {
1167
      $direction = SORT_ASC;
1168
    }
1169
1170 14
    return $direction;
1171
  }
1172
1173
  /**
1174
   * Sort a array by value, by a closure or by a property.
1175
   *
1176
   * - If the sorter is null, the array is sorted naturally.
1177
   * - Associative (string) keys will be maintained, but numeric keys will be re-indexed.
1178
   *
1179
   * @param null       $sorter
1180
   * @param string|int $direction
1181
   * @param int        $strategy
1182
   *
1183
   * @return Arrayy
1184
   */
1185 1
  public function sorter($sorter = null, $direction = SORT_ASC, $strategy = SORT_REGULAR)
1186
  {
1187 1
    $array = (array)$this->array;
1188 1
    $direction = $this->getDirection($direction);
1189
1190
    // Transform all values into their results.
1191 1
    if ($sorter) {
1192 1
      $arrayy = new Arrayy($array);
1193
1194 1
      $that = $this;
1195 1
      $results = $arrayy->each(
1196
          function ($value) use ($sorter, $that) {
1197 1
            return is_callable($sorter) ? $sorter($value) : $that->get($sorter, null, $value);
1198
          }
1199 1
      );
1200 1
    } else {
1201 1
      $results = $array;
1202
    }
1203
1204
    // Sort by the results and replace by original values
1205 1
    array_multisort($results, $direction, $strategy, $array);
1206
1207 1
    return Arrayy::create($array);
1208
  }
1209
1210
  /**
1211
   * @param array      &$elements
1212
   * @param int|string $direction
1213
   * @param int        $strategy
1214
   * @param bool       $keepKeys
1215
   */
1216 3
  protected function sorting(array &$elements, $direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
1217
  {
1218 3
    $direction = $this->getDirection($direction);
1219
1220 3
    if (!$strategy) {
1221 3
      $strategy = SORT_REGULAR;
1222 3
    }
1223
1224
    switch ($direction) {
1225 3
      case 'desc':
1226 3
      case SORT_DESC:
1227 1
        if ($keepKeys) {
1228 1
          arsort($elements, $strategy);
1229 1
        } else {
1230
          rsort($elements, $strategy);
1231
        }
1232 1
        break;
1233 2
      case 'asc':
1234 2
      case SORT_ASC:
1235 2
      default:
1236 2
        if ($keepKeys) {
1237
          asort($elements, $strategy);
1238
        } else {
1239 2
          sort($elements, $strategy);
1240
        }
1241 2
    }
1242 3
  }
1243
1244
  /**
1245
   * Sort the current array and optional you can keep the keys.
1246
   *
1247
   * @param string|int $direction use SORT_ASC or SORT_DESC
1248
   * @param int|string $strategy
1249
   * @param bool       $keepKeys
1250
   *
1251
   * @return Arrayy
1252
   */
1253 3
  public function sort($direction = SORT_ASC, $strategy = SORT_REGULAR, $keepKeys = false)
1254
  {
1255 3
    $this->sorting($this->array, $direction, $strategy, $keepKeys);
1256
1257 3
    return Arrayy::create($this->array);
1258
  }
1259
1260
  /**
1261
   * Exchanges all keys with their associated values in an array.
1262
   *
1263
   * @return Arrayy
1264
   */
1265 1
  public function flip()
1266
  {
1267 1
    $this->array = array_flip($this->array);
1268
1269 1
    return static::create($this->array);
1270
  }
1271
1272
  /**
1273
   * Reduce the current array via callable e.g. anonymous-function.
1274
   *
1275
   * @param mixed $predicate
1276
   * @param array $init
1277
   *
1278
   * @return Arrayy
1279
   */
1280 2
  public function reduce($predicate, array $init = array())
1281
  {
1282 2
    $this->array = array_reduce($this->array, $predicate, $init);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_reduce($this->array, $predicate, $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...
1283
1284 2
    return static::create($this->array);
1285
  }
1286
1287
  /**
1288
   * Return a duplicate free copy of the current array.
1289
   *
1290
   * @return Arrayy
1291
   */
1292 7
  public function unique()
1293
  {
1294 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...
1295 7
        $this->array,
1296 7
        function ($resultArray, $value) {
1297 6
          if (in_array($value, $resultArray, true) === false) {
1298 6
            $resultArray[] = $value;
1299 6
          }
1300
1301 6
          return $resultArray;
1302 7
        },
1303 7
        array()
1304 7
    );
1305
1306 7
    return static::create($this->array);
1307
  }
1308
1309
  /**
1310
   * Convert the current array to JSON.
1311
   *
1312
   * @param null $options e.g. JSON_PRETTY_PRINT
1313
   *
1314
   * @return string
1315
   */
1316 1
  public function toJson($options = null)
1317
  {
1318 1
    return UTF8::json_encode($this->array, $options);
1319
  }
1320
}
1321