ResultSet::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Foolz\SphinxQL\Drivers;
4
5
use Foolz\SphinxQL\Drivers\Pdo\ResultSetAdapter as PdoResultSetAdapter;
6
use Foolz\SphinxQL\Exception\ResultSetException;
7
8
class ResultSet implements ResultSetInterface
9
{
10
    /**
11
     * @var int
12
     */
13
    protected $num_rows = 0;
14
15
    /**
16
     * @var int
17
     */
18
    protected $cursor = 0;
19
20
    /**
21
     * @var int
22
     */
23
    protected $next_cursor = 0;
24
25
    /**
26
     * @var int
27
     */
28
    protected $affected_rows = 0; // leave to 0 so SELECT etc. will be coherent
29
30
    /**
31
     * @var array
32
     */
33
    protected $fields;
34
35
    /**
36
     * @var null|array
37
     */
38
    protected $stored;
39
40
    /**
41
     * @var null|array
42
     */
43
    protected $fetched;
44
45
    /**
46
     * @var ResultSetAdapterInterface
47
     */
48
    protected $adapter;
49
50
    /**
51
     * @param ResultSetAdapterInterface $adapter
52
     */
53
    public function __construct(ResultSetAdapterInterface $adapter)
54
    {
55
        $this->adapter = $adapter;
56
        $this->init();
57
58
        if ($adapter instanceof PdoResultSetAdapter) { //only for pdo for some reason
59
            $this->store();
60
        }
61
    }
62
63
    /**
64
     * @inheritdoc
65
     */
66
    public function hasRow($num)
67
    {
68
        return $num >= 0 && $num < $this->num_rows;
69
    }
70
71
    /**
72
     * @inheritdoc
73
     */
74
    public function hasNextRow()
75
    {
76
        return $this->cursor + 1 < $this->num_rows;
77
    }
78
79
    /**
80
     * @inheritdoc
81
     */
82
    public function getAffectedRows()
83
    {
84
        return $this->affected_rows;
85
    }
86
87
    /**
88
     * @inheritdoc
89
     */
90
    #[\ReturnTypeWillChange]
91
    public function offsetExists($offset)
92
    {
93
        return $this->hasRow($offset);
94
    }
95
96
    /**
97
     * @inheritdoc
98
     * @throws ResultSetException
99
     */
100
    #[\ReturnTypeWillChange]
101
    public function offsetGet($offset)
102
    {
103
        return $this->toRow($offset)->fetchAssoc();
104
    }
105
106
    /**
107
     * @inheritdoc
108
     * @codeCoverageIgnore
109
     */
110
    #[\ReturnTypeWillChange]
111
    public function offsetSet($offset, $value)
112
    {
113
        throw new \BadMethodCallException('Not implemented');
114
    }
115
116
    /**
117
     * @inheritdoc
118
     * @codeCoverageIgnore
119
     */
120
    #[\ReturnTypeWillChange]
121
    public function offsetUnset($offset)
122
    {
123
        throw new \BadMethodCallException('Not implemented');
124
    }
125
126
    /**
127
     * @inheritdoc
128
     */
129
    #[\ReturnTypeWillChange]
130
    public function current()
131
    {
132
        $row = $this->fetched;
133
        unset($this->fetched);
134
135
        return $row;
136
    }
137
138
    /**
139
     * @inheritdoc
140
     */
141
    #[\ReturnTypeWillChange]
142
    public function next()
143
    {
144
        $this->fetched = $this->fetch(true);
145
    }
146
147
    /**
148
     * @inheritdoc
149
     */
150
    #[\ReturnTypeWillChange]
151
    public function key()
152
    {
153
        return (int)$this->cursor;
154
    }
155
156
    /**
157
     * @inheritdoc
158
     */
159
    #[\ReturnTypeWillChange]
160
    public function valid()
161
    {
162
        if ($this->stored !== null) {
163
            return $this->hasRow($this->cursor);
164
        }
165
166
        return $this->adapter->valid();
167
    }
168
169
    /**
170
     * @inheritdoc
171
     */
172
    #[\ReturnTypeWillChange]
173
    public function rewind()
174
    {
175
        if ($this->stored === null) {
176
            $this->adapter->rewind();
177
        }
178
179
        $this->next_cursor = 0;
180
181
        $this->fetched = $this->fetch(true);
182
    }
183
184
    /**
185
     * Returns the number of rows in the result set
186
     * @inheritdoc
187
     */
188
    #[\ReturnTypeWillChange]
189
    public function count()
190
    {
191
        return $this->num_rows;
192
    }
193
194
    protected function init()
195
    {
196
        if ($this->adapter->isDml()) {
197
            $this->affected_rows = $this->adapter->getAffectedRows();
198
        } else {
199
            $this->num_rows = $this->adapter->getNumRows();
200
            $this->fields = $this->adapter->getFields();
201
        }
202
    }
203
204
    /**
205
     * @param array $numeric_array
206
     *
207
     * @return array
208
     */
209
    protected function makeAssoc($numeric_array)
210
    {
211
        $assoc_array = array();
212
        foreach ($numeric_array as $col_key => $col_value) {
213
            $assoc_array[$this->fields[$col_key]->name] = $col_value;
214
        }
215
216
        return $assoc_array;
217
    }
218
219
    /**
220
     * @param bool $assoc
221
     *
222
     * @return array|bool|null
223
     */
224
    protected function fetchFromStore($assoc = true)
225
    {
226
        if ($this->stored === null) {
227
            return false;
228
        }
229
230
        $row = isset($this->stored[$this->cursor]) ? $this->stored[$this->cursor] : null;
231
232
        if ($row !== null) {
233
            $row = $assoc ? $this->makeAssoc($row) : $row;
234
        }
235
236
        return $row;
237
    }
238
239
    /**
240
     * @param bool $assoc
241
     *
242
     * @return array|bool
243
     */
244
    protected function fetchAllFromStore($assoc)
245
    {
246
        if ($this->stored === null) {
247
            return false;
248
        }
249
250
        $result_from_store = array();
251
252
        $this->cursor = $this->next_cursor;
253
        while ($row = $this->fetchFromStore($assoc)) {
254
            $result_from_store[] = $row;
255
            $this->cursor = ++$this->next_cursor;
256
        }
257
258
        return $result_from_store;
259
    }
260
261
    /**
262
     * @param bool $assoc
263
     *
264
     * @return array
265
     */
266
    protected function fetchAll($assoc = true)
267
    {
268
        $fetch_all_result = $this->fetchAllFromStore($assoc);
269
270
        if ($fetch_all_result === false) {
0 ignored issues
show
introduced by
The condition $fetch_all_result === false is always false.
Loading history...
271
            $fetch_all_result = $this->adapter->fetchAll($assoc);
272
        }
273
274
        $this->cursor = $this->num_rows;
275
        $this->next_cursor = $this->cursor + 1;
276
277
        return $fetch_all_result;
278
    }
279
280
    /**
281
     * @inheritdoc
282
     */
283
    public function store()
284
    {
285
        if ($this->stored !== null) {
286
            return $this;
287
        }
288
289
        if ($this->adapter->isDml()) {
290
            $this->stored = $this->affected_rows;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->affected_rows of type integer is incompatible with the declared type array|null of property $stored.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
291
        } else {
292
            $this->stored = $this->adapter->store();
293
        }
294
295
        return $this;
296
    }
297
298
    /**
299
     * @inheritdoc
300
     */
301
    public function getStored()
302
    {
303
        $this->store();
304
        if ($this->adapter->isDml()) {
305
            return $this->getAffectedRows();
306
        }
307
308
        return $this->fetchAllAssoc();
309
    }
310
311
    /**
312
     * @inheritdoc
313
     */
314
    public function toRow($num)
315
    {
316
        if (!$this->hasRow($num)) {
317
            throw new ResultSetException('The row does not exist.');
318
        }
319
320
        $this->cursor = $num;
321
        $this->next_cursor = $num;
322
323
        if ($this->stored === null) {
324
            $this->adapter->toRow($this->cursor);
325
        }
326
327
        return $this;
328
    }
329
330
    /**
331
     * @inheritdoc
332
     */
333
    public function toNextRow()
334
    {
335
        $this->toRow(++$this->cursor);
336
337
        return $this;
338
    }
339
340
    /**
341
     * @inheritdoc
342
     */
343
    public function fetchAllAssoc()
344
    {
345
        return $this->fetchAll(true);
346
    }
347
348
    /**
349
     * @inheritdoc
350
     */
351
    public function fetchAllNum()
352
    {
353
        return $this->fetchAll(false);
354
    }
355
356
    /**
357
     * @inheritdoc
358
     */
359
    public function fetchAssoc()
360
    {
361
        return $this->fetch(true);
362
    }
363
364
    /**
365
     * @inheritdoc
366
     */
367
    public function fetchNum()
368
    {
369
        return $this->fetch(false);
370
    }
371
372
    /**
373
     * @param bool $assoc
374
     *
375
     * @return array|null
376
     */
377
    protected function fetch($assoc = true)
378
    {
379
        $this->cursor = $this->next_cursor;
380
381
        $row = $this->fetchFromStore($assoc);
382
383
        if ($row === false) {
384
            $row = $this->adapter->fetch($assoc);
385
        }
386
387
        $this->next_cursor++;
388
389
        return $row;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $row also could return the type true which is incompatible with the documented return type array|null.
Loading history...
390
    }
391
392
    /**
393
     * @inheritdoc
394
     */
395
    public function freeResult()
396
    {
397
        $this->adapter->freeResult();
398
399
        return $this;
400
    }
401
}
402