Passed
Push — master ( 51e64f...74e7c8 )
by Hung
01:39
created

ResultSet::__construct()   A

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 9.4285
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
    public function offsetExists($offset)
91
    {
92
        return $this->hasRow($offset);
93
    }
94
95
    /**
96
     * @inheritdoc
97
     */
98
    public function offsetGet($offset)
99
    {
100
        return $this->toRow($offset)->fetchAssoc();
101
    }
102
103
    /**
104
     * @inheritdoc
105
     * @codeCoverageIgnore
106
     */
107
    public function offsetSet($offset, $value)
108
    {
109
        throw new \BadMethodCallException('Not implemented');
110
    }
111
112
    /**
113
     * @inheritdoc
114
     * @codeCoverageIgnore
115
     */
116
    public function offsetUnset($offset)
117
    {
118
        throw new \BadMethodCallException('Not implemented');
119
    }
120
121
    /**
122
     * @inheritdoc
123
     */
124
    public function current()
125
    {
126
        $row = $this->fetched;
127
        unset($this->fetched);
128
129
        return $row;
130
    }
131
132
    /**
133
     * @inheritdoc
134
     */
135
    public function next()
136
    {
137
        $this->fetched = $this->fetch(true);
138
    }
139
140
    /**
141
     * @inheritdoc
142
     */
143
    public function key()
144
    {
145
        return (int)$this->cursor;
146
    }
147
148
    /**
149
     * @inheritdoc
150
     */
151
    public function valid()
152
    {
153
        if ($this->stored !== null) {
154
            return $this->hasRow($this->cursor);
155
        }
156
157
        return $this->adapter->valid();
158
    }
159
160
    /**
161
     * @inheritdoc
162
     */
163
    public function rewind()
164
    {
165
        if ($this->stored === null) {
166
            $this->adapter->rewind();
167
        }
168
169
        $this->next_cursor = 0;
170
171
        $this->fetched = $this->fetch(true);
172
    }
173
174
    /**
175
     * Returns the number of rows in the result set
176
     * @inheritdoc
177
     */
178
    public function count()
179
    {
180
        return $this->num_rows;
181
    }
182
183
    protected function init()
184
    {
185
        if ($this->adapter->isDml()) {
186
            $this->affected_rows = $this->adapter->getAffectedRows();
187
        } else {
188
            $this->num_rows = $this->adapter->getNumRows();
189
            $this->fields = $this->adapter->getFields();
190
        }
191
    }
192
193
    /**
194
     * @param array $numeric_array
195
     *
196
     * @return array
197
     */
198
    protected function makeAssoc($numeric_array)
199
    {
200
        $assoc_array = array();
201
        foreach ($numeric_array as $col_key => $col_value) {
202
            $assoc_array[$this->fields[$col_key]->name] = $col_value;
203
        }
204
205
        return $assoc_array;
206
    }
207
208
    /**
209
     * @param bool $assoc
210
     *
211
     * @return array|bool|null
212
     */
213
    protected function fetchFromStore($assoc = true)
214
    {
215
        if ($this->stored === null) {
216
            return false;
217
        }
218
219
        $row = isset($this->stored[$this->cursor]) ? $this->stored[$this->cursor] : null;
220
221
        if ($row !== null) {
222
            $row = $assoc ? $this->makeAssoc($row) : $row;
223
        }
224
225
        return $row;
226
    }
227
228
    /**
229
     * @param bool $assoc
230
     *
231
     * @return array|bool
232
     */
233
    protected function fetchAllFromStore($assoc)
234
    {
235
        if ($this->stored === null) {
236
            return false;
237
        }
238
239
        $result_from_store = array();
240
241
        $this->cursor = $this->next_cursor;
242
        while ($row = $this->fetchFromStore($assoc)) {
243
            $result_from_store[] = $row;
244
            $this->cursor = ++$this->next_cursor;
245
        }
246
247
        return $result_from_store;
248
    }
249
250
    /**
251
     * @param bool $assoc
252
     *
253
     * @return array
254
     */
255
    protected function fetchAll($assoc = true)
256
    {
257
        $fetch_all_result = $this->fetchAllFromStore($assoc);
258
259
        if ($fetch_all_result === false) {
260
            $fetch_all_result = $this->adapter->fetchAll($assoc);
261
        }
262
263
        $this->cursor = $this->num_rows;
264
        $this->next_cursor = $this->cursor + 1;
265
266
        return $fetch_all_result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $fetch_all_result also could return the type true which is incompatible with the documented return type array.
Loading history...
267
    }
268
269
    /**
270
     * @inheritdoc
271
     */
272
    public function store()
273
    {
274
        if ($this->stored !== null) {
275
            return $this;
276
        }
277
278
        if ($this->adapter->isDml()) {
279
            $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...
280
        } else {
281
            $this->stored = $this->adapter->store();
282
        }
283
284
        return $this;
285
    }
286
287
    /**
288
     * @inheritdoc
289
     */
290
    public function getStored()
291
    {
292
        $this->store();
293
        if ($this->adapter->isDml()) {
294
            return $this->getAffectedRows();
295
        }
296
297
        return $this->fetchAllAssoc();
298
    }
299
300
    /**
301
     * @inheritdoc
302
     */
303
    public function toRow($num)
304
    {
305
        if (!$this->hasRow($num)) {
306
            throw new ResultSetException('The row does not exist.');
307
        }
308
309
        $this->cursor = $num;
310
        $this->next_cursor = $num;
311
312
        if ($this->stored === null) {
313
            $this->adapter->toRow($this->cursor);
314
        }
315
316
        return $this;
317
    }
318
319
    /**
320
     * @inheritdoc
321
     */
322
    public function toNextRow()
323
    {
324
        $this->toRow(++$this->cursor);
325
326
        return $this;
327
    }
328
329
    /**
330
     * @inheritdoc
331
     */
332
    public function fetchAllAssoc()
333
    {
334
        return $this->fetchAll(true);
335
    }
336
337
    /**
338
     * @inheritdoc
339
     */
340
    public function fetchAllNum()
341
    {
342
        return $this->fetchAll(false);
343
    }
344
345
    /**
346
     * @inheritdoc
347
     */
348
    public function fetchAssoc()
349
    {
350
        return $this->fetch(true);
351
    }
352
353
    /**
354
     * @inheritdoc
355
     */
356
    public function fetchNum()
357
    {
358
        return $this->fetch(false);
359
    }
360
361
    /**
362
     * @param bool $assoc
363
     *
364
     * @return array|null
365
     */
366
    protected function fetch($assoc = true)
367
    {
368
        $this->cursor = $this->next_cursor;
369
370
        $row = $this->fetchFromStore($assoc);
371
372
        if ($row === false) {
373
            $row = $this->adapter->fetch($assoc);
374
        }
375
376
        $this->next_cursor++;
377
378
        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 null|array.
Loading history...
379
    }
380
381
    /**
382
     * @inheritdoc
383
     */
384
    public function freeResult()
385
    {
386
        $this->adapter->freeResult();
387
388
        return $this;
389
    }
390
}
391