Total Complexity | 82 |
Total Lines | 524 |
Duplicated Lines | 0 % |
Changes | 3 | ||
Bugs | 2 | Features | 0 |
Complex classes like XoopsMySQLDatabase often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use XoopsMySQLDatabase, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
27 | abstract class XoopsMySQLDatabase extends XoopsDatabase |
||
28 | { |
||
29 | /** |
||
30 | * Database connection |
||
31 | * |
||
32 | * @var XoopsDatabase|mysqli |
||
33 | */ |
||
34 | public $conn; |
||
35 | |||
36 | /** |
||
37 | * connect to the database |
||
38 | * |
||
39 | * @param bool $selectdb select the database now? |
||
40 | * @return bool successful? |
||
41 | */ |
||
42 | public function connect($selectdb = true) |
||
43 | { |
||
44 | if (!extension_loaded('mysqli')) { |
||
45 | throw new \Exception('notrace:mysqli extension not loaded'); |
||
46 | |||
47 | return false; |
||
|
|||
48 | } |
||
49 | |||
50 | $this->allowWebChanges = ($_SERVER['REQUEST_METHOD'] !== 'GET'); |
||
51 | |||
52 | if ($selectdb) { |
||
53 | $dbname = constant('XOOPS_DB_NAME'); |
||
54 | } else { |
||
55 | $dbname = ''; |
||
56 | } |
||
57 | mysqli_report(MYSQLI_REPORT_OFF); |
||
58 | if (XOOPS_DB_PCONNECT == 1) { |
||
59 | $this->conn = new mysqli('p:' . XOOPS_DB_HOST, XOOPS_DB_USER, XOOPS_DB_PASS, $dbname); |
||
60 | } else { |
||
61 | $this->conn = new mysqli(XOOPS_DB_HOST, XOOPS_DB_USER, XOOPS_DB_PASS, $dbname); |
||
62 | } |
||
63 | |||
64 | // errno is 0 if connect was successful |
||
65 | if (0 !== $this->conn->connect_errno) { |
||
66 | return false; |
||
67 | } |
||
68 | |||
69 | if (defined('XOOPS_DB_CHARSET') && ('' !== XOOPS_DB_CHARSET)) { |
||
70 | // $this->queryF("SET NAMES '" . XOOPS_DB_CHARSET . "'"); |
||
71 | $this->conn->set_charset(XOOPS_DB_CHARSET); |
||
72 | } |
||
73 | $this->queryF('SET SQL_BIG_SELECTS = 1'); |
||
74 | |||
75 | return true; |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * generate an ID for a new row |
||
80 | * |
||
81 | * This is for compatibility only. Will always return 0, because MySQL supports |
||
82 | * autoincrement for primary keys. |
||
83 | * |
||
84 | * @param string $sequence name of the sequence from which to get the next ID |
||
85 | * @return int always 0, because mysql has support for autoincrement |
||
86 | */ |
||
87 | public function genId($sequence) |
||
88 | { |
||
89 | return 0; // will use auto_increment |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * Get a result row as an enumerated array |
||
94 | * |
||
95 | * @param \mysqli_result $result |
||
96 | * |
||
97 | * @return array|false false on end of data |
||
98 | */ |
||
99 | public function fetchRow($result) |
||
100 | { |
||
101 | $row = @mysqli_fetch_row($result); |
||
102 | return $row ?? false; |
||
103 | } |
||
104 | |||
105 | /** |
||
106 | * Fetch a result row as an associative array |
||
107 | * |
||
108 | * @param \mysqli_result $result |
||
109 | * |
||
110 | * @return array|false false on end of data |
||
111 | */ |
||
112 | public function fetchArray($result) |
||
113 | { |
||
114 | $row = @mysqli_fetch_assoc($result); |
||
115 | return $row ?? false; |
||
116 | |||
117 | } |
||
118 | |||
119 | /** |
||
120 | * Fetch a result row as an associative array |
||
121 | * |
||
122 | * @param \mysqli_result $result |
||
123 | * |
||
124 | * @return array|false false on end of data |
||
125 | */ |
||
126 | public function fetchBoth($result) |
||
127 | { |
||
128 | $row = @mysqli_fetch_array($result, MYSQLI_BOTH); |
||
129 | return $row ?? false; |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * XoopsMySQLDatabase::fetchObject() |
||
134 | * |
||
135 | * @param \mysqli_result $result |
||
136 | * @return stdClass|false false on end of data |
||
137 | */ |
||
138 | public function fetchObject($result) |
||
139 | { |
||
140 | $row = @mysqli_fetch_object($result); |
||
141 | return $row ?? false; |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * Get the ID generated from the previous INSERT operation |
||
146 | * |
||
147 | * @return int|string |
||
148 | */ |
||
149 | public function getInsertId() |
||
150 | { |
||
151 | return mysqli_insert_id($this->conn); |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * Get number of rows in result |
||
156 | * |
||
157 | * @param \mysqli_result $result |
||
158 | * |
||
159 | * @return int |
||
160 | */ |
||
161 | public function getRowsNum($result) |
||
162 | { |
||
163 | return (int)@mysqli_num_rows($result); |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Get number of affected rows |
||
168 | * |
||
169 | * @return int |
||
170 | */ |
||
171 | public function getAffectedRows() |
||
172 | { |
||
173 | return (int)mysqli_affected_rows($this->conn); |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * Close MySQL connection |
||
178 | * |
||
179 | * @return void |
||
180 | */ |
||
181 | public function close() |
||
182 | { |
||
183 | mysqli_close($this->conn); |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * will free all memory associated with the result identifier result. |
||
188 | * |
||
189 | * @param \mysqli_result $result result |
||
190 | * |
||
191 | * @return void |
||
192 | */ |
||
193 | public function freeRecordSet($result) |
||
194 | { |
||
195 | mysqli_free_result($result); |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * Returns the text of the error message from previous MySQL operation |
||
200 | * |
||
201 | * @return string Returns the error text from the last MySQL function, or '' (the empty string) if no error occurred. |
||
202 | */ |
||
203 | public function error() |
||
204 | { |
||
205 | return @mysqli_error($this->conn); |
||
206 | } |
||
207 | |||
208 | /** |
||
209 | * Returns the numerical value of the error message from previous MySQL operation |
||
210 | * |
||
211 | * @return int Returns the error number from the last MySQL function, or 0 (zero) if no error occurred. |
||
212 | */ |
||
213 | public function errno() |
||
214 | { |
||
215 | return @mysqli_errno($this->conn); |
||
216 | } |
||
217 | |||
218 | /** |
||
219 | * Returns escaped string text with single quotes around it to be safely stored in database |
||
220 | * |
||
221 | * @param string $str unescaped string text |
||
222 | * @return string escaped string text with single quotes around |
||
223 | * @deprecated : delegate to exec(). |
||
224 | */ |
||
225 | public function quoteString($str) |
||
226 | { |
||
227 | |||
228 | if (is_object($this->logger)) { |
||
229 | $this->logger->addDeprecated(__METHOD__ . " is deprecated since XOOPS 2.5.12, please use 'quote()' instead."); |
||
230 | } |
||
231 | |||
232 | return $this->quote($str); |
||
233 | } |
||
234 | |||
235 | /** |
||
236 | * Quotes a string for use in a query. |
||
237 | * |
||
238 | * @param string $string string to quote/escape for use in query |
||
239 | * |
||
240 | * @return string |
||
241 | */ |
||
242 | public function quote($string) |
||
246 | } |
||
247 | |||
248 | /** |
||
249 | * Escapes a string for use in a query. Does not add surrounding quotes. |
||
250 | * |
||
251 | * @param string $string string to escape |
||
252 | * |
||
253 | * @return string |
||
254 | */ |
||
255 | public function escape($string) |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * perform a query on the database |
||
262 | * |
||
263 | * @param string $sql a valid MySQL query |
||
264 | * @param int $limit number of records to return |
||
265 | * @param int $start offset of first record to return |
||
266 | * @return mysqli_result|bool query result or FALSE if successful |
||
267 | * or TRUE if successful and no result |
||
268 | */ |
||
269 | public function queryF($sql, $limit = 0, $start = 0) |
||
288 | } |
||
289 | } |
||
290 | |||
291 | /** |
||
292 | * perform a query |
||
293 | * |
||
294 | * This method is empty and does nothing! It should therefore only be |
||
295 | * used if nothing is exactly what you want done! ;-) |
||
296 | * |
||
297 | * @param string $sql a valid MySQL query |
||
298 | * @param int|null $limit number of records to return |
||
299 | * @param int|null $start offset of first record to return |
||
300 | * |
||
301 | * @return \mysqli_result|bool query result or FALSE if successful |
||
302 | * or TRUE if successful and no result |
||
303 | */ |
||
304 | public function query(string $sql, ?int $limit = null, ?int $start = null) |
||
343 | } |
||
344 | |||
345 | |||
346 | /** |
||
347 | * perform queries from SQL dump file in a batch |
||
348 | * |
||
349 | * @param string $file file path to an SQL dump file |
||
350 | * @return bool FALSE if failed reading SQL file or TRUE if the file has been read and queries executed |
||
351 | */ |
||
352 | public function queryFromFile($file) |
||
353 | { |
||
354 | if (false !== ($fp = fopen($file, 'r'))) { |
||
355 | include_once XOOPS_ROOT_PATH . '/class/database/sqlutility.php'; |
||
356 | $sql_queries = trim(fread($fp, filesize($file))); |
||
357 | SqlUtility::splitMySqlFile($pieces, $sql_queries); |
||
358 | foreach ($pieces as $query) { |
||
359 | // [0] contains the prefixed query |
||
360 | // [4] contains unprefixed table name |
||
361 | $prefixed_query = SqlUtility::prefixQuery(trim($query), $this->prefix()); |
||
362 | if ($prefixed_query != false) { |
||
363 | $this->query($prefixed_query[0]); |
||
364 | } |
||
365 | } |
||
366 | |||
367 | return true; |
||
368 | } |
||
369 | |||
370 | return false; |
||
371 | } |
||
372 | |||
373 | /** |
||
374 | * Get field name |
||
375 | * |
||
376 | * @param \mysqli_result $result query result |
||
377 | * @param int $offset numerical field index |
||
378 | * |
||
379 | * @return string |
||
380 | */ |
||
381 | public function getFieldName($result, $offset) |
||
384 | } |
||
385 | |||
386 | /** |
||
387 | * Get field type |
||
388 | * |
||
389 | * @param \mysqli_result $result query result |
||
390 | * @param int $offset numerical field index |
||
391 | * |
||
392 | * @return string |
||
393 | */ |
||
394 | public function getFieldType($result, $offset) |
||
482 | } |
||
483 | |||
484 | /** |
||
485 | * Get number of fields in result |
||
486 | * |
||
487 | * @param \mysqli_result $result query result |
||
488 | * |
||
489 | * @return int |
||
490 | */ |
||
491 | public function getFieldsNum($result) |
||
492 | { |
||
493 | return mysqli_num_fields($result); |
||
494 | } |
||
495 | |||
496 | /** |
||
497 | * getServerVersion get version of the mysql server |
||
498 | * |
||
499 | * @return string |
||
500 | */ |
||
501 | public function getServerVersion() |
||
502 | { |
||
503 | return mysqli_get_server_info($this->conn); |
||
504 | } |
||
505 | |||
506 | /** |
||
507 | * Test the passed result to determine if it is a valid result set |
||
508 | * |
||
509 | * @param mixed $result value to test |
||
510 | * |
||
511 | * @return bool true if $result is a database result set, otherwise false |
||
512 | */ |
||
513 | public function isResultSet($result) |
||
514 | { |
||
515 | return is_a($result, 'mysqli_result'); |
||
516 | } |
||
517 | |||
518 | public function exec(string $sql): bool |
||
551 | } |
||
552 | |||
553 | } |
||
554 | } |
||
555 | |||
620 |
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return
,die
orexit
statements that have been added for debug purposes.In the above example, the last
return false
will never be executed, because a return statement has already been met in every possible execution path.