Completed
Push — master ( d6fc27...dc9f7f )
by Hung
19s
created

ResultSetBase::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
namespace Foolz\SphinxQL\Drivers;
3
4
use Foolz\SphinxQL\Exception\ResultSetException;
5
use \Foolz\SphinxQL\Drivers\Mysqli\ResultSetAdapter;
6
7
abstract class ResultSetBase implements ResultSetInterface
8
{
9
    /**
10
     * @var int
11
     */
12
    protected $num_rows = 0;
13
14
    /**
15
     * @var int
16
     */
17
    protected $cursor = 0;
18
19
    /**
20
     * @var int
21
     */
22
    protected $next_cursor = 0;
23
24
    /**
25
     * @var int
26
     */
27
    protected $affected_rows = 0; // leave to 0 so SELECT etc. will be coherent
28
29
    /**
30
     * @var array
31
     */
32
    protected $fields;
33
34
    /**
35
     * @var null|array
36
     */
37
    protected $stored = null;
38
39
    /**
40
     * @var null|array
41
     */
42
    protected $fetched = null;
43
44
    /**
45
     * @var null|\Foolz\SphinxQL\Drivers\ResultSetAdapterInterface
46
     */
47
    protected $adapter = null;
48
49
    /**
50
     * Checks that a row actually exists
51
     *
52
     * @param int $num The number of the row to check on
53
     * @return bool True if the row exists
54
     */
55
    public function hasRow($num)
56
    {
57
        return $num >= 0 && $num < $this->num_rows;
58
    }
59
60
    /**
61
     * Checks that a next row exists
62
     *
63
     * @return bool True if there's another row with a higher index
64
     */
65
    public function hasNextRow()
66
    {
67
        return $this->cursor + 1 < $this->num_rows;
68
    }
69
70
    /**
71
     * Returns the number of rows affected by the query
72
     * This will be 0 for SELECT and any query not editing rows
73
     *
74
     * @return int
75
     */
76
    public function getAffectedRows()
77
    {
78
        return $this->affected_rows;
79
    }
80
81
    /**
82
     * Returns the number of rows in the result set
83
     *
84
     * @return int The number of rows in the result set
85
     */
86
    public function getCount()
87
    {
88
        return $this->num_rows;
89
    }
90
91
    /**
92
     * (PHP 5 &gt;= 5.0.0)<br/>
93
     * Whether a offset exists
94
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
95
     * @param mixed $offset <p>
96
     * An offset to check for.
97
     * </p>
98
     * @return boolean true on success or false on failure.
99
     * </p>
100
     * <p>
101
     * The return value will be casted to boolean if non-boolean was returned.
102
     */
103
    public function offsetExists($offset)
104
    {
105
        return $this->hasRow($offset);
106
    }
107
108
    /**
109
     * (PHP 5 &gt;= 5.0.0)<br/>
110
     * Offset to retrieve
111
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
112
     * @param mixed $offset <p>
113
     * The offset to retrieve.
114
     * </p>
115
     * @return mixed Can return all value types.
116
     */
117
    public function offsetGet($offset)
118
    {
119
        return $this->toRow($offset)->fetchAssoc();
120
    }
121
122
    /**
123
     * (PHP 5 &gt;= 5.0.0)<br/>
124
     * Offset to set
125
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
126
     * @param mixed $offset <p>
127
     * The offset to assign the value to.
128
     * </p>
129
     * @param mixed $value <p>
130
     * The value to set.
131
     * </p>
132
     * @return void
133
     *
134
     * @codeCoverageIgnore
135
     */
136
    public function offsetSet($offset, $value)
137
    {
138
        throw new \BadMethodCallException('Not implemented');
139
    }
140
141
    /**
142
     * (PHP 5 &gt;= 5.0.0)<br/>
143
     * Offset to unset
144
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
145
     * @param mixed $offset <p>
146
     * The offset to unset.
147
     * </p>
148
     * @return void
149
     *
150
     * @codeCoverageIgnore
151
     */
152
    public function offsetUnset($offset)
153
    {
154
        throw new \BadMethodCallException('Not implemented');
155
    }
156
157
    /**
158
     * (PHP 5 &gt;= 5.0.0)<br/>
159
     * Return the current element
160
     * @link http://php.net/manual/en/iterator.current.php
161
     * @return mixed Can return any type.
162
     */
163
    public function current()
164
    {
165
        $row = $this->fetched;
166
        unset($this->fetched);
167
        return $row;
168
    }
169
170
    /**
171
     * (PHP 5 &gt;= 5.0.0)<br/>
172
     * Move forward to next element
173
     * @link http://php.net/manual/en/iterator.next.php
174
     * @return void Any returned value is ignored.
175
     */
176
    public function next()
177
    {
178
        $this->fetched = $this->fetch(ResultSetAdapter::FETCH_ASSOC);
179
    }
180
181
    /**
182
     * (PHP 5 &gt;= 5.0.0)<br/>
183
     * Return the key of the current element
184
     * @link http://php.net/manual/en/iterator.key.php
185
     * @return mixed scalar on success, or null on failure.
186
     */
187
    public function key()
188
    {
189
        return (int)$this->cursor;
190
    }
191
192
    /**
193
     * (PHP 5 &gt;= 5.0.0)<br/>
194
     * Checks if current position is valid
195
     * @link http://php.net/manual/en/iterator.valid.php
196
     * @return boolean The return value will be casted to boolean and then evaluated.
197
     * Returns true on success or false on failure.
198
     */
199
    public function valid()
200
    {
201
        if ($this->stored !== null) {
202
            return $this->hasRow($this->cursor);
203
        }
204
205
        return $this->adapter->valid();
206
    }
207
208
    /**
209
     * (PHP 5 &gt;= 5.0.0)<br/>
210
     * Rewind the Iterator to the first element
211
     * @link http://php.net/manual/en/iterator.rewind.php
212
     * @return void Any returned value is ignored.
213
     */
214
    public function rewind()
215
    {
216
        if ($this->stored === null) {
217
            $this->adapter->rewind();
218
        }
219
220
        $this->next_cursor = 0;
221
222
        $this->fetched = $this->fetch(ResultSetAdapter::FETCH_ASSOC);
223
    }
224
225
    /**
226
     * (PHP 5 &gt;= 5.1.0)<br/>
227
     * Count elements of an object
228
     * @link http://php.net/manual/en/countable.count.php
229
     * @return int The custom count as an integer.
230
     * </p>
231
     * <p>
232
     * The return value is cast to an integer.
233
     */
234
    public function count()
235
    {
236
        return $this->getCount();
237
    }
238
239
    protected function init()
240
    {
241
        if ($this->adapter->isDml()) {
242
            $this->affected_rows = $this->adapter->getAffectedRows();
243
        } else {
244
            $this->num_rows = $this->adapter->getNumRows();
245
            $this->fields = $this->adapter->getFields();
246
        }
247
    }
248
249
    /**
250
     * @param array $numeric_array
251
     * @return array
252
     */
253
    protected function makeAssoc($numeric_array)
254
    {
255
        $assoc_array = array();
256
        foreach ($numeric_array as $col_key => $col_value) {
257
            $assoc_array[$this->fields[$col_key]->name] = $col_value;
258
        }
259
260
        return $assoc_array;
261
    }
262
263
    /**
264
     * @param ResultSetAdapter::FETCH_ASSOC|ResultSetAdapter::FETCH_NUM $fetch_type
0 ignored issues
show
Documentation introduced by
The doc-type ResultSetAdapter::FETCH_...ltSetAdapter::FETCH_NUM could not be parsed: Unknown type name "ResultSetAdapter::FETCH_ASSOC" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
265
     * @return array|bool|null
266
     */
267
    protected function fetchFromStore($fetch_type)
268
    {
269
        if ($this->stored === null) {
270
            return false;
271
        }
272
273
        $row = isset($this->stored[$this->cursor]) ? $this->stored[$this->cursor] : null;
274
275
        if ($row !== null) {
276
            $row = $fetch_type == ResultSetAdapter::FETCH_ASSOC ? $this->makeAssoc($row) : $row;
277
        }
278
279
        return $row;
280
    }
281
282
    /**
283
     * @param ResultSetAdapter::FETCH_ASSOC|ResultSetAdapter::FETCH_NUM $fetch_type
0 ignored issues
show
Documentation introduced by
The doc-type ResultSetAdapter::FETCH_...ltSetAdapter::FETCH_NUM could not be parsed: Unknown type name "ResultSetAdapter::FETCH_ASSOC" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
284
     * @return array|bool
285
     */
286
    protected function fetchAllFromStore($fetch_type)
287
    {
288
        if ($this->stored === null) {
289
            return false;
290
        }
291
292
        $result_from_store = array();
293
294
        $this->cursor = $this->next_cursor;
295
        while ($row = $this->fetchFromStore($fetch_type)) {
296
            $result_from_store[] = $row;
297
            $this->cursor = ++$this->next_cursor;
298
        }
299
300
        return $result_from_store;
301
    }
302
303
    /**
304
     * @param ResultSetAdapter::FETCH_ASSOC|ResultSetAdapter::FETCH_NUM $fetch_type
0 ignored issues
show
Documentation introduced by
The doc-type ResultSetAdapter::FETCH_...ltSetAdapter::FETCH_NUM could not be parsed: Unknown type name "ResultSetAdapter::FETCH_ASSOC" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
305
     * @return array
306
     */
307
    protected function fetchAll($fetch_type)
308
    {
309
        $fetch_all_result = $this->fetchAllFromStore($fetch_type);
310
311
        if ($fetch_all_result === false) {
312
            $fetch_all_result = $this->adapter->fetchAll($fetch_type);
313
        }
314
315
        $this->cursor = $this->num_rows;
316
        $this->next_cursor = $this->cursor + 1;
317
318
        return $fetch_all_result;
319
    }
320
321
    /**
322
     * Store all the data in this object and free the driver object
323
     *
324
     * @return static $this
325
     */
326
    public function store()
327
    {
328
        if ($this->stored !== null) {
329
            return $this;
330
        }
331
332
        if ($this->adapter->isDml()) {
333
            $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 null|array 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...
334
        } else {
335
            $this->stored = $this->adapter->store();
336
        }
337
338
        return $this;
339
    }
340
341
    /**
342
     * Returns the array as in version 0.9.x
343
     *
344
     * @return array|int|mixed
345
     * @deprecated Commodity method for simple transition to version 1.0.0
346
     */
347
    public function getStored()
348
    {
349
        $this->store();
350
        if ($this->adapter->isDml()) {
351
            return $this->getAffectedRows();
352
        }
353
354
        return $this->fetchAllAssoc();
355
    }
356
357
    /**
358
     * Moves the cursor to the selected row
359
     *
360
     * @param int $num The number of the row to move the cursor to
361
     * @return static
362
     * @throws ResultSetException If the row does not exist
363
     */
364
    public function toRow($num)
365
    {
366
        if (!$this->hasRow($num)) {
367
            throw new ResultSetException('The row does not exist.');
368
        }
369
370
        $this->cursor = $num;
371
        $this->next_cursor = $num;
372
373
        if ($this->stored === null) {
374
            $this->adapter->toRow($this->cursor);
375
        }
376
377
        return $this;
378
    }
379
380
    /**
381
     * Moves the cursor to the next row
382
     *
383
     * @return static $this
384
     * @throws ResultSetException If the next row does not exist
385
     */
386
    public function toNextRow()
387
    {
388
        $this->toRow(++$this->cursor);
389
        return $this;
390
    }
391
392
    /**
393
     * Fetches all the rows as an array of associative arrays
394
     *
395
     * @return array
396
     */
397
    public function fetchAllAssoc()
398
    {
399
        return $this->fetchAll(ResultSetAdapter::FETCH_ASSOC);
400
    }
401
402
    /**
403
     * Fetches all the rows as an array of indexed arrays
404
     *
405
     * @return array
406
     */
407
    public function fetchAllNum()
408
    {
409
        return $this->fetchAll(ResultSetAdapter::FETCH_NUM);
410
    }
411
412
    /**
413
     * Fetches a row as an associative array
414
     *
415
     * @return array
416
     */
417
    public function fetchAssoc()
418
    {
419
        return $this->fetch(ResultSetAdapter::FETCH_ASSOC);
420
    }
421
422
    /**
423
     * Fetches a row as an indexed array
424
     *
425
     * @return array|null
426
     */
427
    public function fetchNum()
428
    {
429
        return $this->fetch(ResultSetAdapter::FETCH_NUM);
430
    }
431
432
    /**
433
     * @param ResultSetAdapter::FETCH_ASSOC|ResultSetAdapter::FETCH_NUM $fetch_type
0 ignored issues
show
Documentation introduced by
The doc-type ResultSetAdapter::FETCH_...ltSetAdapter::FETCH_NUM could not be parsed: Unknown type name "ResultSetAdapter::FETCH_ASSOC" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
434
     * @return array|null
435
     */
436
    protected function fetch($fetch_type)
437
    {
438
        $this->cursor = $this->next_cursor;
439
440
        $row = $this->fetchFromStore($fetch_type);
441
442
        if ($row === false) {
443
            $row = $this->adapter->fetch($fetch_type);
444
        }
445
446
        $this->next_cursor++;
447
448
        return $row;
449
    }
450
451
    /**
452
     * Frees the memory from the result
453
     * Call it after you're done with a result set
454
     *
455
     * @return static
456
     */
457
    public function freeResult()
458
    {
459
        $this->adapter->freeResult();
460
        return $this;
461
    }
462
}
463