These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * soluble-flexstore library |
||
5 | * |
||
6 | * @author Vanvelthem Sébastien |
||
7 | * @link https://github.com/belgattitude/soluble-flexstore |
||
8 | * @copyright Copyright (c) 2016-2017 Vanvelthem Sébastien |
||
9 | * @license MIT License https://github.com/belgattitude/soluble-flexstore/blob/master/LICENSE.md |
||
10 | * |
||
11 | */ |
||
12 | |||
13 | namespace Soluble\FlexStore\Source\Zend; |
||
14 | |||
15 | use Soluble\FlexStore\Source\AbstractSource; |
||
16 | use Soluble\FlexStore\Source\QueryableSourceInterface; |
||
17 | use Soluble\FlexStore\ResultSet\ResultSet; |
||
18 | use Soluble\FlexStore\Exception; |
||
19 | use Soluble\FlexStore\Options; |
||
20 | use Zend\Db\Adapter\Adapter; |
||
21 | use Zend\Db\Sql\Sql; |
||
22 | use Zend\Db\Sql\Select; |
||
23 | use Zend\Db\Sql\Expression; |
||
24 | use ArrayObject; |
||
25 | use Soluble\FlexStore\Column\ColumnModel; |
||
26 | use Soluble\FlexStore\Column\Type\MetadataMapper; |
||
27 | use Soluble\Metadata\Reader as MetadataReader; |
||
28 | |||
29 | class SqlSource extends AbstractSource implements QueryableSourceInterface |
||
30 | { |
||
31 | /** |
||
32 | * @var Sql |
||
33 | */ |
||
34 | protected $sql; |
||
35 | |||
36 | /** |
||
37 | * @var Select |
||
38 | */ |
||
39 | protected $select; |
||
40 | |||
41 | /** |
||
42 | * @var Adapter |
||
43 | */ |
||
44 | protected $adapter; |
||
45 | |||
46 | /** |
||
47 | * Initial params received in the constructor. |
||
48 | * |
||
49 | * @var ArrayObject |
||
50 | */ |
||
51 | protected $params; |
||
52 | |||
53 | /** |
||
54 | * @var string |
||
55 | */ |
||
56 | protected $query_string; |
||
57 | |||
58 | /** |
||
59 | * @var \Zend\Db\Adapter\Driver\Mysqli\Statement |
||
60 | */ |
||
61 | protected static $cache_stmt_prototype; |
||
62 | |||
63 | /** |
||
64 | * @var \Zend\Db\Adapter\Driver\ResultInterface |
||
65 | */ |
||
66 | protected static $cache_result_prototype; |
||
67 | |||
68 | /** |
||
69 | * @var ColumnModel |
||
70 | */ |
||
71 | protected $columnModel; |
||
72 | |||
73 | /** |
||
74 | * @param Adapter $adapter |
||
75 | * @param Select $select |
||
76 | */ |
||
77 | 67 | public function __construct(Adapter $adapter, Select $select = null) |
|
78 | { |
||
79 | 67 | $this->adapter = $adapter; |
|
80 | 67 | $this->sql = new Sql($this->adapter); |
|
81 | 67 | if ($select !== null) { |
|
82 | 58 | $this->setSelect($select); |
|
83 | } |
||
84 | 67 | } |
|
85 | |||
86 | /** |
||
87 | * @param Select $select |
||
88 | * |
||
89 | * @return SqlSource |
||
90 | */ |
||
91 | 62 | public function setSelect(Select $select) |
|
92 | { |
||
93 | 62 | $this->select = $select; |
|
94 | |||
95 | 62 | return $this; |
|
96 | } |
||
97 | |||
98 | /** |
||
99 | * @return Select |
||
100 | */ |
||
101 | 38 | public function getSelect() |
|
102 | { |
||
103 | 38 | return $this->select(); |
|
104 | } |
||
105 | |||
106 | /** |
||
107 | * @return Select |
||
108 | */ |
||
109 | 43 | public function select() |
|
110 | { |
||
111 | 43 | if ($this->select === null) { |
|
112 | 14 | $this->select = $this->sql->select(); |
|
113 | } |
||
114 | |||
115 | 43 | return $this->select; |
|
116 | } |
||
117 | |||
118 | /** |
||
119 | * @param Select $select |
||
120 | * @param Options $options |
||
121 | * |
||
122 | * @return Select |
||
123 | */ |
||
124 | 38 | protected function assignOptions(Select $select, Options $options) |
|
125 | { |
||
126 | 38 | if ($options->hasLimit()) { |
|
127 | 8 | $select->limit($options->getLimit()); |
|
128 | 8 | if ($options->hasOffset()) { |
|
129 | 3 | $select->offset($options->getOffset()); |
|
130 | } |
||
131 | |||
132 | 8 | if ($options->getLimit() > 0) { |
|
133 | /** |
||
134 | * For mysql queries, to allow counting rows we must prepend |
||
135 | * SQL_CALC_FOUND_ROWS to the select quantifiers. |
||
136 | */ |
||
137 | 6 | $calc_found_rows = 'SQL_CALC_FOUND_ROWS'; |
|
138 | 6 | $quant_state = $select->getRawState($select::QUANTIFIER); |
|
139 | 6 | if ($quant_state !== null) { |
|
140 | 1 | if ($quant_state instanceof Expression) { |
|
141 | 1 | $quant_state->setExpression($calc_found_rows . ' ' . $quant_state->getExpression()); |
|
142 | 1 | } elseif (is_string($quant_state)) { |
|
143 | 1 | $quant_state = $calc_found_rows . ' ' . $quant_state; |
|
144 | } |
||
145 | 1 | $select->quantifier($quant_state); |
|
146 | } else { |
||
147 | 6 | $select->quantifier(new Expression($calc_found_rows)); |
|
148 | } |
||
149 | } |
||
150 | } |
||
151 | |||
152 | 38 | return $select; |
|
153 | } |
||
154 | |||
155 | /** |
||
156 | * @param Options $options |
||
157 | * |
||
158 | * @throws Exception\EmptyQueryException |
||
159 | * @throws Exception\ErrorException |
||
160 | * |
||
161 | * @return ResultSet |
||
162 | */ |
||
163 | 38 | public function getData(Options $options = null) |
|
164 | { |
||
165 | 38 | if ($options === null) { |
|
166 | 21 | $options = $this->getOptions(); |
|
167 | } |
||
168 | |||
169 | 38 | $select = $this->assignOptions(clone $this->getSelect(), $options); |
|
170 | |||
171 | 38 | $sql = new Sql($this->adapter); |
|
172 | |||
173 | 38 | $sql_string = $sql->buildSqlString($select); |
|
174 | //echo $this->select->getSqlString($this->adapter->getPlatform()); |
||
175 | //echo "----" . var_dump($sql_string) . "----\n"; |
||
176 | // In ZF 2.3.0 an empty query will return SELECT .* |
||
177 | // In ZF 2.4.0 and empty query will return SELECT * |
||
178 | 38 | if (in_array($sql_string, ['', 'SELECT .*', 'SELECT *'], true)) { |
|
179 | 2 | throw new Exception\EmptyQueryException(__METHOD__ . ': Cannot return data of an empty query'); |
|
180 | } |
||
181 | 36 | $this->query_string = $sql_string; |
|
182 | |||
183 | try { |
||
184 | 36 | $results = $this->adapter->query($sql_string, Adapter::QUERY_MODE_EXECUTE); |
|
185 | //$stmt = $sql->prepareStatementForSqlObject( $select ); |
||
186 | //$results = $stmt->execute(); |
||
187 | //var_dump(get_class($results)); |
||
188 | |||
189 | 36 | $r = new ResultSet($results); |
|
0 ignored issues
–
show
|
|||
190 | 36 | $r->setSource($this); |
|
191 | 36 | $r->setHydrationOptions($options->getHydrationOptions()); |
|
192 | |||
193 | 36 | if ($options->hasLimit() && $options->getLimit() > 0) { |
|
194 | //$row = $this->adapter->query('select FOUND_ROWS() as total_count')->execute()->current(); |
||
195 | 6 | $row = $this->adapter->createStatement('select FOUND_ROWS() as total_count')->execute()->current(); |
|
196 | 6 | $r->setTotalRows($row['total_count']); |
|
197 | } else { |
||
198 | 36 | $r->setTotalRows($r->count()); |
|
199 | } |
||
200 | } catch (\Exception $e) { |
||
201 | throw new Exception\ErrorException(__METHOD__ . ': Cannot retrieve data (' . $e->getMessage() . ')'); |
||
202 | } |
||
203 | |||
204 | 36 | return $r; |
|
205 | } |
||
206 | |||
207 | 29 | public function loadDefaultColumnModel() |
|
208 | { |
||
209 | 29 | $sql = new Sql($this->adapter); |
|
210 | 29 | $select = clone $this->select; |
|
211 | 29 | $select->limit(0); |
|
212 | 29 | $sql_string = $sql->getSqlStringForSqlObject($select); |
|
0 ignored issues
–
show
The method
Zend\Db\Sql\Sql::getSqlStringForSqlObject() has been deprecated with message: Deprecated in 2.4. Use buildSqlString() instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.
Loading history...
|
|||
213 | 29 | $metadata_columns = $this->getMetadataReader()->getColumnsMetadata($sql_string); |
|
214 | 29 | $this->setColumnModel(MetadataMapper::getColumnModelFromMetadata($metadata_columns)); |
|
215 | 29 | } |
|
216 | |||
217 | /** |
||
218 | * {@inheritdoc} |
||
219 | * |
||
220 | * @throws Exception\UnsupportedFeatureException |
||
221 | */ |
||
222 | 31 | public function getMetadataReader() |
|
223 | { |
||
224 | 31 | if ($this->metadataReader === null) { |
|
225 | 31 | $this->setMetadataReader($this->getDefaultMetadataReader()); |
|
226 | } |
||
227 | |||
228 | 31 | return $this->metadataReader; |
|
229 | } |
||
230 | |||
231 | /** |
||
232 | * @throws Exception\UnsupportedFeatureException |
||
233 | */ |
||
234 | 31 | protected function getDefaultMetadataReader() |
|
235 | { |
||
236 | 31 | $conn = $this->adapter->getDriver()->getConnection()->getResource(); |
|
237 | 31 | $class = strtolower(get_class($conn)); |
|
238 | switch ($class) { |
||
239 | 31 | case 'pdo': |
|
240 | return new MetadataReader\PdoMysqlMetadataReader($conn); |
||
241 | 31 | case 'mysqli': |
|
242 | 31 | return new MetadataReader\MysqliMetadataReader($conn); |
|
243 | default: |
||
244 | throw new Exception\UnsupportedFeatureException(__METHOD__ . " Does not support default metadata reader for driver '$class'"); |
||
245 | } |
||
246 | } |
||
247 | |||
248 | /** |
||
249 | * Return the query string that was executed. |
||
250 | * |
||
251 | * @throws Exception\InvalidUsageException |
||
252 | * |
||
253 | * @return string |
||
254 | */ |
||
255 | 5 | public function getQueryString() |
|
256 | { |
||
257 | 5 | if ($this->query_string == '') { |
|
258 | 1 | throw new Exception\InvalidUsageException(__METHOD__ . ': Invalid usage, getQueryString must be called after data has been loaded (performance reason).'); |
|
259 | } |
||
260 | |||
261 | 4 | return str_replace("\n", ' ', $this->query_string); |
|
262 | } |
||
263 | |||
264 | /** |
||
265 | * Return the query string. |
||
266 | * |
||
267 | * @throws Exception\InvalidUsageException |
||
268 | * |
||
269 | * @return string |
||
270 | */ |
||
271 | 2 | public function __toString() |
|
272 | { |
||
273 | 2 | if (trim($this->query_string) != '') { |
|
274 | 2 | $sql = str_replace("\n", ' ', $this->query_string); |
|
275 | } elseif ($this->select !== null) { |
||
276 | $sql = $this->sql->getSqlStringForSqlObject($this->select); |
||
0 ignored issues
–
show
The method
Zend\Db\Sql\Sql::getSqlStringForSqlObject() has been deprecated with message: Deprecated in 2.4. Use buildSqlString() instead
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.
Loading history...
|
|||
277 | } else { |
||
278 | throw new Exception\InvalidUsageException(__METHOD__ . ': No select given.'); |
||
279 | } |
||
280 | |||
281 | 2 | return $sql; |
|
282 | } |
||
283 | } |
||
284 |
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: