AbstractArray::createFromObject()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Arrayzy;
4
5
use Arrayzy\Interfaces\ConvertibleInterface;
6
use Arrayzy\Interfaces\DebuggableInterface;
7
use Arrayzy\Interfaces\DoubleEndedQueueInterface;
8
use Arrayzy\Interfaces\SortableInterface;
9
use Arrayzy\Interfaces\TraversableInterface;
10
use Arrayzy\Traits\ConvertibleTrait;
11
use Arrayzy\Traits\DebuggableTrait;
12
use Arrayzy\Traits\DoubleEndedQueueTrait;
13
use Arrayzy\Traits\SortableTrait;
14
use Arrayzy\Traits\TraversableTrait;
15
use ArrayAccess;
16
use ArrayIterator;
17
use Countable;
18
use IteratorAggregate;
19
use Traversable;
20
21
/**
22
 * Defines common methods and method signatures.
23
 *
24
 * @author Victor Bocharsky <[email protected]>
25
 */
26
abstract class AbstractArray implements
27
    ArrayAccess,
28
    ConvertibleInterface,
29
    Countable,
30
    DebuggableInterface,
31
    DoubleEndedQueueInterface,
32
    IteratorAggregate,
33
    SortableInterface,
34
    TraversableInterface
35
{
36
    use ConvertibleTrait;
37
38
    use DebuggableTrait;
39
40
    use DoubleEndedQueueTrait;
41
42
    use SortableTrait;
43
44
    use TraversableTrait;
45
46
    /**
47
     * @const string
48
     */
49
    const DEFAULT_SEPARATOR = ', ';
50
51
    /**
52
     * @var array
53
     */
54
    protected $elements = [];
55
56
    /**
57
     * Construct new instance
58
     *
59
     * @param array $elements
60
     */
61 307
    public function __construct(array $elements = [])
62
    {
63 307
        $this->elements = $elements;
64 307
    }
65
66
    // The abstract public method list order by ASC
67
68
    /**
69
     * Create a chunked version of current array.
70
     *
71
     * @param int $size Size of each chunk
72
     * @param bool $preserveKeys Whether array keys are preserved or no
73
     *
74
     * @return AbstractArray An array of chunks from the current array
75
     */
76
    abstract public function chunk($size, $preserveKeys = false);
77
78
    /**
79
     * Clear the current array.
80
     *
81
     * @return AbstractArray The current empty array
82
     */
83
    abstract public function clear();
84
85
    /**
86
     * Create an array using the current array as keys and the other array as values.
87
     *
88
     * @param array $array Values array
89
     *
90
     * @return AbstractArray An array with values from the other array
91
     */
92
    abstract public function combine(array $array);
93
94
    /**
95
     * Compute the current array values which not present in the given one.
96
     *
97
     * @param array $array Array for diff
98
     *
99
     * @return AbstractArray An array containing all the entries from this array
100
     * that are not present in $array
101
     */
102
    abstract public function diff(array $array);
103
104
    /**
105
     * Filter the current array for elements satisfying the predicate $func.
106
     *
107
     * @param callable $func
108
     *
109
     * @return AbstractArray An array with only element satisfying $func
110
     */
111
    abstract public function filter(callable $func);
112
113
    /**
114
     * Exchanges all keys of current array with their associated values.
115
     *
116
     * @return AbstractArray An array with flipped elements
117
     */
118
    abstract public function flip();
119
120
    /**
121
     * Compute the current array values which present in the given one.
122
     *
123
     * @param array $array Array for intersect
124
     *
125
     * @return AbstractArray An array with containing all the entries from this array
126
     * that are present in $array
127
     */
128
    abstract public function intersect(array $array);
129
130
    /**
131
     * Compute the current array values with additional index check which present in the given one.
132
     *
133
     * @param array $array Array for intersect
134
     *
135
     * @return AbstractArray An array with containing all the entries from this array
136
     * that are present in $array. Note that the keys are also used in the comparison
137
     * unlike in intersect().
138
     */
139
    abstract public function intersectAssoc(array $array);
140
141
    /**
142
     * Compute the current array using keys for comparison which present in the given one.
143
     *
144
     * @param array $array Array for intersect
145
     *
146
     * @return AbstractArray An array with containing all the entries from this array
147
     * which have keys that are present in $array.
148
     */
149
     abstract public function intersectKey(array $array);
150
151
    /**
152
     * Apply the given function to the every element of the current array,
153
     * collecting the results.
154
     *
155
     * @param callable $func
156
     *
157
     * @return AbstractArray An array with modified elements
158
     */
159
    abstract public function map(callable $func);
160
161
    /**
162
     * Merge the current array with the provided one. The latter array is overwriting.
163
     *
164
     * @param array $array Array to merge with (overwrites)
165
     * @param bool $recursively Whether array will be merged recursively or no
166
     *
167
     * @return AbstractArray An array with the keys/values from $array added
168
     */
169
    abstract public function merge(array $array, $recursively = false);
170
171
    /**
172
     * Pad the current array to the specified size with a given value.
173
     *
174
     * @param int $size Size of the result array
175
     * @param mixed $value Empty value by default
176
     *
177
     * @return AbstractArray An array padded to $size with $value
178
     */
179
    abstract public function pad($size, $value);
180
181
    /**
182
     * Create a numerically re-indexed array based on the current array.
183
     *
184
     * @return AbstractArray An array with re-indexed elements
185
     */
186
    abstract public function reindex();
187
188
    /**
189
     * Replace values in the current array with values in the given one
190
     * that have the same key.
191
     *
192
     * @param array $array Array of replacing values
193
     * @param bool $recursively Whether array will be replaced recursively or no
194
     *
195
     * @return AbstractArray An array with the same keys but new values
196
     */
197
    abstract public function replace(array $array, $recursively = false);
198
199
    /**
200
     * Reverse the values order of the current array.
201
     *
202
     * @param bool $preserveKeys Whether array keys are preserved or no
203
     *
204
     * @return AbstractArray An array with the order of the elements reversed
205
     */
206
    abstract public function reverse($preserveKeys = false);
207
208
    /**
209
     * Randomize elements order of the current array.
210
     *
211
     * @return AbstractArray An array with the shuffled elements order
212
     */
213
    abstract public function shuffle();
214
215
    /**
216
     * Extract a slice of the current array.
217
     *
218
     * @param int $offset Slice begin index
219
     * @param int|null $length Length of the slice
220
     * @param bool $preserveKeys Whether array keys are preserved or no
221
     *
222
     * @return AbstractArray A new array, which is slice of the current array
223
     * with specified $length
224
     */
225
    abstract public function slice($offset, $length = null, $preserveKeys = false);
226
227
    /**
228
     * Remove duplicate values from the current array.
229
     *
230
     * @param int|null $sortFlags
231
     *
232
     * @return AbstractArray An array with only unique elements
233
     */
234
    abstract public function unique($sortFlags = null);
235
236
    /**
237
     * Apply the given function to the every element of the current array,
238
     * discarding the results.
239
     *
240
     * @param callable $func
241
     * @param bool $recursively Whether array will be walked recursively or no
242
     *
243
     * @return AbstractArray An array with modified elements
244
     */
245
    abstract public function walk(callable $func, $recursively = false);
246
247
    // The public static method list order by ASC
248
249
    /**
250
     * Create a new instance.
251
     *
252
     * @param array $elements
253
     *
254
     * @return AbstractArray Returns created instance
255
     */
256 19
    public static function create(array $elements = [])
257
    {
258 19
        return new static($elements);
259
    }
260
261
    /**
262
     * Decode a JSON string to new instance.
263
     *
264
     * @param string $json The JSON string being decoded
265
     * @param int $options Bitmask of JSON decode options
266
     * @param int $depth Specified recursion depth
267
     *
268
     * @return AbstractArray The created array
269
     */
270 8
    public static function createFromJson($json, $options = 0, $depth = 512)
271
    {
272 8
        return new static(json_decode($json, true, $depth, $options));
273
    }
274
275
    /**
276
     * Create a new instance filled with values from an object implementing ArrayAccess.
277
     *
278
     * @param ArrayAccess $elements Object that implements ArrayAccess
279
     *
280
     * @return AbstractArray Returns created instance
281
     */
282 8
    public static function createFromObject(ArrayAccess $elements)
283
    {
284 8
        $array = new static();
285
286 8
        foreach ($elements as $key => $value) {
287 6
            $array[$key] = $value;
288 8
        }
289
290 8
        return $array;
291
    }
292
293
    /**
294
     * Explode a string to new instance by specified separator.
295
     *
296
     * @param string $string Converted string
297
     * @param string $separator Element's separator
298
     *
299
     * @return AbstractArray The created array
300
     */
301 6
    public static function createFromString($string, $separator)
302
    {
303 6
        return new static(explode($separator, $string));
304
    }
305
306
    /**
307
     * Create a new instance containing a range of elements.
308
     *
309
     * @param mixed $low First value of the sequence
310
     * @param mixed $high The sequence is ended upon reaching the end value
311
     * @param int $step Used as the increment between elements in the sequence
312
     *
313
     * @return AbstractArray The created array
314
     */
315 1
    public static function createWithRange($low, $high, $step = 1)
316
    {
317 1
        return new static(range($low, $high, $step));
318
    }
319
320
    // The public method list order by ASC
321
322
    /**
323
     * Check if the given value exists in the array.
324
     *
325
     * @param mixed $element Value to search for
326
     *
327
     * @return bool Returns true if the given value exists in the array, false otherwise
328
     */
329 4
    public function contains($element)
330
    {
331 4
        return in_array($element, $this->elements, true);
332
    }
333
334
    /**
335
     * Check if the given key/index exists in the array.
336
     *
337
     * @param mixed $key Key/index to search for
338
     *
339
     * @return bool Returns true if the given key/index exists in the array, false otherwise
340
     */
341 4
    public function containsKey($key)
342
    {
343 4
        return array_key_exists($key, $this->elements);
344
    }
345
346
    /**
347
     * Returns the number of values in the array.
348
     *
349
     * @link http://php.net/manual/en/function.count.php
350
     *
351
     * @return int total number of values
352
     */
353 31
    public function count()
354
    {
355 31
        return count($this->elements);
356
    }
357
358
    /**
359
     * Clone current instance to new instance.
360
     *
361
     * @deprecated Should be removed
362
     *
363
     * @return AbstractArray Shallow copy of $this
364
     */
365 4
    public function createClone()
366
    {
367 4
        return clone $this;
368
    }
369
370
    /**
371
     * Return slice of an array except given keys.
372
     * 
373
     * @param array $keys List of keys to exclude
374
     * 
375
     * @return AbstractArray The created array
376
     */
377 3
    public function except(array $keys)
378
    {
379 3
        return new static(array_diff_key($this->elements, array_flip($keys)));
380
    }
381
382
    /**
383
     * Find the given value in An array using a closure
384
     *
385
     * @param callable $func
386
     *
387
     * @return bool Returns true if the given value is found, false otherwise
388
     */
389 4
    public function exists(callable $func)
390
    {
391 4
        $isExists = false;
392
393 4
        foreach ($this->elements as $key => $value) {
394 3
            if ($func($key, $value)) {
395 1
                $isExists = true;
396 1
                break;
397
            }
398 4
        }
399
400 4
        return $isExists;
401
    }
402
403
    /**
404
     * Returns the first occurrence of a value that satisfies the predicate $func.
405
     *
406
     * @param callable $func
407
     *
408
     * @return mixed The first occurrence found
409
     */
410 1
    public function find(callable $func)
411
    {
412 1
        $found = null;
413
414 1
        foreach ($this->elements as $key => $value) {
415 1
            if($func($value, $key)) {
416 1
                $found = $value;
417 1
                break;
418
            }
419 1
        }
420
421 1
        return $found;
422
    }
423
424
    /**
425
     * Create an iterator over this array.
426
     *
427
     * @link http://php.net/manual/en/iteratoraggregate.getiterator.php
428
     *
429
     * @return Traversable An instance of an object implementing <b>Iterator</b>
430
     */
431 12
    public function getIterator()
432
    {
433 12
        return new ArrayIterator($this->elements);
434
    }
435
436
    /**
437
     * Return an array all the keys of this array.
438
     *
439
     * @return array An array of all keys
440
     */
441 10
    public function getKeys()
442
    {
443 10
        return array_keys($this->elements);
444
    }
445
446
    /**
447
     * Pick a random value out of this array.
448
     *
449
     * @return mixed Random value of array
450
     *
451
     * @throws \RangeException If array is empty
452
     */
453 3
    public function getRandom()
454
    {
455 3
        return $this->offsetGet($this->getRandomKey());
456
    }
457
458
    /**
459
     * Pick a random key/index from the keys of this array.
460
     *
461
     * @return mixed Random key/index of array
462
     *
463
     * @throws \RangeException If array is empty
464
     */
465 6
    public function getRandomKey()
466
    {
467 6
        return $this->getRandomKeys(1);
468
    }
469
470
    /**
471
     * Pick a given number of random keys/indexes out of this array.
472
     *
473
     * @param int $number The number of keys/indexes (should be <= $this->count())
474
     *
475
     * @return mixed Random keys or key of array
476
     *
477
     * @throws \RangeException
478
     */
479 27
    public function getRandomKeys($number)
480
    {
481 27
        $number = (int) $number;
482
483 27
        $count = $this->count();
484 27
        if ($number === 0 || $number > $count) {
485 3
            throw new \RangeException(sprintf(
486 3
                'Number of requested keys (%s) must be equal or lower than number of elements in this array (%s)',
487 3
                $number,
488
                $count
489 3
            ));
490
        }
491
492 24
        return array_rand($this->elements, $number);
493
    }
494
495
    /**
496
     * Pick a given number of random values with non-duplicate indexes out of the array.
497
     *
498
     * @param int $number The number of values (should be > 1 and < $this->count())
499
     *
500
     * @return array Random values of array
501
     *
502
     * @throws \RangeException
503
     */
504 6
    public function getRandomValues($number)
505
    {
506 6
        $values = [];
507
508 6
        $keys = $number > 1 ? $this->getRandomKeys($number) : [$this->getRandomKeys($number)];
509 6
        foreach ($keys as $key) {
510 6
            $values[] = $this->offsetGet($key);
511 6
        }
512
513 6
        return $values;
514
    }
515
516
    /**
517
     * Return an array of all values from this array numerically indexed.
518
     *
519
     * @return mixed An array of all values
520
     */
521 4
    public function getValues()
522
    {
523 4
        return array_values($this->elements);
524
    }
525
526
    /**
527
     * Alias of search() method. Search for a given element and return
528
     * the index of its first occurrence.
529
     *
530
     * @param mixed $element Value to search for
531
     *
532
     * @return mixed The corresponding key/index
533
     */
534 4
    public function indexOf($element)
535
    {
536 4
        return $this->search($element);
537
    }
538
539
    /**
540
     * Check whether array is associative or not.
541
     *
542
     * @return bool Returns true if associative, false otherwise
543
     */
544 4
    public function isAssoc()
545
    {
546 4
        $isAssoc = false;
547
548 4
        if (!$this->isEmpty()) {
549 3
            $isAssoc = $this->checkType('string');
550 3
        }
551
552 4
        return $isAssoc;
553
    }
554
555
    /**
556
     * Check whether the array is empty or not.
557
     *
558
     * @return bool Returns true if empty, false otherwise
559
     */
560 12
    public function isEmpty()
561
    {
562 12
        return !$this->elements;
563
    }
564
565
    /**
566
     * Check if an array keys are in a given variable type.
567
     *
568
     * @param string $type
569
     *
570
     * @return bool
571
     */
572 6
    private function checkType($type)
573
    {
574 6
        $isInType = true;
575
576 6
        foreach ($this->getKeys() as $key) {
577 6
            if (gettype($key) !== $type) {
578 4
                $isInType = false;
579 4
                break;
580
            }
581 6
        }
582
583 6
        return $isInType;
584
    }
585
586
    /**
587
     * Check whether array is numeric or not.
588
     *
589
     * @return bool Returns true if numeric, false otherwise
590
     */
591 4
    public function isNumeric()
592
    {
593 4
        $isNumeric = false;
594
595 4
        if (!$this->isEmpty()) {
596 3
            $isNumeric = $this->checkType('integer');
597 3
        }
598
599 4
        return $isNumeric;
600
    }
601
602
    /**
603
     * Whether an offset exists.
604
     *
605
     * @param mixed $offset An offset to check for.
606
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
607
     *
608
     * @return boolean true on success or false on failure.
609
     */
610 8
    public function offsetExists($offset)
611
    {
612 8
        return isset($this->elements[$offset]);
613
    }
614
615
    /**
616
     * Retrieve the current offset or null.
617
     *
618
     * @param mixed $offset The offset to retrieve.
619
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
620
     *
621
     * @return mixed Can return all value types.
622
     */
623 13
    public function offsetGet($offset)
624
    {
625 13
        return isset($this->elements[$offset])
626 13
            ? $this->elements[$offset]
627 11
            : null
628 13
        ;
629
    }
630
631
    /**
632
     * Set an offset for this array.
633
     *
634
     * @param mixed $offset The offset to assign the value to.
635
     * @param mixed $value The value to set.
636
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
637
     *
638
     * @return $this
639
     */
640 14
    public function offsetSet($offset, $value)
641
    {
642 14
        if (isset($offset)) {
643 10
            $this->elements[$offset] = $value;
644 10
        } else {
645 4
            $this->elements[] = $value;
646
        }
647
648 14
        return $this;
649
    }
650
651
    /**
652
     * Remove a present offset.
653
     *
654
     * @param mixed $offset The offset to unset.
655
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
656
     *
657
     * @return $this
658
     */
659 10
    public function offsetUnset($offset)
660
    {
661 10
        unset($this->elements[$offset]);
662
663 10
        return $this;
664
    }
665
666
    /**
667
     * Return slice of an array with just a given keys.
668
     *
669
     * @param array $keys List of keys to return
670
     *
671
     * @return AbstractArray The created array
672
     */
673 3
    public function only(array $keys)
674
    {
675 3
        return new static(array_intersect_key($this->elements, array_flip($keys)));
676
    }
677
678
    /**
679
     * Reduce the array to a single value iteratively combining all values using $func.
680
     *
681
     * @param callable $func callback ($carry, $item) -> next $carry
682
     * @param mixed|null $initial starting value of the $carry
683
     *
684
     * @return mixed Final value of $carry
685
     */
686 1
    public function reduce(callable $func, $initial = null)
687
    {
688 1
        return array_reduce($this->elements, $func, $initial);
689
    }
690
691
    /**
692
     * Search for a given element and return the index of its first occurrence.
693
     *
694
     * @param mixed $element Value to search for
695
     *
696
     * @return mixed The corresponding key/index
697
     */
698 4
    public function search($element)
699
    {
700 4
        return array_search($element, $this->elements, true);
701
    }
702
}
703