wp_back/wp-content/plugins/query-monitor/collectors/environment.php
2024-05-20 15:37:46 +03:00

339 lines
8.7 KiB
PHP

<?php declare(strict_types = 1);
/**
* Environment data collector.
*
* @package query-monitor
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* @extends QM_DataCollector<QM_Data_Environment>
*/
class QM_Collector_Environment extends QM_DataCollector {
/**
* @var string
*/
public $id = 'environment';
/**
* @var array<int, string>
*/
protected $php_vars = array(
'max_execution_time',
'memory_limit',
'upload_max_filesize',
'post_max_size',
'display_errors',
'log_errors',
);
public function get_storage(): QM_Data {
return new QM_Data_Environment();
}
/**
* @param int $error_reporting
* @return array<string, bool>
*/
protected static function get_error_levels( $error_reporting ) {
$levels = array(
'E_ERROR' => false,
'E_WARNING' => false,
'E_PARSE' => false,
'E_NOTICE' => false,
'E_CORE_ERROR' => false,
'E_CORE_WARNING' => false,
'E_COMPILE_ERROR' => false,
'E_COMPILE_WARNING' => false,
'E_USER_ERROR' => false,
'E_USER_WARNING' => false,
'E_USER_NOTICE' => false,
'E_STRICT' => false,
'E_RECOVERABLE_ERROR' => false,
'E_DEPRECATED' => false,
'E_USER_DEPRECATED' => false,
'E_ALL' => false,
);
foreach ( $levels as $level => $reported ) {
if ( defined( $level ) ) {
$c = constant( $level );
if ( $error_reporting & $c ) {
$levels[ $level ] = true;
}
}
}
return $levels;
}
/**
* @return void
*/
public function process() {
global $wp_version;
$mysql_vars = array(
'key_buffer_size' => true, # Key cache size limit
'max_allowed_packet' => false, # Individual query size limit
'max_connections' => false, # Max number of client connections
'query_cache_limit' => true, # Individual query cache size limit
'query_cache_size' => true, # Total cache size limit
'query_cache_type' => 'ON', # Query cache on or off
'innodb_buffer_pool_size' => false, # The amount of memory allocated to the InnoDB buffer pool
);
/** @var QM_Collector_DB_Queries|null */
$dbq = QM_Collectors::get( 'db_queries' );
if ( $dbq ) {
if ( method_exists( $dbq->wpdb, 'db_version' ) ) {
$server = $dbq->wpdb->db_version();
// query_cache_* deprecated since MySQL 5.7.20
if ( version_compare( $server, '5.7.20', '>=' ) ) {
unset( $mysql_vars['query_cache_limit'], $mysql_vars['query_cache_size'], $mysql_vars['query_cache_type'] );
}
}
// phpcs:disable
/** @var array<int, stdClass>|null */
$variables = $dbq->wpdb->get_results( "
SHOW VARIABLES
WHERE Variable_name IN ( '" . implode( "', '", array_keys( $mysql_vars ) ) . "' )
" );
// phpcs:enable
/** @var mysqli|false|null $dbh */
$dbh = $dbq->wpdb->dbh;
if ( is_object( $dbh ) ) {
# mysqli or PDO
$extension = get_class( $dbh );
} else {
# Who knows?
$extension = null;
}
$client = mysqli_get_client_version();
if ( $client ) {
$client_version = implode( '.', QM_Util::get_client_version( $client ) );
$client_version = sprintf( '%s (%s)', $client, $client_version );
} else {
$client_version = null;
}
$server_version = self::get_server_version( $dbq->wpdb );
$info = array(
'server-version' => $server_version,
'extension' => $extension,
'client-version' => $client_version,
'user' => $dbq->wpdb->dbuser,
'host' => $dbq->wpdb->dbhost,
'database' => $dbq->wpdb->dbname,
);
$this->data->db = array(
'info' => $info,
'vars' => $mysql_vars,
'variables' => $variables ?: array(),
);
}
$php_data = array(
'variables' => array(),
);
$php_data['version'] = phpversion();
$php_data['sapi'] = php_sapi_name();
$php_data['user'] = self::get_current_user();
// https://www.php.net/supported-versions.php
$php_data['old'] = version_compare( $php_data['version'], '7.4', '<' );
foreach ( $this->php_vars as $setting ) {
$php_data['variables'][ $setting ] = ini_get( $setting ) ?: null;
}
if ( function_exists( 'get_loaded_extensions' ) ) {
$extensions = get_loaded_extensions();
sort( $extensions, SORT_STRING | SORT_FLAG_CASE );
$php_data['extensions'] = array_combine( $extensions, array_map( array( $this, 'get_extension_version' ), $extensions ) ) ?: array();
} else {
$php_data['extensions'] = array();
}
$php_data['error_reporting'] = error_reporting();
$php_data['error_levels'] = self::get_error_levels( $php_data['error_reporting'] );
$this->data->wp['version'] = $wp_version;
$constants = array(
'WP_DEBUG' => self::format_bool_constant( 'WP_DEBUG' ),
'WP_DEBUG_DISPLAY' => self::format_bool_constant( 'WP_DEBUG_DISPLAY' ),
'WP_DEBUG_LOG' => self::format_bool_constant( 'WP_DEBUG_LOG' ),
'SCRIPT_DEBUG' => self::format_bool_constant( 'SCRIPT_DEBUG' ),
'WP_CACHE' => self::format_bool_constant( 'WP_CACHE' ),
'CONCATENATE_SCRIPTS' => self::format_bool_constant( 'CONCATENATE_SCRIPTS' ),
'COMPRESS_SCRIPTS' => self::format_bool_constant( 'COMPRESS_SCRIPTS' ),
'COMPRESS_CSS' => self::format_bool_constant( 'COMPRESS_CSS' ),
'WP_ENVIRONMENT_TYPE' => self::format_bool_constant( 'WP_ENVIRONMENT_TYPE' ),
'WP_DEVELOPMENT_MODE' => self::format_bool_constant( 'WP_DEVELOPMENT_MODE' ),
);
if ( function_exists( 'wp_get_environment_type' ) ) {
$this->data->wp['environment_type'] = wp_get_environment_type();
}
if ( function_exists( 'wp_get_development_mode' ) ) {
$this->data->wp['development_mode'] = wp_get_development_mode();
}
$this->data->wp['constants'] = apply_filters( 'qm/environment-constants', $constants );
if ( is_multisite() ) {
$this->data->wp['constants']['SUNRISE'] = self::format_bool_constant( 'SUNRISE' );
}
if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
$server = explode( ' ', wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) );
$server = explode( '/', reset( $server ) );
} else {
$server = array( '' );
}
$server_version = $server[1] ?? null;
if ( isset( $_SERVER['SERVER_ADDR'] ) ) {
$address = wp_unslash( $_SERVER['SERVER_ADDR'] );
} else {
$address = null;
}
$this->data->php = $php_data;
$this->data->server = array(
'name' => $server[0],
'version' => $server_version,
'address' => $address,
'host' => null,
'OS' => null,
'arch' => null,
);
if ( function_exists( 'php_uname' ) ) {
$this->data->server['host'] = php_uname( 'n' );
$this->data->server['OS'] = php_uname( 's' ) . ' ' . php_uname( 'r' );
$this->data->server['arch'] = php_uname( 'm' );
}
}
/**
* @param string $extension
* @return string
*/
public function get_extension_version( $extension ) {
// Nothing is simple in PHP. The exif and mysqlnd extensions (and probably others) add a bunch of
// crap to their version number, so we need to pluck out the first numeric value in the string.
$version = trim( phpversion( $extension ) ?: '' );
if ( ! $version ) {
return $version;
}
$parts = explode( ' ', $version );
foreach ( $parts as $part ) {
if ( $part && is_numeric( $part[0] ) ) {
$version = $part;
break;
}
}
return $version;
}
/**
* @param wpdb $db
* @return string
*/
protected static function get_server_version( wpdb $db ) {
$version = null;
if ( method_exists( $db, 'db_server_info' ) ) {
$version = $db->db_server_info();
}
if ( ! $version ) {
$version = $db->get_var( 'SELECT VERSION()' );
}
if ( ! $version ) {
$version = __( 'Unknown', 'query-monitor' );
}
return $version;
}
/**
* @return string
*/
protected static function get_current_user() {
$php_u = null;
if ( function_exists( 'posix_getpwuid' ) && function_exists( 'posix_getuid' ) && function_exists( 'posix_getgrgid' ) ) {
$u = posix_getpwuid( posix_getuid() );
if ( isset( $u['gid'], $u['name'] ) ) {
$g = posix_getgrgid( $u['gid'] );
if ( isset( $g['name'] ) ) {
$php_u = $u['name'] . ':' . $g['name'];
}
}
}
if ( empty( $php_u ) && isset( $_ENV['APACHE_RUN_USER'] ) ) {
$php_u = $_ENV['APACHE_RUN_USER'];
if ( isset( $_ENV['APACHE_RUN_GROUP'] ) ) {
$php_u .= ':' . $_ENV['APACHE_RUN_GROUP'];
}
}
if ( empty( $php_u ) && isset( $_SERVER['USER'] ) ) {
$php_u = wp_unslash( $_SERVER['USER'] );
}
if ( empty( $php_u ) && function_exists( 'exec' ) ) {
$php_u = exec( 'whoami' ); // phpcs:ignore
}
if ( empty( $php_u ) && function_exists( 'getenv' ) ) {
$php_u = getenv( 'USERNAME' );
}
return $php_u;
}
}
/**
* @param array<string, QM_Collector> $collectors
* @param QueryMonitor $qm
* @return array<string, QM_Collector>
*/
function register_qm_collector_environment( array $collectors, QueryMonitor $qm ) {
$collectors['environment'] = new QM_Collector_Environment();
return $collectors;
}
add_filter( 'qm/collectors', 'register_qm_collector_environment', 20, 2 );