38217-vm/wp-content/plugins/mainwp/class/class-mainwp-db-base.php
2026-02-05 17:08:59 +03:00

446 lines
12 KiB
PHP

<?php
/**
* MainWP Database Controller
*
* This file handles all interactions with the DB.
*
* @package MainWP/Dashboard
*/
namespace MainWP\Dashboard;
/**
* Class MainWP_DB_Base
*
* @package MainWP\Dashboard
*/
class MainWP_DB_Base { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
// phpcs:disable WordPress.DB.RestrictedFunctions, WordPress.DB.PreparedSQL.NotPrepared -- unprepared SQL ok, accessing the database directly to custom database functions.
/**
* Private static instance.
*
* @static
* @var $instance MainWP_DB_Base.
*/
private static $instance = null;
/**
* Table prefix.
*
* @var string $table_prefix
*/
protected $table_prefix;
/**
* WordPress Database.
*
* @var mixed $wpdb WordPress Database.
*/
protected $wpdb;
/**
* MainWP_DB_Base constructor.
*
* Run each time the class is called.
*/
public function __construct() {
self::$instance = $this;
/**
* WordPress Database.
*
* @var mixed $wpdb Global WordPress Database.
*/
global $wpdb;
$this->wpdb = &$wpdb;
$this->table_prefix = $wpdb->prefix . 'mainwp_';
}
/**
* Method test_connection()
*
* Test db connection.
*
* @uses \MainWP\Dashboard\MainWP_Logger::info()
*/
protected function test_connection() {
if ( ! static::ping( $this->wpdb->dbh ) ) {
MainWP_Logger::instance()->info( esc_html__( 'Trying to reconnect WordPress database connection...', 'mainwp' ) );
$this->wpdb->db_connect();
}
}
/**
* Method table_name()
*
* Create entire table name.
*
* @param mixed $suffix Table suffix.
* @param null $tablePrefix Table prefix.
*
* @return string Table name.
*/
protected function table_name( $suffix, $tablePrefix = null ) {
return ( null === $tablePrefix ? $this->table_prefix : $tablePrefix ) . $suffix;
}
/**
* Method get_table_name()
*
* Create entire table name.
*
* @param mixed $suffix Table suffix.
*
* @return string Table name.
*/
public function get_table_name( $suffix ) {
return $this->table_name( $suffix );
}
/**
* Method get_my_sql_version()
*
* Get MySQL Version.
*
* @return mixed MySQL vresion.
*/
public function get_my_sql_version() {
return $this->wpdb->get_var( 'SHOW VARIABLES LIKE "version"', 1 );
}
/**
* Method get_var_field()
*
* Execute a SQL query and return a single variable.
* This is a low-level wrapper for WPDB that expects SQL to be safely pre-constructed by callers.
* Callers must ensure all dynamic values are either validated primitives or safely escaped.
* See usage in get_sql_*() methods which construct safe SQL using whitelisted operations.
*
* @param string $sql Safe SQL query string. Must be pre-constructed safely by caller.
*
* @return mixed Database query result or null.
*/
public function get_var_field( $sql ) {
if ( null === $sql ) {
return null;
}
// 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.
return $this->wpdb->get_var( $sql );
}
/**
* Method get_row_result()
*
* Execute a SQL query and return a single row result.
* This is a low-level wrapper for WPDB that expects SQL to be safely pre-constructed by callers.
* Callers must ensure all dynamic values are either validated primitives or safely escaped.
* See usage in get_sql_*() methods which construct safe SQL using whitelisted operations.
*
* @param mixed $sql Safe SQL query string. Must be pre-constructed safely by caller.
* @param int $obj Return type: OBJECT or ARRAY_A (defaults to OBJECT).
*
* @return mixed Single row result or null.
*/
public function get_row_result( $sql, $obj = OBJECT ) {
if ( null === $sql ) {
return null;
}
if ( ! in_array( $obj, array( OBJECT, ARRAY_A ) ) ) {
$obj = OBJECT;
}
// 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.
return $this->wpdb->get_row( $sql, $obj );
}
/**
* Method get_results_result()
*
* Execute a SQL query and return multiple results indexed by primary key.
* This is a low-level wrapper for WPDB that expects SQL to be safely pre-constructed by callers.
* Callers must ensure all dynamic values are either validated primitives or safely escaped.
* See usage in get_sql_*() methods which construct safe SQL using whitelisted operations.
*
* @param mixed $sql Safe SQL query string. Must be pre-constructed safely by caller.
*
* @return mixed Array of results indexed by primary key, or null.
*/
public function get_results_result( $sql ) {
if ( null === $sql ) {
return null;
}
// 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.
return $this->wpdb->get_results( $sql, OBJECT_K );
}
/**
* Method query()
*
* SQL Query.
*
* @param mixed $sql SQL Query.
*
* @return mixed false|$result.
*/
public function query( $sql ) {
if ( null === $sql ) {
return false;
}
$result = static::m_query( $sql, $this->wpdb->dbh ); // NOSONAR - required.
if ( ! $result || ( empty( self::num_rows( $result ) ) ) ) { // NOSONAR - required.
return false;
}
return $result;
}
/**
* Method get_last_query()
*
* @return string Get last query.
*/
public function get_last_query() {
return $this->wpdb->last_query;
}
/**
* Method escape_array()
*
* Escape SQL Data.
*
* @param mixed $data_arr Data array to escape.
*
* @return mixed Escapped SQL Data.
*/
public function escape_array( $data_arr ) {
if ( ! is_array( $data_arr ) || empty( $data_arr ) ) {
return false;
}
$tmp_arr = array();
foreach ( $data_arr as $dt ) {
$tmp_arr[] = $this->escape( $dt );
}
return $tmp_arr;
}
/**
* Method escape()
*
* Escape SQL Data.
*
* @param mixed $data Data to escape.
*
* @return mixed Escapped SQL Data.
*/
public function escape( $data ) {
if ( function_exists( 'esc_sql' ) ) {
return esc_sql( $data );
} else {
return $this->wpdb->escape( $data );
}
}
/**
* Method use_mysqli()
*
* Use MySQLi, Support old & new versions of WordPress (3.9+).
*
* @return boolean|self false|$instance Instance of \mysqli
*/
public static function use_mysqli() {
if ( ! function_exists( '\mysqli_connect' ) ) {
return false;
}
return self::$instance->wpdb->dbh instanceof \mysqli; // NOSONAR - required.
}
/**
* Method ping()
*
* Ping MySQLi.
*
* @param mixed $link Query link.
*
* @return mixed \mysqli_ping
*/
public static function ping( $link ) {
if ( self::use_mysqli() ) { // NOSONAR - required.
if ( version_compare( phpversion(), '8.4', '<' ) ) {
return \mysqli_ping( $link );
} else {
try {
self::$instance->wpdb->query( 'DO 1' );
return true;
} catch ( \mysqli_sql_exception $e ) { // NOSONAR - ok.
// error.
return false;
}
}
} else {
return \mysql_ping( $link );
}
}
/**
* Method m_query()
*
* MySQLi m_query.
*
* @param mixed $query Query params.
* @param mixed $link Query link.
*
* @return mixed \mysqli_query
*/
public static function m_query( $query, $link ) {
if ( self::use_mysqli() ) { // NOSONAR - required.
return \mysqli_query( $link, $query );
} else {
return \mysql_query( $query, $link );
}
}
/**
* Method fetch_object()
*
* Fetch object.
*
* @param mixed $result Query result.
*
* @return boolean|mixed false|\mysqli_fetch_object
*/
public static function fetch_object( $result ) {
if ( is_bool( $result ) ) {
return $result;
}
if ( self::use_mysqli() ) { // NOSONAR - required.
return \mysqli_fetch_object( $result );
} else {
return \mysql_fetch_object( $result );
}
}
/**
* Method free_result()
*
* MySQLi free result.
*
* @param mixed $result Query result.
*
* @return boolean|mixed false|\mysqli_free_result
*/
public static function free_result( $result ) {
if ( is_bool( $result ) ) {
return $result;
}
if ( self::use_mysqli() ) { // NOSONAR - required.
\mysqli_free_result( $result );
} else {
\mysql_free_result( $result );
}
}
/**
* Method data_seek()
*
* MySQLi data seek.
*
* @param mixed $result Query result.
* @param mixed $offset Query offset.
*
* @return boolean|mixed false|\mysqli_data_seek
*/
public static function data_seek( $result, $offset ) {
if ( is_bool( $result ) ) {
return $result;
}
if ( self::use_mysqli() ) { // NOSONAR - required.
if ( ! ( $result instanceof \mysqli_result ) ) {
return $result;
}
return \mysqli_data_seek( $result, $offset );
} else {
return \mysql_data_seek( $result, $offset );
}
}
/**
* Method fetch_array()
*
* MySQLi fetch array.
*
* @param mixed $result Query result.
* @param null $result_type Query result type.
*
* @return boolean|mixed false|\mysqli_fetch_array.
*/
public static function fetch_array( $result, $result_type = null ) {
if ( is_bool( $result ) ) {
return $result;
}
if ( self::use_mysqli() ) { // NOSONAR - required.
return \mysqli_fetch_array( $result, ( null === $result_type ? MYSQLI_BOTH : $result_type ) );
} else {
return \mysql_fetch_array( $result, ( null === $result_type ? MYSQL_BOTH : $result_type ) );
}
}
/**
* Method num_rows()
*
* MySQLi number of rows.
*
* @param mixed $result Query result.
*
* @return boolean|mixed false|\mysqli_num_rows.
*/
public static function num_rows( $result ) {
if ( ! self::is_result( $result ) ) { // NOSONAR - required.
return false;
}
if ( self::use_mysqli() ) { // NOSONAR - required.
return \mysqli_num_rows( $result );
} else {
return \mysql_num_rows( $result );
}
}
/**
* Method is_result()
*
* Return instance of \mysqli_result
*
* @param mixed $result Query result.
*
* @return boolean|mixed false|\mysqli_result
*/
public static function is_result( $result ) {
if ( is_bool( $result ) ) {
return $result;
}
if ( self::use_mysqli() ) { // NOSONAR - required.
return $result instanceof \mysqli_result;
} else {
return is_resource( $result );
}
}
// phpcs:enable
}