PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.1.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.1.2
6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 5.2.2 5.3 All 153 releases
mainwp / class / class-mainwp-db-base.php

class-mainwp-db-base.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.1.2, at class/class-mainwp-db-base.php

451 lines 12.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Database Controller
4 *
5 * This file handles all interactions with the DB.
6 *
7 * @package MainWP/Dashboard
8 */
9
10 namespace MainWP\Dashboard;
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Class MainWP_DB_Base
19 *
20 * @package MainWP\Dashboard
21 */
22 class MainWP_DB_Base { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
23
24 // phpcs:disable WordPress.DB.RestrictedFunctions, WordPress.DB.PreparedSQL.NotPrepared -- unprepared SQL ok, accessing the database directly to custom database functions.
25
26 /**
27 * Private static instance.
28 *
29 * @static
30 * @var $instance MainWP_DB_Base.
31 */
32 private static $instance = null;
33
34 /**
35 * Table prefix.
36 *
37 * @var string $table_prefix
38 */
39 protected $table_prefix;
40
41 /**
42 * WordPress Database.
43 *
44 * @var mixed $wpdb WordPress Database.
45 */
46 protected $wpdb;
47
48 /**
49 * MainWP_DB_Base constructor.
50 *
51 * Run each time the class is called.
52 */
53 public function __construct() {
54
55 self::$instance = $this;
56
57 /**
58 * WordPress Database.
59 *
60 * @var mixed $wpdb Global WordPress Database.
61 */
62 global $wpdb;
63
64 $this->wpdb = &$wpdb;
65 $this->table_prefix = $wpdb->prefix . 'mainwp_';
66 }
67
68 /**
69 * Method test_connection()
70 *
71 * Test db connection.
72 *
73 * @uses \MainWP\Dashboard\MainWP_Logger::info()
74 */
75 protected function test_connection() {
76 if ( ! static::ping( $this->wpdb->dbh ) ) {
77 MainWP_Logger::instance()->info( esc_html__( 'Trying to reconnect WordPress database connection...', 'mainwp' ) );
78 $this->wpdb->db_connect();
79 }
80 }
81
82 /**
83 * Method table_name()
84 *
85 * Create entire table name.
86 *
87 * @param mixed $suffix Table suffix.
88 * @param null $tablePrefix Table prefix.
89 *
90 * @return string Table name.
91 */
92 protected function table_name( $suffix, $tablePrefix = null ) {
93 return ( null === $tablePrefix ? $this->table_prefix : $tablePrefix ) . $suffix;
94 }
95
96
97 /**
98 * Method get_table_name()
99 *
100 * Create entire table name.
101 *
102 * @param mixed $suffix Table suffix.
103 *
104 * @return string Table name.
105 */
106 public function get_table_name( $suffix ) {
107 return $this->table_name( $suffix );
108 }
109
110 /**
111 * Method get_my_sql_version()
112 *
113 * Get MySQL Version.
114 *
115 * @return mixed MySQL vresion.
116 */
117 public function get_my_sql_version() {
118 return $this->wpdb->get_var( 'SHOW VARIABLES LIKE "version"', 1 );
119 }
120
121 /**
122 * Method get_var_field()
123 *
124 * Execute a SQL query and return a single variable.
125 * This is a low-level wrapper for WPDB that expects SQL to be safely pre-constructed by callers.
126 * Callers must ensure all dynamic values are either validated primitives or safely escaped.
127 * See usage in get_sql_*() methods which construct safe SQL using whitelisted operations.
128 *
129 * @param string $sql Safe SQL query string. Must be pre-constructed safely by caller.
130 *
131 * @return mixed Database query result or null.
132 */
133 public function get_var_field( $sql ) {
134 if ( null === $sql ) {
135 return null;
136 }
137 // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $sql is safe by contract; callers construct via get_sql_*() methods with validated/escaped values. All call sites verified in mainwp-db.php.
138 return $this->wpdb->get_var( $sql );
139 }
140
141 /**
142 * Method get_row_result()
143 *
144 * Execute a SQL query and return a single row result.
145 * This is a low-level wrapper for WPDB that expects SQL to be safely pre-constructed by callers.
146 * Callers must ensure all dynamic values are either validated primitives or safely escaped.
147 * See usage in get_sql_*() methods which construct safe SQL using whitelisted operations.
148 *
149 * @param mixed $sql Safe SQL query string. Must be pre-constructed safely by caller.
150 * @param int $obj Return type: OBJECT or ARRAY_A (defaults to OBJECT).
151 *
152 * @return mixed Single row result or null.
153 */
154 public function get_row_result( $sql, $obj = OBJECT ) {
155 if ( null === $sql ) {
156 return null;
157 }
158
159 if ( ! in_array( $obj, array( OBJECT, ARRAY_A ) ) ) {
160 $obj = OBJECT;
161 }
162
163 // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $sql is safe by contract; callers construct via get_sql_*() methods with validated/escaped values. All call sites verified in mainwp-db.php.
164 return $this->wpdb->get_row( $sql, $obj );
165 }
166
167 /**
168 * Method get_results_result()
169 *
170 * Execute a SQL query and return multiple results indexed by primary key.
171 * This is a low-level wrapper for WPDB that expects SQL to be safely pre-constructed by callers.
172 * Callers must ensure all dynamic values are either validated primitives or safely escaped.
173 * See usage in get_sql_*() methods which construct safe SQL using whitelisted operations.
174 *
175 * @param mixed $sql Safe SQL query string. Must be pre-constructed safely by caller.
176 *
177 * @return mixed Array of results indexed by primary key, or null.
178 */
179 public function get_results_result( $sql ) {
180 if ( null === $sql ) {
181 return null;
182 }
183
184 // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- $sql is safe by contract; callers construct via get_sql_*() methods with validated/escaped values. All call sites verified in mainwp-db.php.
185 return $this->wpdb->get_results( $sql, OBJECT_K );
186 }
187
188 /**
189 * Method query()
190 *
191 * SQL Query.
192 *
193 * @param mixed $sql SQL Query.
194 *
195 * @return mixed false|$result.
196 */
197 public function query( $sql ) {
198 if ( null === $sql ) {
199 return false;
200 }
201
202 $result = static::m_query( $sql, $this->wpdb->dbh ); // NOSONAR - required.
203
204 if ( ! $result || ( empty( self::num_rows( $result ) ) ) ) { // NOSONAR - required.
205 return false;
206 }
207
208 return $result;
209 }
210
211
212 /**
213 * Method get_last_query()
214 *
215 * @return string Get last query.
216 */
217 public function get_last_query() {
218 return $this->wpdb->last_query;
219 }
220
221
222 /**
223 * Method escape_array()
224 *
225 * Escape SQL Data.
226 *
227 * @param mixed $data_arr Data array to escape.
228 *
229 * @return mixed Escapped SQL Data.
230 */
231 public function escape_array( $data_arr ) {
232 if ( ! is_array( $data_arr ) || empty( $data_arr ) ) {
233 return false;
234 }
235 $tmp_arr = array();
236 foreach ( $data_arr as $dt ) {
237 $tmp_arr[] = $this->escape( $dt );
238 }
239 return $tmp_arr;
240 }
241
242 /**
243 * Method escape()
244 *
245 * Escape SQL Data.
246 *
247 * @param mixed $data Data to escape.
248 *
249 * @return mixed Escapped SQL Data.
250 */
251 public function escape( $data ) {
252 if ( function_exists( 'esc_sql' ) ) {
253 return esc_sql( $data );
254 } else {
255 return $this->wpdb->escape( $data );
256 }
257 }
258
259 /**
260 * Method use_mysqli()
261 *
262 * Use MySQLi, Support old & new versions of WordPress (3.9+).
263 *
264 * @return boolean|self false|$instance Instance of \mysqli
265 */
266 public static function use_mysqli() {
267 if ( ! function_exists( '\mysqli_connect' ) ) {
268 return false;
269 }
270 return self::$instance->wpdb->dbh instanceof \mysqli; // NOSONAR - required.
271 }
272
273 /**
274 * Method ping()
275 *
276 * Ping MySQLi.
277 *
278 * @param mixed $link Query link.
279 *
280 * @return mixed \mysqli_ping
281 */
282 public static function ping( $link ) {
283 if ( self::use_mysqli() ) { // NOSONAR - required.
284 if ( version_compare( phpversion(), '8.4', '<' ) ) {
285 return \mysqli_ping( $link );
286 } else {
287 try {
288 self::$instance->wpdb->query( 'DO 1' );
289 return true;
290 } catch ( \mysqli_sql_exception $e ) { // NOSONAR - ok.
291 // error.
292 return false;
293 }
294 }
295 } else {
296 return \mysql_ping( $link );
297 }
298 }
299
300 /**
301 * Method m_query()
302 *
303 * MySQLi m_query.
304 *
305 * @param mixed $query Query params.
306 * @param mixed $link Query link.
307 *
308 * @return mixed \mysqli_query
309 */
310 public static function m_query( $query, $link ) {
311 if ( self::use_mysqli() ) { // NOSONAR - required.
312 return \mysqli_query( $link, $query );
313 } else {
314 return \mysql_query( $query, $link );
315 }
316 }
317
318 /**
319 * Method fetch_object()
320 *
321 * Fetch object.
322 *
323 * @param mixed $result Query result.
324 *
325 * @return boolean|mixed false|\mysqli_fetch_object
326 */
327 public static function fetch_object( $result ) {
328 if ( is_bool( $result ) ) {
329 return $result;
330 }
331
332 if ( self::use_mysqli() ) { // NOSONAR - required.
333 return \mysqli_fetch_object( $result );
334 } else {
335 return \mysql_fetch_object( $result );
336 }
337 }
338
339 /**
340 * Method free_result()
341 *
342 * MySQLi free result.
343 *
344 * @param mixed $result Query result.
345 *
346 * @return boolean|mixed false|\mysqli_free_result
347 */
348 public static function free_result( $result ) {
349 if ( is_bool( $result ) ) {
350 return $result;
351 }
352
353 if ( self::use_mysqli() ) { // NOSONAR - required.
354 \mysqli_free_result( $result );
355 } else {
356 \mysql_free_result( $result );
357 }
358 }
359
360 /**
361 * Method data_seek()
362 *
363 * MySQLi data seek.
364 *
365 * @param mixed $result Query result.
366 * @param mixed $offset Query offset.
367 *
368 * @return boolean|mixed false|\mysqli_data_seek
369 */
370 public static function data_seek( $result, $offset ) {
371 if ( is_bool( $result ) ) {
372 return $result;
373 }
374
375 if ( self::use_mysqli() ) { // NOSONAR - required.
376 if ( ! ( $result instanceof \mysqli_result ) ) {
377 return $result;
378 }
379 return \mysqli_data_seek( $result, $offset );
380 } else {
381 return \mysql_data_seek( $result, $offset );
382 }
383 }
384
385 /**
386 * Method fetch_array()
387 *
388 * MySQLi fetch array.
389 *
390 * @param mixed $result Query result.
391 * @param null $result_type Query result type.
392 *
393 * @return boolean|mixed false|\mysqli_fetch_array.
394 */
395 public static function fetch_array( $result, $result_type = null ) {
396 if ( is_bool( $result ) ) {
397 return $result;
398 }
399
400 if ( self::use_mysqli() ) { // NOSONAR - required.
401 return \mysqli_fetch_array( $result, ( null === $result_type ? MYSQLI_BOTH : $result_type ) );
402 } else {
403 return \mysql_fetch_array( $result, ( null === $result_type ? MYSQL_BOTH : $result_type ) );
404 }
405 }
406
407
408 /**
409 * Method num_rows()
410 *
411 * MySQLi number of rows.
412 *
413 * @param mixed $result Query result.
414 *
415 * @return boolean|mixed false|\mysqli_num_rows.
416 */
417 public static function num_rows( $result ) {
418 if ( ! self::is_result( $result ) ) { // NOSONAR - required.
419 return false;
420 }
421
422 if ( self::use_mysqli() ) { // NOSONAR - required.
423 return \mysqli_num_rows( $result );
424 } else {
425 return \mysql_num_rows( $result );
426 }
427 }
428
429 /**
430 * Method is_result()
431 *
432 * Return instance of \mysqli_result
433 *
434 * @param mixed $result Query result.
435 *
436 * @return boolean|mixed false|\mysqli_result
437 */
438 public static function is_result( $result ) {
439 if ( is_bool( $result ) ) {
440 return $result;
441 }
442
443 if ( self::use_mysqli() ) { // NOSONAR - required.
444 return $result instanceof \mysqli_result;
445 } else {
446 return is_resource( $result );
447 }
448 }
449 // phpcs:enable
450 }
451