Passed
Push — 1.x ( b78ae7...e3653f )
by Ulises Jeremias
02:22
created

SliceIterator::offsetUnset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
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 ArrayAccess;
12
use LimitIterator;
13
use JsonSerializable;
14
use Countable;
15
use Iterator;
16
use InvalidArgumentException;
17
use RuntimeException;
18
19
/**
20
* Iterator to allow a slice to be used like an array
21
*/
22
23
class SliceIterator extends LimitIterator implements ArrayAccess, Countable, JsonSerializable
24
{
25
    protected $count = 0;
26
    protected $begin = 0;
27
28
    const INVALID_INDEX = 'Index invalid or out of range';
29
30
    /**
31
     * Build an iterator over a slice of an ArrayAccess object
32
     * Unlike a LimitIterator, the $end defines the last index, not the count
33
     *
34
     * @param Iterator $iterator An ArrayAccess iterator, e.g. SplFixedArray
35
     * @param int $begin The starting offset of the slice
36
     * @param int $end The last index of the slice
37
     */
38
    public function __construct(Iterator $iterator, $begin = 0, $end = null)
39
    {
40
        if ($iterator instanceof ArrayAccess && $iterator instanceof Countable) {
41
            $count = count($iterator);
42
43
            // Negative begin means start from the end
44
            if ($begin < 0) {
45
                $begin = max(0, $count + $begin);
46
            }
47
48
            // If no end set, assume whole array
49
            if ($end === null) {
50
                $end = $count;
51
            } elseif ($end < 0) {
52
                // Ends counting back from start
53
                $end = max($begin, $count + $end);
54
            }
55
56
            // Set the size of iterable object, for quick-lookup
57
            $this->count = max(0, $end - $begin);
58
59
            // Need to store the starting offset to adjust by
60
            $this->begin = $begin;
61
62
            // Init as LimitIterator
63
            parent::__construct($iterator, $this->begin, $this->count);
64
        } else {
65
            throw new InvalidArgumentException('Iterator must be a Countable ArrayAccess');
66
        }
67
    }
68
69
    /**
70
     * Rewind, extended for clean results on empty sets
71
     */
72
    public function rewind()
73
    {
74
        // no need to rewind on empty sets
75
        if ($this->count > 0) {
76
            parent::rewind();
77
        }
78
    }
79
80
    /**
81
     * Countable
82
     */
83
    public function count(): int
84
    {
85
        return $this->count;
86
    }
87
88
    /**
89
     * ArrayAccess
90
     */
91
    public function offsetExists($offset)
92
    {
93
        return $offset >= 0 && $offset < $this->count;
94
    }
95
    
96
    public function offsetGet($offset)
97
    {
98
        if ($this->offsetExists($offset)) {
99
            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

99
            return $this->getInnerIterator()->/** @scrutinizer ignore-call */ offsetGet($offset + $this->begin);
Loading history...
100
        } else {
101
            throw new RuntimeException(self::INVALID_INDEX);
102
        }
103
    }
104
105
    public function offsetSet($offset, $value)
106
    {
107
        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

107
        return $this->getInnerIterator()->/** @scrutinizer ignore-call */ offsetSet($offset + $this->begin, $value);
Loading history...
108
    }
109
110
    public function offsetUnset($offset)
111
    {
112
        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

112
        return $this->getInnerIterator()->/** @scrutinizer ignore-call */ offsetUnset($offset + $this->begin);
Loading history...
113
    }
114
115
    /**
116
     * JsonSerializable
117
     */
118
    public function jsonSerialize()
119
    {
120
        return $this->toArray();
121
    }
122
123
    public function toArray()
124
    {
125
        return iterator_to_array($this, false);
126
    }
127
}
128