339 lines
8.7 KiB
PHP
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 );
|