PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.2
6.2.2 6.2.1 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 All 155 releases
← All changes | class/class-mainwp-db-base.php +404 -316 5.0 → 6.2.2 View file →
@@ -8,364 +8,452 @@
8 8 */
9 9
10 10 namespace MainWP\Dashboard;
11 11
12 +// Exit if accessed directly.
13 +if ( ! defined( 'ABSPATH' ) ) {
14 + exit;
15 +}
16 +
12 17 /**
13 18 * Class MainWP_DB_Base
14 19 *
15 20 * @package MainWP\Dashboard
16 21 */
17 -class MainWP_DB_Base {
22 +class MainWP_DB_Base { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
18 23
19 - // phpcs:disable WordPress.DB.RestrictedFunctions, WordPress.DB.PreparedSQL.NotPrepared -- unprepared SQL ok, accessing the database directly to custom database functions.
24 + // phpcs:disable WordPress.DB.RestrictedFunctions, WordPress.DB.PreparedSQL.NotPrepared -- unprepared SQL ok, accessing the database directly to custom database functions.
20 25
21 - /**
22 - * Private static instance.
23 - *
24 - * @static
25 - * @var $instance MainWP_DB_Base.
26 - */
27 - private static $instance = null;
26 + /**
27 + * Private static instance.
28 + *
29 + * @static
30 + * @var $instance MainWP_DB_Base.
31 + */
32 + private static $instance = null;
28 33
29 - /**
30 - * Table prefix.
31 - *
32 - * @var string $table_prefix
33 - */
34 - protected $table_prefix;
34 + /**
35 + * Table prefix.
36 + *
37 + * @var string $table_prefix
38 + */
39 + protected $table_prefix;
35 40
36 - /**
37 - * WordPress Database.
38 - *
39 - * @var mixed $wpdb WordPress Database.
40 - */
41 - protected $wpdb;
41 + /**
42 + * WordPress Database.
43 + *
44 + * @var mixed $wpdb WordPress Database.
45 + */
46 + protected $wpdb;
42 47
43 - /**
44 - * MainWP_DB_Base constructor.
45 - *
46 - * Run each time the class is called.
47 - */
48 - public function __construct() {
48 + /**
49 + * MainWP_DB_Base constructor.
50 + *
51 + * Run each time the class is called.
52 + */
53 + public function __construct() {
49 54
50 - self::$instance = $this;
55 + self::$instance = $this;
51 56
52 - /**
53 - * WordPress Database.
54 - *
55 - * @var mixed $wpdb Global WordPress Database.
56 - */
57 - global $wpdb;
57 + /**
58 + * WordPress Database.
59 + *
60 + * @var mixed $wpdb Global WordPress Database.
61 + */
62 + global $wpdb;
58 63
59 - $this->wpdb = &$wpdb;
60 - $this->table_prefix = $wpdb->prefix . 'mainwp_';
61 - }
64 + $this->wpdb = &$wpdb;
65 + $this->table_prefix = $wpdb->prefix . 'mainwp_';
66 + }
62 67
63 - /**
64 - * Method test_connection()
65 - *
66 - * Test db connection.
67 - *
68 - * @uses \MainWP\Dashboard\MainWP_Logger::info()
69 - */
70 - protected function test_connection() {
71 - if ( ! self::ping( $this->wpdb->dbh ) ) {
72 - MainWP_Logger::instance()->info( esc_html__( 'Trying to reconnect WordPress database connection...', 'mainwp' ) );
73 - $this->wpdb->db_connect();
74 - }
75 - }
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 + }
76 81
77 - /**
78 - * Method table_name()
79 - *
80 - * Create entire table name.
81 - *
82 - * @param mixed $suffix Table suffix.
83 - * @param null $tablePrefix Table prefix.
84 - *
85 - * @return string Table name.
86 - */
87 - protected function table_name( $suffix, $tablePrefix = null ) {
88 - return ( null === $tablePrefix ? $this->table_prefix : $tablePrefix ) . $suffix;
89 - }
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 + }
90 95
91 96
92 - /**
93 - * Method get_table_name()
94 - *
95 - * Create entire table name.
96 - *
97 - * @param mixed $suffix Table suffix.
98 - *
99 - * @return string Table name.
100 - */
101 - public function get_table_name( $suffix ) {
102 - return $this->table_name( $suffix );
103 - }
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 + }
104 109
105 - /**
106 - * Method get_my_sql_version()
107 - *
108 - * Get MySQL Version.
109 - *
110 - * @return mixed MySQL vresion.
111 - */
112 - public function get_my_sql_version() {
113 - return $this->wpdb->get_var( 'SHOW VARIABLES LIKE "version"', 1 );
114 - }
110 + /**
111 + * Method get_wpdb_instance()
112 + *
113 + * @return object wpdb.
114 + */
115 + public function get_wpdb_instance() {
116 + return $this->wpdb;
117 + }
115 118
116 - /**
117 - * Method get_row_result()
118 - *
119 - * Get row result.
120 - *
121 - * @param mixed $sql SQL Query.
122 - *
123 - * @return mixed null|Row
124 - */
125 - public function get_row_result( $sql ) {
126 - if ( null === $sql ) {
127 - return null;
128 - }
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 129
130 - return $this->wpdb->get_row( $sql, OBJECT );
131 - }
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 + }
132 149
133 - /**
134 - * Method get_results_result()
135 - *
136 - * Get Results of result.
137 - *
138 - * @param mixed $sql SQL query.
139 - *
140 - * @return mixed null|get_results()
141 - */
142 - public function get_results_result( $sql ) {
143 - if ( null === $sql ) {
144 - return null;
145 - }
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 + }
146 167
147 - return $this->wpdb->get_results( $sql, OBJECT_K );
148 - }
168 + if ( ! in_array( $obj, array( OBJECT, ARRAY_A ) ) ) {
169 + $obj = OBJECT;
170 + }
149 171
150 - /**
151 - * Method query()
152 - *
153 - * SQL Query.
154 - *
155 - * @param mixed $sql SQL Query.
156 - *
157 - * @return mixed false|$result.
158 - */
159 - public function query( $sql ) {
160 - if ( null === $sql ) {
161 - return false;
162 - }
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 + }
163 175
164 - $result = self::m_query( $sql, $this->wpdb->dbh );
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 + }
165 192
166 - if ( ! $result || ( empty( self::num_rows( $result ) ) ) ) {
167 - return false;
168 - }
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 + }
169 196
170 - return $result;
171 - }
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 + }
172 210
173 - /**
174 - * Method escape()
175 - *
176 - * Escape SQL Data.
177 - *
178 - * @param mixed $data Data to escape.
179 - *
180 - * @return mixed Escapped SQL Data.
181 - */
182 - public function escape( $data ) {
183 - if ( function_exists( 'esc_sql' ) ) {
184 - return esc_sql( $data );
185 - } else {
186 - return $this->wpdb->escape( $data );
187 - }
188 - }
211 + $result = static::m_query( $sql, $this->wpdb->dbh ); // NOSONAR - required.
189 212
190 - /**
191 - * Method use_mysqli()
192 - *
193 - * Use MySQLi, Support old & new versions of WordPress (3.9+).
194 - *
195 - * @return boolean|self false|$instance Instance of \mysqli
196 - */
197 - public static function use_mysqli() {
198 - if ( ! function_exists( '\mysqli_connect' ) ) {
199 - return false;
200 - }
201 - return ( self::$instance->wpdb->dbh instanceof \mysqli );
202 - }
213 + if ( ! $result || ( empty( self::num_rows( $result ) ) ) ) { // NOSONAR - required.
214 + return false;
215 + }
203 216
204 - /**
205 - * Method ping()
206 - *
207 - * Ping MySQLi.
208 - *
209 - * @param mixed $link Query link.
210 - *
211 - * @return mixed \mysqli_ping
212 - */
213 - public static function ping( $link ) {
214 - if ( self::use_mysqli() ) {
215 - return \mysqli_ping( $link );
216 - } else {
217 - return \mysql_ping( $link );
218 - }
219 - }
217 + return $result;
218 + }
220 219
221 - /**
222 - * Method m_query()
223 - *
224 - * MySQLi m_query.
225 - *
226 - * @param mixed $query Query params.
227 - * @param mixed $link Query link.
228 - *
229 - * @return mixed \mysqli_query
230 - */
231 - public static function m_query( $query, $link ) {
232 - if ( self::use_mysqli() ) {
233 - return \mysqli_query( $link, $query );
234 - } else {
235 - return \mysql_query( $query, $link );
236 - }
237 - }
238 220
239 - /**
240 - * Method fetch_object()
241 - *
242 - * Fetch object.
243 - *
244 - * @param mixed $result Query result.
245 - *
246 - * @return boolean|mixed false|\mysqli_fetch_object
247 - */
248 - public static function fetch_object( $result ) {
249 - if ( is_bool( $result ) ) {
250 - return $result;
251 - }
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 + }
252 229
253 - if ( self::use_mysqli() ) {
254 - return \mysqli_fetch_object( $result );
255 - } else {
256 - return \mysql_fetch_object( $result );
257 - }
258 - }
259 230
260 - /**
261 - * Method free_result()
262 - *
263 - * MySQLi free result.
264 - *
265 - * @param mixed $result Query result.
266 - *
267 - * @return boolean|mixed false|\mysqli_free_result
268 - */
269 - public static function free_result( $result ) {
270 - if ( is_bool( $result ) ) {
271 - return $result;
272 - }
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 + }
273 250
274 - if ( self::use_mysqli() ) {
275 - return \mysqli_free_result( $result );
276 - } else {
277 - return \mysql_free_result( $result );
278 - }
279 - }
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 + }
280 267
281 - /**
282 - * Method data_seek()
283 - *
284 - * MySQLi data seek.
285 - *
286 - * @param mixed $result Query result.
287 - * @param mixed $offset Query offset.
288 - *
289 - * @return boolean|mixed false|\mysqli_data_seek
290 - */
291 - public static function data_seek( $result, $offset ) {
292 - if ( is_bool( $result ) ) {
293 - return $result;
294 - }
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 + }
295 281
296 - if ( self::use_mysqli() ) {
297 - if ( ! ( $result instanceof \mysqli_result ) ) {
298 - return $result;
299 - }
300 - return \mysqli_data_seek( $result, $offset );
301 - } else {
302 - return \mysql_data_seek( $result, $offset );
303 - }
304 - }
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 + }
305 308
306 - /**
307 - * Method fetch_array()
308 - *
309 - * MySQLi fetch array.
310 - *
311 - * @param mixed $result Query result.
312 - * @param null $result_type Query result type.
313 - *
314 - * @return boolean|mixed false|\mysqli_fetch_array.
315 - */
316 - public static function fetch_array( $result, $result_type = null ) {
317 - if ( is_bool( $result ) ) {
318 - return $result;
319 - }
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 + }
320 326
321 - if ( self::use_mysqli() ) {
322 - return \mysqli_fetch_array( $result, ( null === $result_type ? MYSQLI_BOTH : $result_type ) );
323 - } else {
324 - return \mysql_fetch_array( $result, ( null === $result_type ? MYSQL_BOTH : $result_type ) );
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 + }
327 340
341 + if ( self::use_mysqli() ) { // NOSONAR - required.
342 + return \mysqli_fetch_object( $result );
343 + } else {
344 + return \mysql_fetch_object( $result );
345 + }
346 + }
328 347
329 - /**
330 - * Method num_rows()
331 - *
332 - * MySQLi number of rows.
333 - *
334 - * @param mixed $result Query result.
335 - *
336 - * @return boolean|mixed false|\mysqli_num_rows.
337 - */
338 - public static function num_rows( $result ) {
339 - if ( ! self::is_result( $result ) ) {
340 - return false;
341 - }
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 + }
342 361
343 - if ( self::use_mysqli() ) {
344 - return \mysqli_num_rows( $result );
345 - } else {
346 - return \mysql_num_rows( $result );
347 - }
348 - }
362 + if ( self::use_mysqli() ) { // NOSONAR - required.
363 + \mysqli_free_result( $result );
364 + } else {
365 + \mysql_free_result( $result );
366 + }
367 + }
349 368
350 - /**
351 - * Method is_result()
352 - *
353 - * Return instance of \mysqli_result
354 - *
355 - * @param mixed $result Query result.
356 - *
357 - * @return boolean|mixed false|\mysqli_result
358 - */
359 - public static function is_result( $result ) {
360 - if ( is_bool( $result ) ) {
361 - return $result;
362 - }
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 + }
363 383
364 - if ( self::use_mysqli() ) {
365 - return ( $result instanceof \mysqli_result );
366 - } else {
367 - return is_resource( $result );
368 - }
369 - }
370 - // phpcs:enable
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
371 459 }