PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / trunk
MainWP Dashboard: Self-hosted WordPress Management for Agencies vtrunk
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 trunk, at class/class-mainwp-db-base.php

460 lines 12.2 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_wpdb_instance()
112 *
113 * @return object wpdb.
114 */
115 public function get_wpdb_instance() {
116 return $this->wpdb;
117 }
118
119 /**
120 * Method get_my_sql_version()
121 *
122 * Get MySQL Version.
123 *
124 * @return mixed MySQL vresion.
125 */
126 public function get_my_sql_version() {
127 return $this->wpdb->get_var( 'SHOW VARIABLES LIKE "version"', 1 );
128 }
129
130 /**
131 * Method get_var_field()
132 *
133 * Execute a SQL query and return a single variable.
134 * This is a low-level wrapper for WPDB that expects SQL to be safely pre-constructed by callers.
135 * Callers must ensure all dynamic values are either validated primitives or safely escaped.
136 * See usage in get_sql_*() methods which construct safe SQL using whitelisted operations.
137 *
138 * @param string $sql Safe SQL query string. Must be pre-constructed safely by caller.
139 *
140 * @return mixed Database query result or null.
141 */
142 public function get_var_field( $sql ) {
143 if ( null === $sql ) {
144 return null;
145 }
146 // 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.
147 return $this->wpdb->get_var( $sql );
148 }
149
150 /**
151 * Method get_row_result()
152 *
153 * Execute a SQL query and return a single row result.
154 * This is a low-level wrapper for WPDB that expects SQL to be safely pre-constructed by callers.
155 * Callers must ensure all dynamic values are either validated primitives or safely escaped.
156 * See usage in get_sql_*() methods which construct safe SQL using whitelisted operations.
157 *
158 * @param mixed $sql Safe SQL query string. Must be pre-constructed safely by caller.
159 * @param int $obj Return type: OBJECT or ARRAY_A (defaults to OBJECT).
160 *
161 * @return mixed Single row result or null.
162 */
163 public function get_row_result( $sql, $obj = OBJECT ) {
164 if ( null === $sql ) {
165 return null;
166 }
167
168 if ( ! in_array( $obj, array( OBJECT, ARRAY_A ) ) ) {
169 $obj = OBJECT;
170 }
171
172 // 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.
173 return $this->wpdb->get_row( $sql, $obj );
174 }
175
176 /**
177 * Method get_results_result()
178 *
179 * Execute a SQL query and return multiple results indexed by primary key.
180 * This is a low-level wrapper for WPDB that expects SQL to be safely pre-constructed by callers.
181 * Callers must ensure all dynamic values are either validated primitives or safely escaped.
182 * See usage in get_sql_*() methods which construct safe SQL using whitelisted operations.
183 *
184 * @param mixed $sql Safe SQL query string. Must be pre-constructed safely by caller.
185 *
186 * @return mixed Array of results indexed by primary key, or null.
187 */
188 public function get_results_result( $sql ) {
189 if ( null === $sql ) {
190 return null;
191 }
192
193 // 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.
194 return $this->wpdb->get_results( $sql, OBJECT_K );
195 }
196
197 /**
198 * Method query()
199 *
200 * SQL Query.
201 *
202 * @param mixed $sql SQL Query.
203 *
204 * @return mixed false|$result.
205 */
206 public function query( $sql ) {
207 if ( null === $sql ) {
208 return false;
209 }
210
211 $result = static::m_query( $sql, $this->wpdb->dbh ); // NOSONAR - required.
212
213 if ( ! $result || ( empty( self::num_rows( $result ) ) ) ) { // NOSONAR - required.
214 return false;
215 }
216
217 return $result;
218 }
219
220
221 /**
222 * Method get_last_query()
223 *
224 * @return string Get last query.
225 */
226 public function get_last_query() {
227 return $this->wpdb->last_query;
228 }
229
230
231 /**
232 * Method escape_array()
233 *
234 * Escape SQL Data.
235 *
236 * @param mixed $data_arr Data array to escape.
237 *
238 * @return mixed Escapped SQL Data.
239 */
240 public function escape_array( $data_arr ) {
241 if ( ! is_array( $data_arr ) || empty( $data_arr ) ) {
242 return false;
243 }
244 $tmp_arr = array();
245 foreach ( $data_arr as $dt ) {
246 $tmp_arr[] = $this->escape( $dt );
247 }
248 return $tmp_arr;
249 }
250
251 /**
252 * Method escape()
253 *
254 * Escape SQL Data.
255 *
256 * @param mixed $data Data to escape.
257 *
258 * @return mixed Escapped SQL Data.
259 */
260 public function escape( $data ) {
261 if ( function_exists( 'esc_sql' ) ) {
262 return esc_sql( $data );
263 } else {
264 return $this->wpdb->escape( $data );
265 }
266 }
267
268 /**
269 * Method use_mysqli()
270 *
271 * Use MySQLi, Support old & new versions of WordPress (3.9+).
272 *
273 * @return boolean|self false|$instance Instance of \mysqli
274 */
275 public static function use_mysqli() {
276 if ( ! function_exists( '\mysqli_connect' ) ) {
277 return false;
278 }
279 return self::$instance->wpdb->dbh instanceof \mysqli; // NOSONAR - required.
280 }
281
282 /**
283 * Method ping()
284 *
285 * Ping MySQLi.
286 *
287 * @param mixed $link Query link.
288 *
289 * @return mixed \mysqli_ping
290 */
291 public static function ping( $link ) {
292 if ( self::use_mysqli() ) { // NOSONAR - required.
293 if ( version_compare( phpversion(), '8.4', '<' ) ) {
294 return \mysqli_ping( $link );
295 } else {
296 try {
297 self::$instance->wpdb->query( 'DO 1' );
298 return true;
299 } catch ( \mysqli_sql_exception $e ) { // NOSONAR - ok.
300 // error.
301 return false;
302 }
303 }
304 } else {
305 return \mysql_ping( $link );
306 }
307 }
308
309 /**
310 * Method m_query()
311 *
312 * MySQLi m_query.
313 *
314 * @param mixed $query Query params.
315 * @param mixed $link Query link.
316 *
317 * @return mixed \mysqli_query
318 */
319 public static function m_query( $query, $link ) {
320 if ( self::use_mysqli() ) { // NOSONAR - required.
321 return \mysqli_query( $link, $query );
322 } else {
323 return \mysql_query( $query, $link );
324 }
325 }
326
327 /**
328 * Method fetch_object()
329 *
330 * Fetch object.
331 *
332 * @param mixed $result Query result.
333 *
334 * @return boolean|mixed false|\mysqli_fetch_object
335 */
336 public static function fetch_object( $result ) {
337 if ( is_bool( $result ) ) {
338 return $result;
339 }
340
341 if ( self::use_mysqli() ) { // NOSONAR - required.
342 return \mysqli_fetch_object( $result );
343 } else {
344 return \mysql_fetch_object( $result );
345 }
346 }
347
348 /**
349 * Method free_result()
350 *
351 * MySQLi free result.
352 *
353 * @param mixed $result Query result.
354 *
355 * @return boolean|mixed false|\mysqli_free_result
356 */
357 public static function free_result( $result ) {
358 if ( is_bool( $result ) ) {
359 return $result;
360 }
361
362 if ( self::use_mysqli() ) { // NOSONAR - required.
363 \mysqli_free_result( $result );
364 } else {
365 \mysql_free_result( $result );
366 }
367 }
368
369 /**
370 * Method data_seek()
371 *
372 * MySQLi data seek.
373 *
374 * @param mixed $result Query result.
375 * @param mixed $offset Query offset.
376 *
377 * @return boolean|mixed false|\mysqli_data_seek
378 */
379 public static function data_seek( $result, $offset ) {
380 if ( is_bool( $result ) ) {
381 return $result;
382 }
383
384 if ( self::use_mysqli() ) { // NOSONAR - required.
385 if ( ! ( $result instanceof \mysqli_result ) ) {
386 return $result;
387 }
388 return \mysqli_data_seek( $result, $offset );
389 } else {
390 return \mysql_data_seek( $result, $offset );
391 }
392 }
393
394 /**
395 * Method fetch_array()
396 *
397 * MySQLi fetch array.
398 *
399 * @param mixed $result Query result.
400 * @param null $result_type Query result type.
401 *
402 * @return boolean|mixed false|\mysqli_fetch_array.
403 */
404 public static function fetch_array( $result, $result_type = null ) {
405 if ( is_bool( $result ) ) {
406 return $result;
407 }
408
409 if ( self::use_mysqli() ) { // NOSONAR - required.
410 return \mysqli_fetch_array( $result, ( null === $result_type ? MYSQLI_BOTH : $result_type ) );
411 } else {
412 return \mysql_fetch_array( $result, ( null === $result_type ? MYSQL_BOTH : $result_type ) );
413 }
414 }
415
416
417 /**
418 * Method num_rows()
419 *
420 * MySQLi number of rows.
421 *
422 * @param mixed $result Query result.
423 *
424 * @return boolean|mixed false|\mysqli_num_rows.
425 */
426 public static function num_rows( $result ) {
427 if ( ! self::is_result( $result ) ) { // NOSONAR - required.
428 return false;
429 }
430
431 if ( self::use_mysqli() ) { // NOSONAR - required.
432 return \mysqli_num_rows( $result );
433 } else {
434 return \mysql_num_rows( $result );
435 }
436 }
437
438 /**
439 * Method is_result()
440 *
441 * Return instance of \mysqli_result
442 *
443 * @param mixed $result Query result.
444 *
445 * @return boolean|mixed false|\mysqli_result
446 */
447 public static function is_result( $result ) {
448 if ( is_bool( $result ) ) {
449 return $result;
450 }
451
452 if ( self::use_mysqli() ) { // NOSONAR - required.
453 return $result instanceof \mysqli_result;
454 } else {
455 return is_resource( $result );
456 }
457 }
458 // phpcs:enable
459 }
460