Passed
Pull Request — master (#7)
by Sandro
02:17
created

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