Completed
Push — master ( 6578e4...b57e95 )
by Sandro
27s queued 17s
created

Statement::isCached()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 6
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 6
1
<?php
2
/**
3
 * Sandro Keil (https://sandro-keil.de)
4
 *
5
 * @link      http://github.com/sandrokeil/arangodb-php-client for the canonical source repository
6
 * @copyright Copyright (c) 2018-2020 Sandro Keil
7
 * @license   http://github.com/sandrokeil/arangodb-php-client/blob/master/LICENSE.md New BSD License
8
 */
9
10
namespace ArangoDb\Statement;
11
12
use ArangoDb\Exception\NoCursorId;
13
use ArangoDb\Exception\ServerException;
14
use ArangoDb\Http\TypeSupport;
15
use ArangoDb\Type\CursorType;
16
use Countable;
17
use Fig\Http\Message\StatusCodeInterface;
18
use Iterator;
19
use Psr\Http\Client\ClientExceptionInterface;
20
21
/**
22
 * @implements Iterator<int, mixed>
23
 */
24
final class Statement implements QueryResult, Iterator, Countable
25
{
26
    /**
27
     * @var TypeSupport
28
     */
29
    private $client;
30
31
    /**
32
     * @var CursorType
33
     */
34
    private $cursor;
35
36
    /**
37
     * @var StreamHandler
38
     */
39
    private $streamHandler;
40
41
    /**
42
     * @var StreamHandlerFactoryInterface
43
     */
44
    private $streamHandlerFactory;
45
46
    /**
47
     * Number of HTTP calls that were made to build the cursor result
48
     *
49
     * @var int
50
     */
51
    private $fetches = 0;
52
53
    /**
54
     * Query is executed on first access
55
     *
56
     * @param TypeSupport $client - connection to be used
57
     * @param CursorType $cursor
58
     * @param StreamHandlerFactoryInterface $streamHandlerFactory
59
     */
60 7
    public function __construct(
61
        TypeSupport $client,
62
        CursorType $cursor,
63
        StreamHandlerFactoryInterface $streamHandlerFactory
64
    ) {
65 7
        $this->client = $client;
66 7
        $this->cursor = $cursor;
67 7
        $this->streamHandlerFactory = $streamHandlerFactory;
68 7
    }
69
70
    /**
71
     * Fetch outstanding results from the server
72
     *
73
     * @return void
74
     * @throws ClientExceptionInterface
75
     */
76 7
    private function fetchOutstanding(): void
77
    {
78 7
        if ($this->fetches === 0) {
79 7
            $request = $this->cursor;
80
        } else {
81 4
            $cursorId = $this->streamHandler->cursorId();
82
83 4
            if ($cursorId === null) {
84
                throw NoCursorId::forType($this->cursor);
85
            }
86 4
            $request = $this->cursor::nextBatch($cursorId);
87
        }
88 7
        $response = $this->client->sendType($request);
89
90 7
        $httpStatusCode = $response->getStatusCode();
91
92 7
        if ($httpStatusCode < StatusCodeInterface::STATUS_OK
93 7
            || $httpStatusCode > StatusCodeInterface::STATUS_MULTIPLE_CHOICES
94
        ) {
95
            throw ServerException::with($request, $response);
96
        }
97
98 7
        if ($this->fetches === 0) {
99 7
            $this->streamHandler = $this->streamHandlerFactory->createStreamHandler($response->getBody());
100
        } else {
101 4
            $this->streamHandler->appendStream($response->getBody());
102
        }
103 7
        $this->fetches++;
104 7
    }
105
106
    /**
107
     * Fetches next result from server and returns all current loaded results. Null if cursor end has reached.
108
     *
109
     * @return string|array|object|null Data
110
     * @throws ClientExceptionInterface
111
     */
112 1
    public function fetch()
113
    {
114 1
        if (null === $this->streamHandler || $this->streamHandler->hasMore()) {
115 1
            $this->fetchOutstanding();
116 1
            return $this->streamHandler->result();
117
        }
118 1
        return null;
119
    }
120
121
    /**
122
     * Fetches all results from server and returns overall result.
123
     * This might issue additional HTTP requests to fetch any outstanding results from the server.
124
     *
125
     * @return string|array|object Data
126
     * @throws ClientExceptionInterface
127
     */
128 4
    public function fetchAll()
129
    {
130 4
        while (null === $this->streamHandler || $this->streamHandler->hasMore()) {
131 3
            $this->fetchOutstanding();
132
        }
133
134 4
        return $this->streamHandler->completeResult();
135
    }
136
137 1
    public function resultCount(): ?int
138
    {
139 1
        if (null === $this->streamHandler) {
140
            $this->fetchOutstanding();
141
        }
142 1
        return $this->streamHandler->resultCount();
143
    }
144
145 1
    public function result()
146
    {
147 1
        if (null === $this->streamHandler) {
148
            $this->fetchOutstanding();
149
        }
150 1
        return $this->streamHandler->result();
151
    }
152
153
    /**
154
     * Get the total number of results in the cursor.
155
     *
156
     * This might issue additional HTTP requests to fetch any outstanding results from the server.
157
     *
158
     * @return int Total number of results
159
     * @throws ClientExceptionInterface
160
     */
161 1
    public function count()
162
    {
163 1
        if (null === $this->streamHandler) {
164
            $this->fetchOutstanding();
165
        }
166
167 1
        while ($this->streamHandler->hasMore()) {
168 1
            $this->fetchOutstanding();
169
        }
170
171 1
        return $this->streamHandler->count();
172
    }
173
174
    /**
175
     * Rewind the cursor, loads first batch, can be repeated (new cursor will be created)
176
     *
177
     * @return void
178
     * @throws ClientExceptionInterface
179
     */
180 3
    public function rewind()
181
    {
182 3
        $this->fetches = 0;
183 3
        $this->fetchOutstanding();
184 3
    }
185
186
    /**
187
     * Return the current result row depending on stream handler
188
     *
189
     * @return string|array|object Data
190
     */
191 3
    public function current()
192
    {
193 3
        if (null === $this->streamHandler) {
194
            $this->fetchOutstanding();
195
        }
196 3
        return $this->streamHandler->current();
197
    }
198
199 3
    public function key(): int
200
    {
201 3
        if (null === $this->streamHandler) {
202
            $this->fetchOutstanding();
203
        }
204 3
        return $this->streamHandler->key();
205
    }
206
207 3
    public function next(): void
208
    {
209 3
        $this->streamHandler->next();
210 3
    }
211
212
    /**
213
     * @return bool
214
     * @throws ClientExceptionInterface
215
     */
216 3
    public function valid(): bool
217
    {
218 3
        if (null === $this->streamHandler) {
219
            $this->fetchOutstanding();
220
        }
221
222 3
        if (true === $this->streamHandler->valid()) {
223 3
            return true;
224
        }
225
226 3
        if (! $this->streamHandler->hasMore() || $this->streamHandler->cursorId() === null) {
227 3
            return false;
228
        }
229
230
        // need to fetch additional results from the server
231 2
        $this->fetchOutstanding();
232
233 2
        return $this->streamHandler->valid();
234
    }
235
236
    /**
237
     * Returns the number of HTTP calls that were made to build the cursor result
238
     *
239
     * @return int
240
     */
241 7
    public function fetches(): int
242
    {
243 7
        return $this->fetches;
244
    }
245
246
    public function cursorId(): ?string
247
    {
248
        if (null === $this->streamHandler) {
249
            $this->fetchOutstanding();
250
        }
251
        return $this->streamHandler->cursorId();
252
    }
253
254
    public function hasMore(): bool
255
    {
256
        if (null === $this->streamHandler) {
257
            $this->fetchOutstanding();
258
        }
259
        return $this->streamHandler->hasMore();
260
    }
261
262
    public function warnings(): array
263
    {
264
        if (null === $this->streamHandler) {
265
            $this->fetchOutstanding();
266
        }
267
        return $this->streamHandler->warnings();
268
    }
269
270 1
    public function fullCount(): ?int
271
    {
272 1
        if (null === $this->streamHandler) {
273 1
            $this->fetchOutstanding();
274
        }
275 1
        return $this->streamHandler->fullCount();
276
    }
277
278
    public function isCached(): bool
279
    {
280
        if (null === $this->streamHandler) {
281
            $this->fetchOutstanding();
282
        }
283
        return $this->streamHandler->isCached();
284
    }
285
286
    public function writesExecuted(): ?int
287
    {
288
        if (null === $this->streamHandler) {
289
            $this->fetchOutstanding();
290
        }
291
        return $this->streamHandler->writesExecuted();
292
    }
293
294
    public function writesIgnored(): ?int
295
    {
296
        if (null === $this->streamHandler) {
297
            $this->fetchOutstanding();
298
        }
299
        return $this->streamHandler->writesIgnored();
300
    }
301
302
    public function scannedFull(): ?int
303
    {
304
        if (null === $this->streamHandler) {
305
            $this->fetchOutstanding();
306
        }
307
        return $this->streamHandler->scannedFull();
308
    }
309
310
    public function scannedIndex(): ?int
311
    {
312
        if (null === $this->streamHandler) {
313
            $this->fetchOutstanding();
314
        }
315
        return $this->streamHandler->scannedIndex();
316
    }
317
318
    public function filtered(): ?int
319
    {
320
        if (null === $this->streamHandler) {
321
            $this->fetchOutstanding();
322
        }
323
        return $this->streamHandler->filtered();
324
    }
325
326
    /**
327
     * @return string|array|object Complete response body data
328
     */
329
    public function raw()
330
    {
331
        return $this->streamHandler->raw();
332
    }
333
}
334