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

Statement   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 314
Duplicated Lines 0 %

Test Coverage

Coverage 60.52%

Importance

Changes 0
Metric Value
wmc 52
eloc 94
dl 0
loc 314
ccs 69
cts 114
cp 0.6052
rs 7.44
c 0
b 0
f 0

24 Methods

Rating   Name   Duplication   Size   Complexity  
A isCached() 0 6 2
A __construct() 0 10 1
A next() 0 3 1
A current() 0 6 2
A scannedIndex() 0 6 2
A fetches() 0 3 1
A filtered() 0 6 2
A count() 0 11 3
A fullCount() 0 6 2
A valid() 0 18 5
A result() 0 6 2
A warnings() 0 6 2
A fetchAll() 0 7 3
A writesIgnored() 0 6 2
A resultCount() 0 6 2
A fetchOutstanding() 0 26 5
A writesExecuted() 0 6 2
A key() 0 6 2
A hasMore() 0 6 2
A scannedFull() 0 6 2
A raw() 0 3 1
A fetch() 0 7 3
A rewind() 0 4 1
A cursorId() 0 6 2

How to fix   Complexity   

Complex Class

Complex classes like Statement often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Statement, and based on these observations, apply Extract Interface, too.

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