Passed
Push — 1.x ( b7bde1...3cc805 )
by Ulises Jeremias
02:11
created

SliceIterator::__construct()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 28
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 6
eloc 13
nc 7
nop 3
dl 0
loc 28
rs 8.439
c 1
b 0
f 1
1
<?php namespace Mbh\Iterator;
2
3
/**
4
 * MBHFramework
5
 *
6
 * @link      https://github.com/MBHFramework/mbh-framework
7
 * @copyright Copyright (c) 2017 Ulises Jeremias Cornejo Fandos
8
 * @license   https://github.com/MBHFramework/mbh-framework/blob/master/LICENSE (MIT License)
9
 */
10
11
use Mbh\Collection\Interfaces\Sequenceable as SequenceableInterface;
12
use ArrayAccess;
13
use LimitIterator;
14
use JsonSerializable;
15
use Countable;
16
use Iterator;
17
use InvalidArgumentException;
18
use RuntimeException;
19
20
/**
21
* Iterator to allow a slice to be used like an array
22
*/
23
24
class SliceIterator extends LimitIterator implements SequenceableInterface
25
{
26
    use \Mbh\Collection\Traits\Collection;
27
28
    protected $count = 0;
29
    protected $begin = 0;
30
31
    const INVALID_INDEX = 'Index invalid or out of range';
32
33
    /**
34
     * Build an iterator over a slice of an ArrayAccess object
35
     * Unlike a LimitIterator, the $end defines the last index, not the count
36
     *
37
     * @param Iterator $iterator An ArrayAccess iterator, e.g. SplFixedArray
38
     * @param int $begin The starting offset of the slice
39
     * @param int $end The last index of the slice
40
     */
41
    public function __construct(Iterator $iterator, $begin = 0, $end = null)
42
    {
43
        if ($iterator instanceof ArrayAccess && $iterator instanceof Countable) {
44
            $count = count($iterator);
45
46
            // Negative begin means start from the end
47
            if ($begin < 0) {
48
                $begin = max(0, $count + $begin);
49
            }
50
51
            // If no end set, assume whole array
52
            if ($end === null) {
53
                $end = $count;
54
            } elseif ($end < 0) {
55
                // Ends counting back from start
56
                $end = max($begin, $count + $end);
57
            }
58
59
            // Set the size of iterable object, for quick-lookup
60
            $this->count = max(0, $end - $begin);
61
62
            // Need to store the starting offset to adjust by
63
            $this->begin = $begin;
64
65
            // Init as LimitIterator
66
            parent::__construct($iterator, $this->begin, $this->count);
67
        } else {
68
            throw new InvalidArgumentException('Iterator must be a Countable ArrayAccess');
69
        }
70
    }
71
72
    /**
73
     * Rewind, extended for clean results on empty sets
74
     */
75
    public function rewind()
76
    {
77
        // no need to rewind on empty sets
78
        if ($this->count > 0) {
79
            parent::rewind();
80
        }
81
    }
82
83
    public function clear()
84
    {
85
    }
86
87
    /**
88
     * Countable
89
     */
90
    public function count(): int
91
    {
92
        return $this->count;
93
    }
94
95
    /**
96
     * ArrayAccess
97
     */
98
    public function offsetExists($offset)
99
    {
100
        return $offset >= 0 && $offset < $this->count;
101
    }
102
103
    public function offsetGet($offset)
104
    {
105
        if ($this->offsetExists($offset)) {
106
            return $this->getInnerIterator()->offsetGet($offset + $this->begin);
0 ignored issues
show
Bug introduced by
The method offsetGet() does not exist on Iterator. It seems like you code against a sub-type of Iterator such as SplDoublyLinkedList or SplFixedArray or SplObjectStorage or Mbh\Collection\Interfaces\Sequenceable or CachingIterator or Guzzle\Iterator\MethodProxyIterator or Mbh\Iterator\ConcatIterator or Mbh\Iterator\SliceIterator or Phar or ArrayIterator or Phar or Phar or RecursiveCachingIterator or RecursiveArrayIterator or SimpleXMLIterator or Phar. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

106
            return $this->getInnerIterator()->/** @scrutinizer ignore-call */ offsetGet($offset + $this->begin);
Loading history...
107
        } else {
108
            throw new RuntimeException(self::INVALID_INDEX);
109
        }
110
    }
111
112
    public function offsetSet($offset, $value)
113
    {
114
        return $this->getInnerIterator()->offsetSet($offset + $this->begin, $value);
0 ignored issues
show
Bug introduced by
The method offsetSet() does not exist on Iterator. It seems like you code against a sub-type of Iterator such as SplDoublyLinkedList or SplFixedArray or SplObjectStorage or Mbh\Collection\Interfaces\Sequenceable or CachingIterator or Guzzle\Iterator\MethodProxyIterator or Mbh\Iterator\ConcatIterator or Mbh\Iterator\SliceIterator or Phar or ArrayIterator or Phar or Phar or RecursiveCachingIterator or RecursiveArrayIterator or SimpleXMLIterator or Phar. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

114
        return $this->getInnerIterator()->/** @scrutinizer ignore-call */ offsetSet($offset + $this->begin, $value);
Loading history...
115
    }
116
117
    public function offsetUnset($offset)
118
    {
119
        return $this->getInnerIterator()->offsetUnset($offset + $this->begin);
0 ignored issues
show
Bug introduced by
The method offsetUnset() does not exist on Iterator. It seems like you code against a sub-type of Iterator such as SplDoublyLinkedList or SplFixedArray or SplObjectStorage or Mbh\Collection\Interfaces\Sequenceable or CachingIterator or Guzzle\Iterator\MethodProxyIterator or Mbh\Iterator\ConcatIterator or Mbh\Iterator\SliceIterator or Phar or ArrayIterator or Phar or Phar or RecursiveCachingIterator or RecursiveArrayIterator or SimpleXMLIterator or Phar. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

119
        return $this->getInnerIterator()->/** @scrutinizer ignore-call */ offsetUnset($offset + $this->begin);
Loading history...
120
    }
121
122
    public function toArray(): array
123
    {
124
        return iterator_to_array($this, false);
125
    }
126
}
127