Completed
Push — master ( 18f9b1...e2cca3 )
by Dawid
07:34
created

LazyCollection::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Igni\Storage\Mapping\Collection;
4
5
use Igni\Exception\OutOfBoundsException;
6
use Igni\Storage\Driver\Cursor;
7
8
class LazyCollection implements \Igni\Storage\Mapping\Collection
9
{
10
    protected $cursor;
11
    protected $length;
12
    protected $current;
13
    protected $items = [];
14
    protected $pointer = 0;
15
    protected $complete = false;
16
17 14
    public function __construct(Cursor $cursor)
18
    {
19 14
        $this->cursor = $cursor;
20 14
    }
21
22
    public function contains($item): bool
23
    {
24
        foreach ($this as $element) {
25
            if ($element === $item) {
26
                return true;
27
            }
28
        }
29
30
        return false;
31
    }
32
33
    public function first()
34
    {
35
        $this->pointer = 0;
36
        if ($this->pointer < $this->length) {
37
            return $this->current = $this->items[$this->pointer];
38
        }
39
        return $this->current();
40
    }
41
42 3
    public function last()
43
    {
44 3
        while ($this->valid()) {
45 3
            $this->current();
46 3
            $this->next();
47
        }
48
49 3
        return $this->current();
50
    }
51
52 2
    public function at(int $index)
53
    {
54 2
        $item = null;
55 2
        if ($index < $this->length) {
56 2
            return $this->current = $this->items[$index];
57
        }
58
59
        if ($this->complete) {
60
            throw OutOfBoundsException::forInvalidOffset($index);
0 ignored issues
show
Bug introduced by
The method forInvalidOffset() does not exist on Igni\Exception\OutOfBoundsException. ( Ignorable by Annotation )

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

60
            throw OutOfBoundsException::/** @scrutinizer ignore-call */ forInvalidOffset($index);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
61
        }
62
63
        $savedPointer = $this->pointer;
64
        while ($this->pointer <= $index) {
65
            $item = $this->current();
66
            if (!$this->valid()) {
67
                break;
68
            }
69
            $this->next();
70
        }
71
72
        if ($this->pointer < $index && $this->complete) {
73
            $offset = $this->pointer;
74
            $this->pointer = $savedPointer;
75
            throw OutOfBoundsException::forInvalidOffset($offset);
76
        }
77
78
        $this->pointer = $savedPointer;
79
80
        return $item;
81
    }
82
83 4
    public function current()
84
    {
85
        // Empty resultset or out of bounds.
86 4
        if ($this->cursor === null &&
87 4
            $this->current === null &&
88 4
            ($this->pointer > $this->length || ($this->length === null && $this->complete))
89
        ) {
90
            throw OutOfBoundsException::forInvalidOffset($this->pointer);
91
        }
92
93 4
        if (null === $this->current) {
94 4
            if ($this->pointer < $this->length) {
95
                $this->current = $this->items[$this->pointer];
96
            } else {
97 4
                $this->items[$this->pointer] = $this->current = $this->cursor->current();
98
            }
99
        }
100
101 4
        return $this->current;
102
    }
103
104 3
    public function next(): void
105
    {
106 3
        $this->pointer++;
107
108 3
        if ($this->pointer < $this->length) {
109
            $this->current = $this->items[$this->pointer];
110 3
        } else if ($this->cursor) {
111 3
            if ($this->pointer > $this->length) {
112 3
                $this->length = $this->pointer;
113
            }
114 3
            $this->cursor->next();
115 3
            if ($this->cursor->valid()) {
116 3
                $this->items[$this->pointer] = $this->current = $this->cursor->current();
117
            }
118
        }
119 3
    }
120
121
    public function previous(): void
122
    {
123
        if ($this->pointer > 0) {
124
            $this->pointer--;
125
        }
126
    }
127
128
    public function key()
129
    {
130
        if (!$this->current) {
131
            $this->current();
132
        }
133
        return $this->pointer;
134
    }
135
136
    public function index(): int
137
    {
138
        return $this->pointer;
139
    }
140
141 3
    public function valid(): bool
142
    {
143 3
        if ($this->pointer < $this->length) {
144
            return true;
145
        }
146
147 3
        if ($this->cursor) {
148 3
            $valid = $this->cursor->valid();
149
150 3
            if (!$valid) {
151 3
                $this->complete = true;
152
153 3
                $this->cursor->close();
154 3
                $this->cursor = null;
155
            }
156
157 3
            return $valid;
158
        }
159
160
        return false;
161
    }
162
163
    public function rewind(): void
164
    {
165
        $this->pointer = 0;
166
        $this->current = null;
167
    }
168
169 2
    public function count(): int
170
    {
171 2
        if ($this->complete) {
172
            return $this->length;
173
        }
174 2
        $this->last();
175
176 2
        return $this->length;
177
    }
178
179 1
    public function toArray(): array
180
    {
181 1
        if ($this->complete) {
182
            return $this->items;
183
        }
184 1
        $this->last();
185
186 1
        return $this->items;
187
    }
188
}
189