1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Foolz\SphinxQL\Drivers; |
4
|
|
|
|
5
|
|
|
use Foolz\SphinxQL\Exception\DatabaseException; |
6
|
|
|
|
7
|
|
|
class MultiResultSet implements MultiResultSetInterface |
8
|
|
|
{ |
9
|
|
|
/** |
10
|
|
|
* @var null|array |
11
|
|
|
*/ |
12
|
|
|
protected $stored; |
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 ResultSetInterface|null |
26
|
|
|
*/ |
27
|
|
|
protected $rowSet; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var MultiResultSetAdapterInterface |
31
|
|
|
*/ |
32
|
|
|
protected $adapter; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var bool |
36
|
|
|
*/ |
37
|
|
|
protected $valid = true; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @param MultiResultSetAdapterInterface $adapter |
41
|
|
|
*/ |
42
|
|
|
public function __construct(MultiResultSetAdapterInterface $adapter) |
43
|
|
|
{ |
44
|
|
|
$this->adapter = $adapter; |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @inheritdoc |
49
|
|
|
*/ |
50
|
|
|
public function getStored() |
51
|
|
|
{ |
52
|
|
|
$this->store(); |
53
|
|
|
|
54
|
|
|
return $this->stored; |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* @inheritdoc |
59
|
|
|
*/ |
60
|
|
|
public function offsetExists($offset) |
61
|
|
|
{ |
62
|
|
|
$this->store(); |
63
|
|
|
|
64
|
|
|
return $this->storedValid($offset); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* @inheritdoc |
69
|
|
|
*/ |
70
|
|
|
public function offsetGet($offset) |
71
|
|
|
{ |
72
|
|
|
$this->store(); |
73
|
|
|
|
74
|
|
|
return $this->stored[$offset]; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @inheritdoc |
79
|
|
|
* @codeCoverageIgnore |
80
|
|
|
*/ |
81
|
|
|
public function offsetSet($offset, $value) |
82
|
|
|
{ |
83
|
|
|
throw new \BadMethodCallException('Not implemented'); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @inheritdoc |
88
|
|
|
* @codeCoverageIgnore |
89
|
|
|
*/ |
90
|
|
|
public function offsetUnset($offset) |
91
|
|
|
{ |
92
|
|
|
throw new \BadMethodCallException('Not implemented'); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* @inheritdoc |
97
|
|
|
*/ |
98
|
|
|
public function next() |
99
|
|
|
{ |
100
|
|
|
$this->rowSet = $this->getNext(); |
|
|
|
|
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* @inheritdoc |
105
|
|
|
*/ |
106
|
|
|
public function key() |
107
|
|
|
{ |
108
|
|
|
return (int)$this->cursor; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* @inheritdoc |
113
|
|
|
*/ |
114
|
|
|
public function rewind() |
115
|
|
|
{ |
116
|
|
|
// we actually can't roll this back unless it was stored first |
117
|
|
|
$this->cursor = 0; |
118
|
|
|
$this->next_cursor = 0; |
119
|
|
|
$this->rowSet = $this->getNext(); |
|
|
|
|
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* @inheritdoc |
124
|
|
|
*/ |
125
|
|
|
public function count() |
126
|
|
|
{ |
127
|
|
|
$this->store(); |
128
|
|
|
|
129
|
|
|
return count($this->stored); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* @inheritdoc |
134
|
|
|
*/ |
135
|
|
|
public function valid() |
136
|
|
|
{ |
137
|
|
|
if ($this->stored !== null) { |
138
|
|
|
return $this->storedValid(); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
return $this->adapter->valid(); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* @inheritdoc |
146
|
|
|
*/ |
147
|
|
|
public function current() |
148
|
|
|
{ |
149
|
|
|
$rowSet = $this->rowSet; |
150
|
|
|
unset($this->rowSet); |
151
|
|
|
|
152
|
|
|
return $rowSet; |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
/** |
156
|
|
|
* @param null|int $cursor |
157
|
|
|
* |
158
|
|
|
* @return bool |
159
|
|
|
*/ |
160
|
|
|
protected function storedValid($cursor = null) |
161
|
|
|
{ |
162
|
|
|
$cursor = (!is_null($cursor) ? $cursor : $this->cursor); |
163
|
|
|
|
164
|
|
|
return $cursor >= 0 && $cursor < count($this->stored); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* @inheritdoc |
169
|
|
|
*/ |
170
|
|
|
public function getNext() |
171
|
|
|
{ |
172
|
|
|
$this->cursor = $this->next_cursor; |
173
|
|
|
|
174
|
|
|
if ($this->stored !== null) { |
175
|
|
|
$resultSet = !$this->storedValid() ? false : $this->stored[$this->cursor]; |
176
|
|
|
} else { |
177
|
|
|
if ($this->next_cursor > 0) { |
178
|
|
|
$this->adapter->getNext(); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
$resultSet = !$this->adapter->valid() ? false : $this->adapter->current(); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
$this->next_cursor++; |
185
|
|
|
|
186
|
|
|
return $resultSet; |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* @inheritdoc |
191
|
|
|
*/ |
192
|
|
|
public function store() |
193
|
|
|
{ |
194
|
|
|
if ($this->stored !== null) { |
195
|
|
|
return $this; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
// don't let users mix storage and driver cursors |
199
|
|
|
if ($this->next_cursor > 0) { |
200
|
|
|
throw new DatabaseException('The MultiResultSet is using the driver cursors, store() can\'t fetch all the data'); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
$store = array(); |
204
|
|
|
while ($set = $this->getNext()) { |
205
|
|
|
// this relies on stored being null! |
206
|
|
|
$store[] = $set->store(); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
$this->cursor = 0; |
210
|
|
|
$this->next_cursor = 0; |
211
|
|
|
|
212
|
|
|
// if we write the array straight to $this->stored it won't be null anymore and functions relying on null will break |
213
|
|
|
$this->stored = $store; |
214
|
|
|
|
215
|
|
|
return $this; |
216
|
|
|
} |
217
|
|
|
} |
218
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.