mirror of
https://github.com/felixfoertsch/wordpress-dev-env.git
synced 2026-04-18 07:18:43 +02:00
Initial commit
This commit is contained in:
130
wordpress_plugins/query-monitor/classes/Activation.php
Normal file
130
wordpress_plugins/query-monitor/classes/Activation.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin activation handler.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
class QM_Activation extends QM_Plugin {
|
||||
|
||||
protected function __construct( $file ) {
|
||||
|
||||
# PHP version handling
|
||||
if ( ! self::php_version_met() ) {
|
||||
add_action( 'all_admin_notices', array( $this, 'php_notice' ) );
|
||||
return;
|
||||
}
|
||||
|
||||
# Filters
|
||||
add_filter( 'pre_update_option_active_plugins', array( $this, 'filter_active_plugins' ) );
|
||||
add_filter( 'pre_update_site_option_active_sitewide_plugins', array( $this, 'filter_active_sitewide_plugins' ) );
|
||||
|
||||
# Activation and deactivation
|
||||
register_activation_hook( $file, array( $this, 'activate' ) );
|
||||
register_deactivation_hook( $file, array( $this, 'deactivate' ) );
|
||||
|
||||
# Parent setup:
|
||||
parent::__construct( $file );
|
||||
|
||||
}
|
||||
|
||||
public function activate( $sitewide = false ) {
|
||||
$db = WP_CONTENT_DIR . '/db.php';
|
||||
|
||||
if ( ! file_exists( $db ) && function_exists( 'symlink' ) ) {
|
||||
@symlink( $this->plugin_path( 'wp-content/db.php' ), $db ); // phpcs:ignore
|
||||
}
|
||||
|
||||
if ( $sitewide ) {
|
||||
update_site_option( 'active_sitewide_plugins', get_site_option( 'active_sitewide_plugins' ) );
|
||||
} else {
|
||||
update_option( 'active_plugins', get_option( 'active_plugins' ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function deactivate() {
|
||||
$admins = QM_Util::get_admins();
|
||||
|
||||
// Remove legacy capability handling:
|
||||
if ( $admins ) {
|
||||
$admins->remove_cap( 'view_query_monitor' );
|
||||
}
|
||||
|
||||
# Only delete db.php if it belongs to Query Monitor
|
||||
if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && class_exists( 'QM_DB' ) ) {
|
||||
unlink( WP_CONTENT_DIR . '/db.php' ); // phpcs:ignore
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function filter_active_plugins( $plugins ) {
|
||||
|
||||
// this needs to run on the cli too
|
||||
|
||||
if ( empty( $plugins ) ) {
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
$f = preg_quote( basename( $this->plugin_base() ), '/' );
|
||||
|
||||
return array_merge(
|
||||
preg_grep( '/' . $f . '$/', $plugins ),
|
||||
preg_grep( '/' . $f . '$/', $plugins, PREG_GREP_INVERT )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public function filter_active_sitewide_plugins( $plugins ) {
|
||||
|
||||
if ( empty( $plugins ) ) {
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
$f = $this->plugin_base();
|
||||
|
||||
if ( isset( $plugins[ $f ] ) ) {
|
||||
|
||||
unset( $plugins[ $f ] );
|
||||
|
||||
return array_merge( array(
|
||||
$f => time(),
|
||||
), $plugins );
|
||||
|
||||
} else {
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function php_notice() {
|
||||
?>
|
||||
<div id="qm_php_notice" class="error">
|
||||
<p>
|
||||
<span class="dashicons dashicons-warning" style="color:#dd3232" aria-hidden="true"></span>
|
||||
<?php
|
||||
echo esc_html( sprintf(
|
||||
/* Translators: 1: Minimum required PHP version, 2: Current PHP version. */
|
||||
__( 'The Query Monitor plugin requires PHP version %1$s or higher. This site is running version %2$s.', 'query-monitor' ),
|
||||
self::$minimum_php_version,
|
||||
PHP_VERSION
|
||||
) );
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
public static function init( $file = null ) {
|
||||
|
||||
static $instance = null;
|
||||
|
||||
if ( ! $instance ) {
|
||||
$instance = new QM_Activation( $file );
|
||||
}
|
||||
|
||||
return $instance;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
348
wordpress_plugins/query-monitor/classes/Backtrace.php
Normal file
348
wordpress_plugins/query-monitor/classes/Backtrace.php
Normal file
@@ -0,0 +1,348 @@
|
||||
<?php
|
||||
/**
|
||||
* Function call backtrace container.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'QM_Backtrace' ) ) {
|
||||
class QM_Backtrace {
|
||||
|
||||
protected static $ignore_class = array(
|
||||
'wpdb' => true,
|
||||
'QueryMonitor' => true,
|
||||
'W3_Db' => true,
|
||||
'Debug_Bar_PHP' => true,
|
||||
'WP_Hook' => true,
|
||||
);
|
||||
protected static $ignore_method = array();
|
||||
protected static $ignore_func = array(
|
||||
'include_once' => true,
|
||||
'require_once' => true,
|
||||
'include' => true,
|
||||
'require' => true,
|
||||
'call_user_func_array' => true,
|
||||
'call_user_func' => true,
|
||||
'trigger_error' => true,
|
||||
'_doing_it_wrong' => true,
|
||||
'_deprecated_argument' => true,
|
||||
'_deprecated_file' => true,
|
||||
'_deprecated_function' => true,
|
||||
'dbDelta' => true,
|
||||
);
|
||||
protected static $show_args = array(
|
||||
'do_action' => 1,
|
||||
'apply_filters' => 1,
|
||||
'do_action_ref_array' => 1,
|
||||
'apply_filters_ref_array' => 1,
|
||||
'get_template_part' => 2,
|
||||
'get_extended_template_part' => 2,
|
||||
'load_template' => 'dir',
|
||||
'dynamic_sidebar' => 1,
|
||||
'get_header' => 1,
|
||||
'get_sidebar' => 1,
|
||||
'get_footer' => 1,
|
||||
'class_exists' => 2,
|
||||
'current_user_can' => 3,
|
||||
'user_can' => 4,
|
||||
'current_user_can_for_blog' => 4,
|
||||
'author_can' => 4,
|
||||
);
|
||||
protected static $filtered = false;
|
||||
protected $trace = null;
|
||||
protected $filtered_trace = null;
|
||||
protected $calling_line = 0;
|
||||
protected $calling_file = '';
|
||||
|
||||
public function __construct( array $args = array(), array $trace = null ) {
|
||||
$this->trace = ( null === $trace ) ? debug_backtrace( false ) : $trace;
|
||||
|
||||
$args = array_merge( array(
|
||||
'ignore_current_filter' => true,
|
||||
'ignore_frames' => 0,
|
||||
), $args );
|
||||
|
||||
$this->ignore( 1 ); # Self-awareness
|
||||
|
||||
/**
|
||||
* If error_handler() is in the trace, QM fails later when it tries
|
||||
* to get $lowest['file'] in get_filtered_trace()
|
||||
*/
|
||||
if ( 'error_handler' === $this->trace[0]['function'] ) {
|
||||
$this->ignore( 1 );
|
||||
}
|
||||
|
||||
if ( $args['ignore_frames'] ) {
|
||||
$this->ignore( $args['ignore_frames'] );
|
||||
}
|
||||
if ( $args['ignore_current_filter'] ) {
|
||||
$this->ignore_current_filter();
|
||||
}
|
||||
|
||||
foreach ( $this->trace as $k => $frame ) {
|
||||
if ( ! isset( $frame['args'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $frame['function'] ) && isset( self::$show_args[ $frame['function'] ] ) ) {
|
||||
$show = self::$show_args[ $frame['function'] ];
|
||||
|
||||
if ( 'dir' === $show ) {
|
||||
$show = 1;
|
||||
}
|
||||
|
||||
$frame['args'] = array_slice( $frame['args'], 0, $show );
|
||||
|
||||
} else {
|
||||
unset( $frame['args'] );
|
||||
}
|
||||
|
||||
$this->trace[ $k ] = $frame;
|
||||
}
|
||||
}
|
||||
|
||||
public function get_stack() {
|
||||
|
||||
$trace = $this->get_filtered_trace();
|
||||
$stack = wp_list_pluck( $trace, 'display' );
|
||||
|
||||
return $stack;
|
||||
|
||||
}
|
||||
|
||||
public function get_caller() {
|
||||
|
||||
$trace = $this->get_filtered_trace();
|
||||
|
||||
return reset( $trace );
|
||||
|
||||
}
|
||||
|
||||
public function get_component() {
|
||||
|
||||
$components = array();
|
||||
|
||||
foreach ( $this->trace as $frame ) {
|
||||
$component = self::get_frame_component( $frame );
|
||||
|
||||
if ( $component ) {
|
||||
if ( 'plugin' === $component->type ) {
|
||||
// If the component is a plugin then it can't be anything else,
|
||||
// so short-circuit and return early.
|
||||
return $component;
|
||||
}
|
||||
|
||||
$components[ $component->type ] = $component;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( QM_Util::get_file_dirs() as $type => $dir ) {
|
||||
if ( isset( $components[ $type ] ) ) {
|
||||
return $components[ $type ];
|
||||
}
|
||||
}
|
||||
|
||||
# This should not happen
|
||||
|
||||
}
|
||||
|
||||
public static function get_frame_component( array $frame ) {
|
||||
try {
|
||||
|
||||
if ( isset( $frame['class'] ) ) {
|
||||
if ( ! class_exists( $frame['class'], false ) ) {
|
||||
return null;
|
||||
}
|
||||
if ( ! method_exists( $frame['class'], $frame['function'] ) ) {
|
||||
return null;
|
||||
}
|
||||
$ref = new ReflectionMethod( $frame['class'], $frame['function'] );
|
||||
$file = $ref->getFileName();
|
||||
} elseif ( isset( $frame['function'] ) && function_exists( $frame['function'] ) ) {
|
||||
$ref = new ReflectionFunction( $frame['function'] );
|
||||
$file = $ref->getFileName();
|
||||
} elseif ( isset( $frame['file'] ) ) {
|
||||
$file = $frame['file'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return QM_Util::get_file_component( $file );
|
||||
|
||||
} catch ( ReflectionException $e ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function get_trace() {
|
||||
return $this->trace;
|
||||
}
|
||||
|
||||
public function get_display_trace() {
|
||||
return $this->get_filtered_trace();
|
||||
}
|
||||
|
||||
public function get_filtered_trace() {
|
||||
|
||||
if ( ! isset( $this->filtered_trace ) ) {
|
||||
|
||||
$trace = array_map( array( $this, 'filter_trace' ), $this->trace );
|
||||
$trace = array_values( array_filter( $trace ) );
|
||||
|
||||
if ( empty( $trace ) && ! empty( $this->trace ) ) {
|
||||
$lowest = $this->trace[0];
|
||||
$file = QM_Util::standard_dir( $lowest['file'], '' );
|
||||
$lowest['calling_file'] = $lowest['file'];
|
||||
$lowest['calling_line'] = $lowest['line'];
|
||||
$lowest['function'] = $file;
|
||||
$lowest['display'] = $file;
|
||||
$lowest['id'] = $file;
|
||||
unset( $lowest['class'], $lowest['args'], $lowest['type'] );
|
||||
$trace[0] = $lowest;
|
||||
}
|
||||
|
||||
$this->filtered_trace = $trace;
|
||||
|
||||
}
|
||||
|
||||
return $this->filtered_trace;
|
||||
|
||||
}
|
||||
|
||||
public function ignore( $num ) {
|
||||
for ( $i = 0; $i < $num; $i++ ) {
|
||||
unset( $this->trace[ $i ] );
|
||||
}
|
||||
$this->trace = array_values( $this->trace );
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function ignore_current_filter() {
|
||||
|
||||
if ( isset( $this->trace[2] ) && isset( $this->trace[2]['function'] ) ) {
|
||||
if ( in_array( $this->trace[2]['function'], array( 'apply_filters', 'do_action' ), true ) ) {
|
||||
$this->ignore( 3 ); # Ignore filter and action callbacks
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function filter_trace( array $trace ) {
|
||||
|
||||
if ( ! self::$filtered && function_exists( 'did_action' ) && did_action( 'plugins_loaded' ) ) {
|
||||
|
||||
/**
|
||||
* Filters which classes to ignore when constructing user-facing call stacks.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @param bool[] $ignore_class Array of class names to ignore. The array keys are class names to ignore,
|
||||
* the array values are whether to ignore the class or not (usually true).
|
||||
*/
|
||||
self::$ignore_class = apply_filters( 'qm/trace/ignore_class', self::$ignore_class );
|
||||
|
||||
/**
|
||||
* Filters which class methods to ignore when constructing user-facing call stacks.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @param bool[] $ignore_method Array of method names to ignore. The array keys are method names to ignore,
|
||||
* the array values are whether to ignore the method or not (usually true).
|
||||
*/
|
||||
self::$ignore_method = apply_filters( 'qm/trace/ignore_method', self::$ignore_method );
|
||||
|
||||
/**
|
||||
* Filters which functions to ignore when constructing user-facing call stacks.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @param bool[] $ignore_func Array of function names to ignore. The array keys are function names to ignore,
|
||||
* the array values are whether to ignore the function or not (usually true).
|
||||
*/
|
||||
self::$ignore_func = apply_filters( 'qm/trace/ignore_func', self::$ignore_func );
|
||||
|
||||
/**
|
||||
* Filters the number of argument values to show for the given function name when constructing user-facing
|
||||
* call stacks.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @param (int|string)[] $show_args The number of argument values to show for the given function name. The
|
||||
* array keys are function names, the array values are either integers or
|
||||
* "dir" to specifically treat the function argument as a directory path.
|
||||
*/
|
||||
self::$show_args = apply_filters( 'qm/trace/show_args', self::$show_args );
|
||||
|
||||
self::$filtered = true;
|
||||
|
||||
}
|
||||
|
||||
$return = $trace;
|
||||
|
||||
if ( isset( $trace['class'] ) ) {
|
||||
if ( isset( self::$ignore_class[ $trace['class'] ] ) ) {
|
||||
$return = null;
|
||||
} elseif ( isset( self::$ignore_method[ $trace['class'] ][ $trace['function'] ] ) ) {
|
||||
$return = null;
|
||||
} elseif ( 0 === strpos( $trace['class'], 'QM' ) ) {
|
||||
$return = null;
|
||||
} else {
|
||||
$return['id'] = $trace['class'] . $trace['type'] . $trace['function'] . '()';
|
||||
$return['display'] = QM_Util::shorten_fqn( $trace['class'] . $trace['type'] . $trace['function'] ) . '()';
|
||||
}
|
||||
} else {
|
||||
if ( isset( self::$ignore_func[ $trace['function'] ] ) ) {
|
||||
$return = null;
|
||||
} elseif ( isset( self::$show_args[ $trace['function'] ] ) ) {
|
||||
$show = self::$show_args[ $trace['function'] ];
|
||||
|
||||
if ( 'dir' === $show ) {
|
||||
if ( isset( $trace['args'][0] ) ) {
|
||||
$arg = QM_Util::standard_dir( $trace['args'][0], '' );
|
||||
$return['id'] = $trace['function'] . '()';
|
||||
$return['display'] = QM_Util::shorten_fqn( $trace['function'] ) . "('{$arg}')";
|
||||
}
|
||||
} else {
|
||||
$args = array();
|
||||
for ( $i = 0; $i < $show; $i++ ) {
|
||||
if ( isset( $trace['args'][ $i ] ) ) {
|
||||
if ( is_string( $trace['args'][ $i ] ) ) {
|
||||
$args[] = '\'' . $trace['args'][ $i ] . '\'';
|
||||
} else {
|
||||
$args[] = QM_Util::display_variable( $trace['args'][ $i ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
$return['id'] = $trace['function'] . '()';
|
||||
$return['display'] = QM_Util::shorten_fqn( $trace['function'] ) . '(' . implode( ',', $args ) . ')';
|
||||
}
|
||||
} else {
|
||||
$return['id'] = $trace['function'] . '()';
|
||||
$return['display'] = QM_Util::shorten_fqn( $trace['function'] ) . '()';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $return ) {
|
||||
|
||||
$return['calling_file'] = $this->calling_file;
|
||||
$return['calling_line'] = $this->calling_line;
|
||||
|
||||
}
|
||||
|
||||
if ( isset( $trace['line'] ) ) {
|
||||
$this->calling_line = $trace['line'];
|
||||
}
|
||||
if ( isset( $trace['file'] ) ) {
|
||||
$this->calling_file = $trace['file'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
add_action( 'init', 'QueryMonitor::symlink_warning' );
|
||||
|
||||
}
|
||||
59
wordpress_plugins/query-monitor/classes/CLI.php
Normal file
59
wordpress_plugins/query-monitor/classes/CLI.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin CLI command.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
class QM_CLI extends QM_Plugin {
|
||||
|
||||
protected function __construct( $file ) {
|
||||
|
||||
# Register command
|
||||
WP_CLI::add_command( 'qm enable', array( $this, 'enable' ) );
|
||||
|
||||
# Parent setup:
|
||||
parent::__construct( $file );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable QM by creating the symlink for db.php
|
||||
*/
|
||||
public function enable() {
|
||||
$drop_in = WP_CONTENT_DIR . '/db.php';
|
||||
|
||||
if ( file_exists( $drop_in ) ) {
|
||||
if ( false !== strpos( file_get_contents( $drop_in ), 'class QM_DB' ) ) {
|
||||
WP_CLI::success( "Query Monitor's wp-content/db.php is already in place" );
|
||||
exit( 0 );
|
||||
} else {
|
||||
WP_CLI::error( 'Unknown wp-content/db.php already is already in place' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'symlink' ) ) {
|
||||
WP_CLI::error( 'The symlink function is not available' );
|
||||
}
|
||||
|
||||
if ( symlink( $this->plugin_path( 'wp-content/db.php' ), $drop_in ) ) {
|
||||
WP_CLI::success( 'wp-content/db.php symlink created' );
|
||||
exit( 0 );
|
||||
} else {
|
||||
WP_CLI::error( 'Failed to create wp-content/db.php symlink' );
|
||||
}
|
||||
}
|
||||
|
||||
public static function init( $file = null ) {
|
||||
|
||||
static $instance = null;
|
||||
|
||||
if ( ! $instance ) {
|
||||
$instance = new QM_CLI( $file );
|
||||
}
|
||||
|
||||
return $instance;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
266
wordpress_plugins/query-monitor/classes/Collector.php
Normal file
266
wordpress_plugins/query-monitor/classes/Collector.php
Normal file
@@ -0,0 +1,266 @@
|
||||
<?php
|
||||
/**
|
||||
* Abstract data collector.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'QM_Collector' ) ) {
|
||||
abstract class QM_Collector {
|
||||
|
||||
protected $timer;
|
||||
protected $data = array(
|
||||
'types' => array(),
|
||||
'component_times' => array(),
|
||||
);
|
||||
protected static $hide_qm = null;
|
||||
|
||||
public $concerned_actions = array();
|
||||
public $concerned_filters = array();
|
||||
public $concerned_constants = array();
|
||||
public $tracked_hooks = array();
|
||||
|
||||
public function __construct() {}
|
||||
|
||||
final public function id() {
|
||||
return "qm-{$this->id}";
|
||||
}
|
||||
|
||||
protected function log_type( $type ) {
|
||||
|
||||
if ( isset( $this->data['types'][ $type ] ) ) {
|
||||
$this->data['types'][ $type ]++;
|
||||
} else {
|
||||
$this->data['types'][ $type ] = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function maybe_log_dupe( $sql, $i ) {
|
||||
|
||||
$sql = str_replace( array( "\r\n", "\r", "\n" ), ' ', $sql );
|
||||
$sql = str_replace( array( "\t", '`' ), '', $sql );
|
||||
$sql = preg_replace( '/ +/', ' ', $sql );
|
||||
$sql = trim( $sql );
|
||||
$sql = rtrim( $sql, ';' );
|
||||
|
||||
$this->data['dupes'][ $sql ][] = $i;
|
||||
|
||||
}
|
||||
|
||||
protected function log_component( $component, $ltime, $type ) {
|
||||
|
||||
if ( ! isset( $this->data['component_times'][ $component->name ] ) ) {
|
||||
$this->data['component_times'][ $component->name ] = array(
|
||||
'component' => $component->name,
|
||||
'ltime' => 0,
|
||||
'types' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
$this->data['component_times'][ $component->name ]['ltime'] += $ltime;
|
||||
|
||||
if ( isset( $this->data['component_times'][ $component->name ]['types'][ $type ] ) ) {
|
||||
$this->data['component_times'][ $component->name ]['types'][ $type ]++;
|
||||
} else {
|
||||
$this->data['component_times'][ $component->name ]['types'][ $type ] = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static function timer_stop_float() {
|
||||
global $timestart;
|
||||
return microtime( true ) - $timestart;
|
||||
}
|
||||
|
||||
public static function format_bool_constant( $constant ) {
|
||||
// @TODO this should be in QM_Util
|
||||
|
||||
if ( ! defined( $constant ) ) {
|
||||
/* translators: Undefined PHP constant */
|
||||
return __( 'undefined', 'query-monitor' );
|
||||
} elseif ( is_string( constant( $constant ) ) && ! is_numeric( constant( $constant ) ) ) {
|
||||
return constant( $constant );
|
||||
} elseif ( ! constant( $constant ) ) {
|
||||
return 'false';
|
||||
} else {
|
||||
return 'true';
|
||||
}
|
||||
}
|
||||
|
||||
final public function get_data() {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
final public function set_id( $id ) {
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
final public function process_concerns() {
|
||||
global $wp_filter;
|
||||
|
||||
$tracked = array();
|
||||
$id = $this->id;
|
||||
|
||||
/**
|
||||
* Filters the concerned actions for the given panel.
|
||||
*
|
||||
* The dynamic portion of the hook name, `$id`, refers to the collector ID, which is typically the `$id`
|
||||
* property of the collector class.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param string[] $actions Array of action names that this panel concerns itself with.
|
||||
*/
|
||||
$concerned_actions = apply_filters( "qm/collect/concerned_actions/{$id}", $this->get_concerned_actions() );
|
||||
|
||||
/**
|
||||
* Filters the concerned filters for the given panel.
|
||||
*
|
||||
* The dynamic portion of the hook name, `$id`, refers to the collector ID, which is typically the `$id`
|
||||
* property of the collector class.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param string[] $filters Array of filter names that this panel concerns itself with.
|
||||
*/
|
||||
$concerned_filters = apply_filters( "qm/collect/concerned_filters/{$id}", $this->get_concerned_filters() );
|
||||
|
||||
/**
|
||||
* Filters the concerned options for the given panel.
|
||||
*
|
||||
* The dynamic portion of the hook name, `$id`, refers to the collector ID, which is typically the `$id`
|
||||
* property of the collector class.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param string[] $options Array of option names that this panel concerns itself with.
|
||||
*/
|
||||
$concerned_options = apply_filters( "qm/collect/concerned_options/{$id}", $this->get_concerned_options() );
|
||||
|
||||
/**
|
||||
* Filters the concerned constants for the given panel.
|
||||
*
|
||||
* The dynamic portion of the hook name, `$id`, refers to the collector ID, which is typically the `$id`
|
||||
* property of the collector class.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*
|
||||
* @param string[] $constants Array of constant names that this panel concerns itself with.
|
||||
*/
|
||||
$concerned_constants = apply_filters( "qm/collect/concerned_constants/{$id}", $this->get_concerned_constants() );
|
||||
|
||||
foreach ( $concerned_actions as $action ) {
|
||||
if ( has_action( $action ) ) {
|
||||
$this->concerned_actions[ $action ] = QM_Hook::process( $action, $wp_filter, true, true );
|
||||
}
|
||||
$tracked[] = $action;
|
||||
}
|
||||
|
||||
foreach ( $concerned_filters as $filter ) {
|
||||
if ( has_filter( $filter ) ) {
|
||||
$this->concerned_filters[ $filter ] = QM_Hook::process( $filter, $wp_filter, true, true );
|
||||
}
|
||||
$tracked[] = $filter;
|
||||
}
|
||||
|
||||
$option_filters = array(
|
||||
// Should this include the pre_delete_ and pre_update_ filters too?
|
||||
'pre_option_%s',
|
||||
'default_option_%s',
|
||||
'option_%s',
|
||||
'pre_site_option_%s',
|
||||
'default_site_option_%s',
|
||||
'site_option_%s',
|
||||
);
|
||||
|
||||
foreach ( $concerned_options as $option ) {
|
||||
foreach ( $option_filters as $option_filter ) {
|
||||
$filter = sprintf(
|
||||
$option_filter,
|
||||
$option
|
||||
);
|
||||
if ( has_filter( $filter ) ) {
|
||||
$this->concerned_filters[ $filter ] = QM_Hook::process( $filter, $wp_filter, true, true );
|
||||
}
|
||||
$tracked[] = $filter;
|
||||
}
|
||||
}
|
||||
|
||||
$this->concerned_actions = array_filter( $this->concerned_actions, array( $this, 'filter_concerns' ) );
|
||||
$this->concerned_filters = array_filter( $this->concerned_filters, array( $this, 'filter_concerns' ) );
|
||||
|
||||
foreach ( $concerned_constants as $constant ) {
|
||||
if ( defined( $constant ) ) {
|
||||
$this->concerned_constants[ $constant ] = constant( $constant );
|
||||
}
|
||||
}
|
||||
|
||||
sort( $tracked );
|
||||
|
||||
$this->tracked_hooks = $tracked;
|
||||
}
|
||||
|
||||
public function filter_concerns( $concerns ) {
|
||||
return ! empty( $concerns['actions'] );
|
||||
}
|
||||
|
||||
public static function format_user( WP_User $user_object ) {
|
||||
$user = get_object_vars( $user_object->data );
|
||||
unset(
|
||||
$user['user_pass'],
|
||||
$user['user_activation_key']
|
||||
);
|
||||
$user['roles'] = $user_object->roles;
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public static function enabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function hide_qm() {
|
||||
if ( null === self::$hide_qm ) {
|
||||
self::$hide_qm = QM_HIDE_SELF;
|
||||
}
|
||||
|
||||
return self::$hide_qm;
|
||||
}
|
||||
|
||||
public function filter_remove_qm( array $item ) {
|
||||
$component = $item['trace']->get_component();
|
||||
return ( 'query-monitor' !== $component->context );
|
||||
}
|
||||
|
||||
public function process() {}
|
||||
|
||||
public function post_process() {}
|
||||
|
||||
public function tear_down() {}
|
||||
|
||||
public function get_timer() {
|
||||
return $this->timer;
|
||||
}
|
||||
|
||||
public function set_timer( QM_Timer $timer ) {
|
||||
$this->timer = $timer;
|
||||
}
|
||||
|
||||
public function get_concerned_actions() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function get_concerned_filters() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function get_concerned_options() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function get_concerned_constants() {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
}
|
||||
74
wordpress_plugins/query-monitor/classes/Collectors.php
Normal file
74
wordpress_plugins/query-monitor/classes/Collectors.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* Container for data collectors.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'QM_Collectors' ) ) {
|
||||
class QM_Collectors implements IteratorAggregate {
|
||||
|
||||
private $items = array();
|
||||
private $processed = false;
|
||||
|
||||
public function getIterator() {
|
||||
return new ArrayIterator( $this->items );
|
||||
}
|
||||
|
||||
public static function add( QM_Collector $collector ) {
|
||||
$collectors = self::init();
|
||||
|
||||
$collectors->items[ $collector->id ] = $collector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a collector instance.
|
||||
*
|
||||
* @param string $id The collector ID.
|
||||
* @return QM_Collector|null The collector object.
|
||||
*/
|
||||
public static function get( $id ) {
|
||||
$collectors = self::init();
|
||||
if ( isset( $collectors->items[ $id ] ) ) {
|
||||
return $collectors->items[ $id ];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function init() {
|
||||
static $instance;
|
||||
|
||||
if ( ! $instance ) {
|
||||
$instance = new QM_Collectors();
|
||||
}
|
||||
|
||||
return $instance;
|
||||
|
||||
}
|
||||
|
||||
public function process() {
|
||||
if ( $this->processed ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $this as $collector ) {
|
||||
$collector->tear_down();
|
||||
|
||||
$timer = new QM_Timer();
|
||||
$timer->start();
|
||||
|
||||
$collector->process();
|
||||
$collector->process_concerns();
|
||||
|
||||
$collector->set_timer( $timer->stop() );
|
||||
}
|
||||
|
||||
foreach ( $this as $collector ) {
|
||||
$collector->post_process();
|
||||
}
|
||||
|
||||
$this->processed = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
149
wordpress_plugins/query-monitor/classes/Dispatcher.php
Normal file
149
wordpress_plugins/query-monitor/classes/Dispatcher.php
Normal file
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
/**
|
||||
* Abstract dispatcher.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'QM_Dispatcher' ) ) {
|
||||
abstract class QM_Dispatcher {
|
||||
|
||||
/**
|
||||
* Outputter instances.
|
||||
*
|
||||
* @var QM_Output[] Array of outputters.
|
||||
*/
|
||||
protected $outputters = array();
|
||||
|
||||
/**
|
||||
* Query Monitor plugin instance.
|
||||
*
|
||||
* @var QM_Plugin Plugin instance.
|
||||
*/
|
||||
protected $qm;
|
||||
|
||||
public function __construct( QM_Plugin $qm ) {
|
||||
$this->qm = $qm;
|
||||
|
||||
if ( ! defined( 'QM_COOKIE' ) ) {
|
||||
define( 'QM_COOKIE', 'wp-query_monitor_' . COOKIEHASH );
|
||||
}
|
||||
if ( ! defined( 'QM_EDITOR_COOKIE' ) ) {
|
||||
define( 'QM_EDITOR_COOKIE', 'wp-query_monitor_editor_' . COOKIEHASH );
|
||||
}
|
||||
|
||||
add_action( 'init', array( $this, 'init' ) );
|
||||
|
||||
}
|
||||
|
||||
abstract public function is_active();
|
||||
|
||||
final public function should_dispatch() {
|
||||
|
||||
$e = error_get_last();
|
||||
|
||||
# Don't dispatch if a fatal has occurred:
|
||||
if ( ! empty( $e ) && ( $e['type'] & QM_ERROR_FATALS ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows users to disable this dispatcher.
|
||||
*
|
||||
* The dynamic portion of the hook name, `$this->id`, refers to the dispatcher ID.
|
||||
*
|
||||
* @since 2.8.0
|
||||
*
|
||||
* @param bool $true Whether or not the dispatcher is enabled.
|
||||
*/
|
||||
if ( ! apply_filters( "qm/dispatch/{$this->id}", true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->is_active();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes and fetches the outputters for this dispatcher.
|
||||
*
|
||||
* @param string $outputter_id The outputter ID.
|
||||
* @return QM_Output[] Array of outputters.
|
||||
*/
|
||||
public function get_outputters( $outputter_id ) {
|
||||
$collectors = QM_Collectors::init();
|
||||
$collectors->process();
|
||||
|
||||
/**
|
||||
* Allows users to filter what outputs.
|
||||
*
|
||||
* The dynamic portion of the hook name, `$outputter_id`, refers to the outputter ID.
|
||||
*
|
||||
* @since 2.8.0
|
||||
*
|
||||
* @param QM_Output[] $outputters Array of outputters.
|
||||
* @param QM_Collectors $collectors List of collectors.
|
||||
*/
|
||||
$this->outputters = apply_filters( "qm/outputter/{$outputter_id}", array(), $collectors );
|
||||
|
||||
return $this->outputters;
|
||||
}
|
||||
|
||||
public function init() {
|
||||
if ( ! self::user_can_view() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! defined( 'DONOTCACHEPAGE' ) ) {
|
||||
define( 'DONOTCACHEPAGE', 1 );
|
||||
}
|
||||
|
||||
add_action( 'send_headers', 'nocache_headers' );
|
||||
}
|
||||
|
||||
protected function before_output() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
protected function after_output() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
public static function user_can_view() {
|
||||
|
||||
if ( ! did_action( 'plugins_loaded' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( current_user_can( 'view_query_monitor' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return self::user_verified();
|
||||
|
||||
}
|
||||
|
||||
public static function user_verified() {
|
||||
if ( isset( $_COOKIE[QM_COOKIE] ) ) { // phpcs:ignore
|
||||
return self::verify_cookie( wp_unslash( $_COOKIE[QM_COOKIE] ) ); // phpcs:ignore
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function editor_cookie() {
|
||||
if ( defined( 'QM_EDITOR_COOKIE' ) && isset( $_COOKIE[QM_EDITOR_COOKIE] ) ) { // phpcs:ignore
|
||||
return $_COOKIE[QM_EDITOR_COOKIE]; // phpcs:ignore
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function verify_cookie( $value ) {
|
||||
$old_user_id = wp_validate_auth_cookie( $value, 'logged_in' );
|
||||
if ( $old_user_id ) {
|
||||
return user_can( $old_user_id, 'view_query_monitor' );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
40
wordpress_plugins/query-monitor/classes/Dispatchers.php
Normal file
40
wordpress_plugins/query-monitor/classes/Dispatchers.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Container for dispatchers.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
class QM_Dispatchers implements IteratorAggregate {
|
||||
|
||||
private $items = array();
|
||||
|
||||
public function getIterator() {
|
||||
return new ArrayIterator( $this->items );
|
||||
}
|
||||
|
||||
public static function add( QM_Dispatcher $dispatcher ) {
|
||||
$dispatchers = self::init();
|
||||
$dispatchers->items[ $dispatcher->id ] = $dispatcher;
|
||||
}
|
||||
|
||||
public static function get( $id ) {
|
||||
$dispatchers = self::init();
|
||||
if ( isset( $dispatchers->items[ $id ] ) ) {
|
||||
return $dispatchers->items[ $id ];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function init() {
|
||||
static $instance;
|
||||
|
||||
if ( ! $instance ) {
|
||||
$instance = new QM_Dispatchers();
|
||||
}
|
||||
|
||||
return $instance;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
60
wordpress_plugins/query-monitor/classes/Hook.php
Normal file
60
wordpress_plugins/query-monitor/classes/Hook.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* Hook processor.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
class QM_Hook {
|
||||
|
||||
public static function process( $name, array $wp_filter, $hide_qm = false, $hide_core = false ) {
|
||||
|
||||
$actions = array();
|
||||
$components = array();
|
||||
|
||||
if ( isset( $wp_filter[ $name ] ) ) {
|
||||
|
||||
# http://core.trac.wordpress.org/ticket/17817
|
||||
$action = $wp_filter[ $name ];
|
||||
|
||||
foreach ( $action as $priority => $callbacks ) {
|
||||
|
||||
foreach ( $callbacks as $callback ) {
|
||||
|
||||
$callback = QM_Util::populate_callback( $callback );
|
||||
|
||||
if ( isset( $callback['component'] ) ) {
|
||||
if (
|
||||
( $hide_qm && 'query-monitor' === $callback['component']->context )
|
||||
|| ( $hide_core && 'core' === $callback['component']->context )
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$components[ $callback['component']->name ] = $callback['component']->name;
|
||||
}
|
||||
|
||||
// This isn't used and takes up a ton of memory:
|
||||
unset( $callback['function'] );
|
||||
|
||||
$actions[] = array(
|
||||
'priority' => $priority,
|
||||
'callback' => $callback,
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$parts = array_values( array_filter( preg_split( '#[_/-]#', $name ) ) );
|
||||
|
||||
return array(
|
||||
'name' => $name,
|
||||
'actions' => $actions,
|
||||
'parts' => $parts,
|
||||
'components' => $components,
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
48
wordpress_plugins/query-monitor/classes/Output.php
Normal file
48
wordpress_plugins/query-monitor/classes/Output.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* Abstract output handler.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'QM_Output' ) ) {
|
||||
abstract class QM_Output {
|
||||
|
||||
/**
|
||||
* Collector instance.
|
||||
*
|
||||
* @var QM_Collector Collector.
|
||||
*/
|
||||
protected $collector;
|
||||
|
||||
/**
|
||||
* Timer instance.
|
||||
*
|
||||
* @var QM_Timer Timer.
|
||||
*/
|
||||
protected $timer;
|
||||
|
||||
public function __construct( QM_Collector $collector ) {
|
||||
$this->collector = $collector;
|
||||
}
|
||||
|
||||
abstract public function get_output();
|
||||
|
||||
public function output() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
public function get_collector() {
|
||||
return $this->collector;
|
||||
}
|
||||
|
||||
final public function get_timer() {
|
||||
return $this->timer;
|
||||
}
|
||||
|
||||
final public function set_timer( QM_Timer $timer ) {
|
||||
$this->timer = $timer;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
111
wordpress_plugins/query-monitor/classes/Plugin.php
Normal file
111
wordpress_plugins/query-monitor/classes/Plugin.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/**
|
||||
* Abstract plugin wrapper.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'QM_Plugin' ) ) {
|
||||
abstract class QM_Plugin {
|
||||
|
||||
private $plugin = array();
|
||||
public static $minimum_php_version = '5.3.6';
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*/
|
||||
protected function __construct( $file ) {
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL for for a file/dir within this plugin.
|
||||
*
|
||||
* @param string $file The path within this plugin, e.g. '/js/clever-fx.js'
|
||||
* @return string URL
|
||||
*/
|
||||
final public function plugin_url( $file = '' ) {
|
||||
return $this->_plugin( 'url', $file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filesystem path for a file/dir within this plugin.
|
||||
*
|
||||
* @param string $file The path within this plugin, e.g. '/js/clever-fx.js'
|
||||
* @return string Filesystem path
|
||||
*/
|
||||
final public function plugin_path( $file = '' ) {
|
||||
return $this->_plugin( 'path', $file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a version number for the given plugin file.
|
||||
*
|
||||
* @param string $file The path within this plugin, e.g. '/js/clever-fx.js'
|
||||
* @return string Version
|
||||
*/
|
||||
final public function plugin_ver( $file ) {
|
||||
return filemtime( $this->plugin_path( $file ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current plugin's basename, eg. 'my_plugin/my_plugin.php'.
|
||||
*
|
||||
* @return string Basename
|
||||
*/
|
||||
final public function plugin_base() {
|
||||
return $this->_plugin( 'base' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates and returns the current plugin info.
|
||||
*/
|
||||
final private function _plugin( $item, $file = '' ) {
|
||||
if ( ! array_key_exists( $item, $this->plugin ) ) {
|
||||
switch ( $item ) {
|
||||
case 'url':
|
||||
$this->plugin[ $item ] = plugin_dir_url( $this->file );
|
||||
break;
|
||||
case 'path':
|
||||
$this->plugin[ $item ] = plugin_dir_path( $this->file );
|
||||
break;
|
||||
case 'base':
|
||||
$this->plugin[ $item ] = plugin_basename( $this->file );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $this->plugin[ $item ] . ltrim( $file, '/' );
|
||||
}
|
||||
|
||||
public static function php_version_met() {
|
||||
static $met = null;
|
||||
|
||||
if ( null === $met ) {
|
||||
$met = version_compare( PHP_VERSION, self::$minimum_php_version, '>=' );
|
||||
}
|
||||
|
||||
return $met;
|
||||
}
|
||||
|
||||
public static function php_version_nope() {
|
||||
printf(
|
||||
'<div id="qm-php-nope" class="notice notice-error is-dismissible"><p>%s</p></div>',
|
||||
wp_kses(
|
||||
sprintf(
|
||||
/* translators: 1: Required PHP version number, 2: Current PHP version number, 3: URL of PHP update help page */
|
||||
__( 'The Query Monitor plugin requires PHP version %1$s or higher. This site is running PHP version %2$s. <a href="%3$s">Learn about updating PHP</a>.', 'query-monitor' ),
|
||||
self::$minimum_php_version,
|
||||
PHP_VERSION,
|
||||
'https://wordpress.org/support/update-php/'
|
||||
),
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
110
wordpress_plugins/query-monitor/classes/QM.php
Normal file
110
wordpress_plugins/query-monitor/classes/QM.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/**
|
||||
* A convenience class for wrapping certain user-facing functionality.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
class QM {
|
||||
|
||||
public static function emergency( $message, array $context = array() ) {
|
||||
/**
|
||||
* Fires when an `emergency` level message is logged.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $message The message.
|
||||
* @param array $context The context passed.
|
||||
*/
|
||||
do_action( 'qm/emergency', $message, $context );
|
||||
}
|
||||
|
||||
public static function alert( $message, array $context = array() ) {
|
||||
/**
|
||||
* Fires when an `alert` level message is logged.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $message The message.
|
||||
* @param array $context The context passed.
|
||||
*/
|
||||
do_action( 'qm/alert', $message, $context );
|
||||
}
|
||||
|
||||
public static function critical( $message, array $context = array() ) {
|
||||
/**
|
||||
* Fires when a `critical` level message is logged.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $message The message.
|
||||
* @param array $context The context passed.
|
||||
*/
|
||||
do_action( 'qm/critical', $message, $context );
|
||||
}
|
||||
|
||||
public static function error( $message, array $context = array() ) {
|
||||
/**
|
||||
* Fires when an `error` level message is logged.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $message The message.
|
||||
* @param array $context The context passed.
|
||||
*/
|
||||
do_action( 'qm/error', $message, $context );
|
||||
}
|
||||
|
||||
public static function warning( $message, array $context = array() ) {
|
||||
/**
|
||||
* Fires when a `warning` level message is logged.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $message The message.
|
||||
* @param array $context The context passed.
|
||||
*/
|
||||
do_action( 'qm/warning', $message, $context );
|
||||
}
|
||||
|
||||
public static function notice( $message, array $context = array() ) {
|
||||
/**
|
||||
* Fires when a `notice` level message is logged.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $message The message.
|
||||
* @param array $context The context passed.
|
||||
*/
|
||||
do_action( 'qm/notice', $message, $context );
|
||||
}
|
||||
|
||||
public static function info( $message, array $context = array() ) {
|
||||
/**
|
||||
* Fires when an `info` level message is logged.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $message The message.
|
||||
* @param array $context The context passed.
|
||||
*/
|
||||
do_action( 'qm/info', $message, $context );
|
||||
}
|
||||
|
||||
public static function debug( $message, array $context = array() ) {
|
||||
/**
|
||||
* Fires when a `debug` level message is logged.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*
|
||||
* @param string $message The message.
|
||||
* @param array $context The context passed.
|
||||
*/
|
||||
do_action( 'qm/debug', $message, $context );
|
||||
}
|
||||
|
||||
public static function log( $level, $message, array $context = array() ) {
|
||||
$logger = QM_Collectors::get( 'logger' );
|
||||
$logger->log( $level, $message, $context );
|
||||
}
|
||||
}
|
||||
217
wordpress_plugins/query-monitor/classes/QueryMonitor.php
Normal file
217
wordpress_plugins/query-monitor/classes/QueryMonitor.php
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
/**
|
||||
* The main Query Monitor plugin class.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
class QueryMonitor extends QM_Plugin {
|
||||
|
||||
protected function __construct( $file ) {
|
||||
|
||||
# Actions
|
||||
add_action( 'plugins_loaded', array( $this, 'action_plugins_loaded' ) );
|
||||
add_action( 'init', array( $this, 'action_init' ) );
|
||||
add_action( 'members_register_caps', array( $this, 'action_register_members_caps' ) );
|
||||
add_action( 'members_register_cap_groups', array( $this, 'action_register_members_groups' ) );
|
||||
|
||||
# Filters
|
||||
add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 10, 4 );
|
||||
add_filter( 'ure_built_in_wp_caps', array( $this, 'filter_ure_caps' ) );
|
||||
add_filter( 'ure_capabilities_groups_tree', array( $this, 'filter_ure_groups' ) );
|
||||
add_filter( 'network_admin_plugin_action_links_query-monitor/query-monitor.php', array( $this, 'filter_plugin_action_links' ) );
|
||||
add_filter( 'plugin_action_links_query-monitor/query-monitor.php', array( $this, 'filter_plugin_action_links' ) );
|
||||
|
||||
# Parent setup:
|
||||
parent::__construct( $file );
|
||||
|
||||
# Load and register built-in collectors:
|
||||
$collectors = array();
|
||||
foreach ( glob( $this->plugin_path( 'collectors/*.php' ) ) as $file ) {
|
||||
$key = basename( $file, '.php' );
|
||||
$collectors[ $key ] = $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow filtering of built-in collector files.
|
||||
*
|
||||
* @since 2.14.0
|
||||
*
|
||||
* @param string[] $collectors Array of file paths to be loaded.
|
||||
*/
|
||||
foreach ( apply_filters( 'qm/built-in-collectors', $collectors ) as $file ) {
|
||||
include $file;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function filter_plugin_action_links( array $actions ) {
|
||||
return array_merge( array(
|
||||
'settings' => '<a href="#qm-settings">' . esc_html__( 'Settings', 'query-monitor' ) . '</a>',
|
||||
'add-ons' => '<a href="https://github.com/johnbillion/query-monitor/wiki/Query-Monitor-Add-on-Plugins">' . esc_html__( 'Add-ons', 'query-monitor' ) . '</a>',
|
||||
), $actions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a user's capabilities so they can be altered at runtime.
|
||||
*
|
||||
* This is used to:
|
||||
* - Grant the 'view_query_monitor' capability to the user if they have the ability to manage options.
|
||||
*
|
||||
* This does not get called for Super Admins.
|
||||
*
|
||||
* @param bool[] $user_caps Array of key/value pairs where keys represent a capability name and boolean values
|
||||
* represent whether the user has that capability.
|
||||
* @param string[] $required_caps Required primitive capabilities for the requested capability.
|
||||
* @param array $args {
|
||||
* Arguments that accompany the requested capability check.
|
||||
*
|
||||
* @type string $0 Requested capability.
|
||||
* @type int $1 Concerned user ID.
|
||||
* @type mixed ...$2 Optional second and further parameters.
|
||||
* }
|
||||
* @param WP_User $user Concerned user object.
|
||||
* @return bool[] Concerned user's capabilities.
|
||||
*/
|
||||
public function filter_user_has_cap( array $user_caps, array $required_caps, array $args, WP_User $user ) {
|
||||
if ( 'view_query_monitor' !== $args[0] ) {
|
||||
return $user_caps;
|
||||
}
|
||||
|
||||
if ( array_key_exists( 'view_query_monitor', $user_caps ) ) {
|
||||
return $user_caps;
|
||||
}
|
||||
|
||||
if ( ! is_multisite() && user_can( $args[1], 'manage_options' ) ) {
|
||||
$user_caps['view_query_monitor'] = true;
|
||||
}
|
||||
|
||||
return $user_caps;
|
||||
}
|
||||
|
||||
public function action_plugins_loaded() {
|
||||
// Hide QM itself from output by default:
|
||||
if ( ! defined( 'QM_HIDE_SELF' ) ) {
|
||||
define( 'QM_HIDE_SELF', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the collectors that are being added.
|
||||
*
|
||||
* @since 2.11.2
|
||||
*
|
||||
* @param QM_Collector[] $collectors Array of collector instances.
|
||||
* @param QueryMonitor $instance QueryMonitor instance.
|
||||
*/
|
||||
foreach ( apply_filters( 'qm/collectors', array(), $this ) as $collector ) {
|
||||
QM_Collectors::add( $collector );
|
||||
}
|
||||
|
||||
# Load dispatchers:
|
||||
foreach ( glob( $this->plugin_path( 'dispatchers/*.php' ) ) as $file ) {
|
||||
include $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the dispatchers that are being added.
|
||||
*
|
||||
* @since 2.11.2
|
||||
*
|
||||
* @param QM_Dispatcher[] $dispatchers Array of dispatcher instances.
|
||||
* @param QueryMonitor $instance QueryMonitor instance.
|
||||
*/
|
||||
foreach ( apply_filters( 'qm/dispatchers', array(), $this ) as $dispatcher ) {
|
||||
QM_Dispatchers::add( $dispatcher );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function action_init() {
|
||||
load_plugin_textdomain( 'query-monitor', false, dirname( $this->plugin_base() ) . '/languages' );
|
||||
}
|
||||
|
||||
public static function symlink_warning() {
|
||||
$db = WP_CONTENT_DIR . '/db.php';
|
||||
trigger_error( sprintf(
|
||||
/* translators: %s: Symlink file location */
|
||||
esc_html__( 'The symlink at %s is no longer pointing to the correct location. Please remove the symlink, then deactivate and reactivate Query Monitor.', 'query-monitor' ),
|
||||
'<code>' . esc_html( $db ) . '</code>'
|
||||
), E_USER_WARNING );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the Query Monitor user capability group for the Members plugin.
|
||||
*
|
||||
* @link https://wordpress.org/plugins/members/
|
||||
*/
|
||||
public function action_register_members_groups() {
|
||||
members_register_cap_group( 'query_monitor', array(
|
||||
'label' => __( 'Query Monitor', 'query-monitor' ),
|
||||
'caps' => array(
|
||||
'view_query_monitor',
|
||||
),
|
||||
'icon' => 'dashicons-admin-tools',
|
||||
'priority' => 30,
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the View Query Monitor user capability for the Members plugin.
|
||||
*
|
||||
* @link https://wordpress.org/plugins/members/
|
||||
*/
|
||||
public function action_register_members_caps() {
|
||||
members_register_cap( 'view_query_monitor', array(
|
||||
'label' => _x( 'View Query Monitor', 'Human readable label for the user capability required to view Query Monitor.', 'query-monitor' ),
|
||||
'group' => 'query_monitor',
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the Query Monitor user capability group for the User Role Editor plugin.
|
||||
*
|
||||
* @link https://wordpress.org/plugins/user-role-editor/
|
||||
*
|
||||
* @param array[] $groups Array of existing groups.
|
||||
* @return array[] Updated array of groups.
|
||||
*/
|
||||
public function filter_ure_groups( array $groups ) {
|
||||
$groups['query_monitor'] = array(
|
||||
'caption' => esc_html__( 'Query Monitor', 'query-monitor' ),
|
||||
'parent' => 'custom',
|
||||
'level' => 2,
|
||||
);
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the View Query Monitor user capability for the User Role Editor plugin.
|
||||
*
|
||||
* @link https://wordpress.org/plugins/user-role-editor/
|
||||
*
|
||||
* @param array[] $caps Array of existing capabilities.
|
||||
* @return array[] Updated array of capabilities.
|
||||
*/
|
||||
public function filter_ure_caps( array $caps ) {
|
||||
$caps['view_query_monitor'] = array(
|
||||
'custom',
|
||||
'query_monitor',
|
||||
);
|
||||
|
||||
return $caps;
|
||||
}
|
||||
|
||||
public static function init( $file = null ) {
|
||||
|
||||
static $instance = null;
|
||||
|
||||
if ( ! $instance ) {
|
||||
$instance = new QueryMonitor( $file );
|
||||
}
|
||||
|
||||
return $instance;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
109
wordpress_plugins/query-monitor/classes/Timer.php
Normal file
109
wordpress_plugins/query-monitor/classes/Timer.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/**
|
||||
* Timer that collects timing and memory usage.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
class QM_Timer {
|
||||
|
||||
protected $start = null;
|
||||
protected $end = null;
|
||||
protected $trace = null;
|
||||
protected $laps = array();
|
||||
|
||||
public function start( array $data = null ) {
|
||||
$this->trace = new QM_Backtrace();
|
||||
$this->start = array(
|
||||
'time' => microtime( true ),
|
||||
'memory' => memory_get_usage(),
|
||||
'data' => $data,
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function stop( array $data = null ) {
|
||||
|
||||
$this->end = array(
|
||||
'time' => microtime( true ),
|
||||
'memory' => memory_get_usage(),
|
||||
'data' => $data,
|
||||
);
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function lap( array $data = null, $name = null ) {
|
||||
|
||||
$lap = array(
|
||||
'time' => microtime( true ),
|
||||
'memory' => memory_get_usage(),
|
||||
'data' => $data,
|
||||
);
|
||||
|
||||
if ( ! isset( $name ) ) {
|
||||
/* translators: %d: Timing lap number */
|
||||
$i = sprintf( __( 'Lap %d', 'query-monitor' ), count( $this->laps ) + 1 );
|
||||
} else {
|
||||
$i = $name;
|
||||
}
|
||||
|
||||
$this->laps[ $i ] = $lap;
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function get_laps() {
|
||||
|
||||
$laps = array();
|
||||
$prev = $this->start;
|
||||
|
||||
foreach ( $this->laps as $lap_id => $lap ) {
|
||||
|
||||
$lap['time_used'] = $lap['time'] - $prev['time'];
|
||||
$lap['memory_used'] = $lap['memory'] - $prev['memory'];
|
||||
|
||||
$laps[ $lap_id ] = $lap;
|
||||
$prev = $lap;
|
||||
|
||||
}
|
||||
|
||||
return $laps;
|
||||
|
||||
}
|
||||
|
||||
public function get_time() {
|
||||
return $this->end['time'] - $this->start['time'];
|
||||
}
|
||||
|
||||
public function get_memory() {
|
||||
return $this->end['memory'] - $this->start['memory'];
|
||||
}
|
||||
|
||||
public function get_start_time() {
|
||||
return $this->start['time'];
|
||||
}
|
||||
|
||||
public function get_start_memory() {
|
||||
return $this->start['memory'];
|
||||
}
|
||||
|
||||
public function get_end_time() {
|
||||
return $this->end['time'];
|
||||
}
|
||||
|
||||
public function get_end_memory() {
|
||||
return $this->end['memory'];
|
||||
}
|
||||
|
||||
public function get_trace() {
|
||||
return $this->trace;
|
||||
}
|
||||
|
||||
public function end( array $data = null ) {
|
||||
return $this->stop( $data );
|
||||
}
|
||||
|
||||
}
|
||||
518
wordpress_plugins/query-monitor/classes/Util.php
Normal file
518
wordpress_plugins/query-monitor/classes/Util.php
Normal file
@@ -0,0 +1,518 @@
|
||||
<?php
|
||||
/**
|
||||
* General utilities class.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'QM_Util' ) ) {
|
||||
class QM_Util {
|
||||
|
||||
protected static $file_components = array();
|
||||
protected static $file_dirs = array();
|
||||
protected static $abspath = null;
|
||||
protected static $contentpath = null;
|
||||
protected static $sort_field = null;
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
public static function convert_hr_to_bytes( $size ) {
|
||||
|
||||
# Annoyingly, wp_convert_hr_to_bytes() is defined in a file that's only
|
||||
# loaded in the admin area, so we'll use our own version.
|
||||
# See also http://core.trac.wordpress.org/ticket/17725
|
||||
|
||||
$bytes = (float) $size;
|
||||
|
||||
if ( $bytes ) {
|
||||
$last = strtolower( substr( $size, -1 ) );
|
||||
$pos = strpos( ' kmg', $last, 1 );
|
||||
if ( $pos ) {
|
||||
$bytes *= pow( 1024, $pos );
|
||||
}
|
||||
$bytes = round( $bytes );
|
||||
}
|
||||
|
||||
return $bytes;
|
||||
|
||||
}
|
||||
|
||||
public static function standard_dir( $dir, $path_replace = null ) {
|
||||
|
||||
$dir = self::normalize_path( $dir );
|
||||
|
||||
if ( is_string( $path_replace ) ) {
|
||||
if ( ! self::$abspath ) {
|
||||
self::$abspath = self::normalize_path( ABSPATH );
|
||||
self::$contentpath = self::normalize_path( dirname( WP_CONTENT_DIR ) . '/' );
|
||||
}
|
||||
$dir = str_replace( array(
|
||||
self::$abspath,
|
||||
self::$contentpath,
|
||||
), $path_replace, $dir );
|
||||
}
|
||||
|
||||
return $dir;
|
||||
|
||||
}
|
||||
|
||||
public static function normalize_path( $path ) {
|
||||
if ( function_exists( 'wp_normalize_path' ) ) {
|
||||
$path = wp_normalize_path( $path );
|
||||
} else {
|
||||
$path = str_replace( '\\', '/', $path );
|
||||
$path = str_replace( '//', '/', $path );
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
public static function get_file_dirs() {
|
||||
if ( empty( self::$file_dirs ) ) {
|
||||
|
||||
/**
|
||||
* Filters the absolute directory paths that correlate to components.
|
||||
*
|
||||
* Note that this filter is applied before QM adds its built-in list of components. This is
|
||||
* so custom registered components take precedence during component detection.
|
||||
*
|
||||
* See the corresponding `qm/component_name/{$type}` filter for specifying the component name.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*
|
||||
* @param string[] $dirs Array of absolute directory paths keyed by component identifier.
|
||||
*/
|
||||
self::$file_dirs = apply_filters( 'qm/component_dirs', self::$file_dirs );
|
||||
|
||||
self::$file_dirs['plugin'] = WP_PLUGIN_DIR;
|
||||
self::$file_dirs['mu-vendor'] = WPMU_PLUGIN_DIR . '/vendor';
|
||||
self::$file_dirs['go-plugin'] = WPMU_PLUGIN_DIR . '/shared-plugins';
|
||||
self::$file_dirs['mu-plugin'] = WPMU_PLUGIN_DIR;
|
||||
self::$file_dirs['vip-plugin'] = get_theme_root() . '/vip/plugins';
|
||||
|
||||
if ( defined( 'WPCOM_VIP_CLIENT_MU_PLUGIN_DIR' ) ) {
|
||||
self::$file_dirs['vip-client-mu-plugin'] = WPCOM_VIP_CLIENT_MU_PLUGIN_DIR;
|
||||
}
|
||||
|
||||
self::$file_dirs['theme'] = null;
|
||||
self::$file_dirs['stylesheet'] = get_stylesheet_directory();
|
||||
self::$file_dirs['template'] = get_template_directory();
|
||||
self::$file_dirs['other'] = WP_CONTENT_DIR;
|
||||
self::$file_dirs['core'] = ABSPATH;
|
||||
self::$file_dirs['unknown'] = null;
|
||||
|
||||
foreach ( self::$file_dirs as $type => $dir ) {
|
||||
self::$file_dirs[ $type ] = self::standard_dir( $dir );
|
||||
}
|
||||
}
|
||||
|
||||
return self::$file_dirs;
|
||||
}
|
||||
|
||||
public static function get_file_component( $file ) {
|
||||
|
||||
# @TODO turn this into a class (eg QM_File_Component)
|
||||
|
||||
$file = self::standard_dir( $file );
|
||||
|
||||
if ( isset( self::$file_components[ $file ] ) ) {
|
||||
return self::$file_components[ $file ];
|
||||
}
|
||||
|
||||
foreach ( self::get_file_dirs() as $type => $dir ) {
|
||||
// this slash makes paths such as plugins-mu match mu-plugin not plugin
|
||||
if ( $dir && ( 0 === strpos( $file, trailingslashit( $dir ) ) ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$context = $type;
|
||||
|
||||
switch ( $type ) {
|
||||
case 'plugin':
|
||||
case 'mu-plugin':
|
||||
case 'mu-vendor':
|
||||
$plug = str_replace( '/vendor/', '/', $file );
|
||||
$plug = plugin_basename( $plug );
|
||||
if ( strpos( $plug, '/' ) ) {
|
||||
$plug = explode( '/', $plug );
|
||||
$plug = reset( $plug );
|
||||
} else {
|
||||
$plug = basename( $plug );
|
||||
}
|
||||
if ( 'plugin' !== $type ) {
|
||||
/* translators: %s: Plugin name */
|
||||
$name = sprintf( __( 'MU Plugin: %s', 'query-monitor' ), $plug );
|
||||
} else {
|
||||
/* translators: %s: Plugin name */
|
||||
$name = sprintf( __( 'Plugin: %s', 'query-monitor' ), $plug );
|
||||
}
|
||||
$context = $plug;
|
||||
break;
|
||||
case 'go-plugin':
|
||||
case 'vip-plugin':
|
||||
case 'vip-client-mu-plugin':
|
||||
$plug = str_replace( self::$file_dirs[ $type ], '', $file );
|
||||
$plug = trim( $plug, '/' );
|
||||
if ( strpos( $plug, '/' ) ) {
|
||||
$plug = explode( '/', $plug );
|
||||
$plug = reset( $plug );
|
||||
} else {
|
||||
$plug = basename( $plug );
|
||||
}
|
||||
if ( 'vip-client-mu-plugin' === $type ) {
|
||||
/* translators: %s: Plugin name */
|
||||
$name = sprintf( __( 'VIP Client MU Plugin: %s', 'query-monitor' ), $plug );
|
||||
} else {
|
||||
/* translators: %s: Plugin name */
|
||||
$name = sprintf( __( 'VIP Plugin: %s', 'query-monitor' ), $plug );
|
||||
}
|
||||
$context = $plug;
|
||||
break;
|
||||
case 'stylesheet':
|
||||
if ( is_child_theme() ) {
|
||||
$name = __( 'Child Theme', 'query-monitor' );
|
||||
} else {
|
||||
$name = __( 'Theme', 'query-monitor' );
|
||||
}
|
||||
$type = 'theme';
|
||||
break;
|
||||
case 'template':
|
||||
$name = __( 'Parent Theme', 'query-monitor' );
|
||||
$type = 'theme';
|
||||
break;
|
||||
case 'other':
|
||||
// Anything else that's within the content directory should appear as
|
||||
// `wp-content/{dir}` or `wp-content/{file}`
|
||||
$name = self::standard_dir( $file );
|
||||
$name = str_replace( dirname( self::$file_dirs['other'] ), '', $name );
|
||||
$parts = explode( '/', trim( $name, '/' ) );
|
||||
$name = $parts[0] . '/' . $parts[1];
|
||||
$context = $file;
|
||||
break;
|
||||
case 'core':
|
||||
$name = __( 'Core', 'query-monitor' );
|
||||
break;
|
||||
case 'unknown':
|
||||
default:
|
||||
$name = __( 'Unknown', 'query-monitor' );
|
||||
|
||||
/**
|
||||
* Filters the name of a custom or unknown component.
|
||||
*
|
||||
* The dynamic portion of the hook name, `$type`, refers to the component identifier.
|
||||
*
|
||||
* See the corresponding `qm/component_dirs` filter for specifying the component directories.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*
|
||||
* @param string $name The component name.
|
||||
* @param string $file The full file path for the file within the component.
|
||||
*/
|
||||
$name = apply_filters( "qm/component_name/{$type}", $name, $file );
|
||||
break;
|
||||
}
|
||||
|
||||
self::$file_components[ $file ] = (object) compact( 'type', 'name', 'context' );
|
||||
|
||||
return self::$file_components[ $file ];
|
||||
}
|
||||
|
||||
public static function populate_callback( array $callback ) {
|
||||
|
||||
if ( is_string( $callback['function'] ) && ( false !== strpos( $callback['function'], '::' ) ) ) {
|
||||
$callback['function'] = explode( '::', $callback['function'] );
|
||||
}
|
||||
|
||||
if ( isset( $callback['class'] ) ) {
|
||||
$callback['function'] = array(
|
||||
$callback['class'],
|
||||
$callback['function'],
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if ( is_array( $callback['function'] ) ) {
|
||||
if ( is_object( $callback['function'][0] ) ) {
|
||||
$class = get_class( $callback['function'][0] );
|
||||
$access = '->';
|
||||
} else {
|
||||
$class = $callback['function'][0];
|
||||
$access = '::';
|
||||
}
|
||||
|
||||
$callback['name'] = self::shorten_fqn( $class . $access . $callback['function'][1] ) . '()';
|
||||
$ref = new ReflectionMethod( $class, $callback['function'][1] );
|
||||
} elseif ( is_object( $callback['function'] ) ) {
|
||||
if ( is_a( $callback['function'], 'Closure' ) ) {
|
||||
$ref = new ReflectionFunction( $callback['function'] );
|
||||
$file = self::standard_dir( $ref->getFileName(), '' );
|
||||
if ( 0 === strpos( $file, '/' ) ) {
|
||||
$file = basename( $ref->getFileName() );
|
||||
}
|
||||
/* translators: 1: Line number, 2: File name */
|
||||
$callback['name'] = sprintf( __( 'Closure on line %1$d of %2$s', 'query-monitor' ), $ref->getStartLine(), $file );
|
||||
} else {
|
||||
// the object should have a __invoke() method
|
||||
$class = get_class( $callback['function'] );
|
||||
$callback['name'] = self::shorten_fqn( $class ) . '->__invoke()';
|
||||
$ref = new ReflectionMethod( $class, '__invoke' );
|
||||
}
|
||||
} else {
|
||||
$callback['name'] = self::shorten_fqn( $callback['function'] ) . '()';
|
||||
$ref = new ReflectionFunction( $callback['function'] );
|
||||
}
|
||||
|
||||
$callback['file'] = $ref->getFileName();
|
||||
$callback['line'] = $ref->getStartLine();
|
||||
|
||||
// https://github.com/facebook/hhvm/issues/5856
|
||||
$name = trim( $ref->getName() );
|
||||
|
||||
if ( '__lambda_func' === $name || 0 === strpos( $name, 'lambda_' ) ) {
|
||||
if ( preg_match( '|(?P<file>.*)\((?P<line>[0-9]+)\)|', $callback['file'], $matches ) ) {
|
||||
$callback['file'] = $matches['file'];
|
||||
$callback['line'] = $matches['line'];
|
||||
$file = trim( self::standard_dir( $callback['file'], '' ), '/' );
|
||||
/* translators: 1: Line number, 2: File name */
|
||||
$callback['name'] = sprintf( __( 'Anonymous function on line %1$d of %2$s', 'query-monitor' ), $callback['line'], $file );
|
||||
} else {
|
||||
// https://github.com/facebook/hhvm/issues/5807
|
||||
unset( $callback['line'], $callback['file'] );
|
||||
$callback['name'] = $name . '()';
|
||||
$callback['error'] = new WP_Error( 'unknown_lambda', __( 'Unable to determine source of lambda function', 'query-monitor' ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $callback['file'] ) ) {
|
||||
$callback['component'] = self::get_file_component( $callback['file'] );
|
||||
} else {
|
||||
$callback['component'] = (object) array(
|
||||
'type' => 'php',
|
||||
'name' => 'PHP',
|
||||
'context' => '',
|
||||
);
|
||||
}
|
||||
} catch ( ReflectionException $e ) {
|
||||
|
||||
$callback['error'] = new WP_Error( 'reflection_exception', $e->getMessage() );
|
||||
|
||||
}
|
||||
|
||||
return $callback;
|
||||
|
||||
}
|
||||
|
||||
public static function is_ajax() {
|
||||
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function is_async() {
|
||||
if ( self::is_ajax() ) {
|
||||
return true;
|
||||
}
|
||||
if ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && 'xmlhttprequest' === strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) ) { // phpcs:ignore
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function get_admins() {
|
||||
if ( is_multisite() ) {
|
||||
return false;
|
||||
} else {
|
||||
return get_role( 'administrator' );
|
||||
}
|
||||
}
|
||||
|
||||
public static function is_multi_network() {
|
||||
global $wpdb;
|
||||
|
||||
if ( function_exists( 'is_multi_network' ) ) {
|
||||
return is_multi_network();
|
||||
}
|
||||
|
||||
if ( ! is_multisite() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// phpcs:disable
|
||||
$num_sites = $wpdb->get_var( "
|
||||
SELECT COUNT(*)
|
||||
FROM {$wpdb->site}
|
||||
" );
|
||||
// phpcs:enable
|
||||
|
||||
return ( $num_sites > 1 );
|
||||
}
|
||||
|
||||
public static function get_client_version( $client ) {
|
||||
|
||||
$client = intval( $client );
|
||||
|
||||
$hello = $client % 10000;
|
||||
|
||||
$major = intval( floor( $client / 10000 ) );
|
||||
$minor = intval( floor( $hello / 100 ) );
|
||||
$patch = intval( $hello % 100 );
|
||||
|
||||
return compact( 'major', 'minor', 'patch' );
|
||||
|
||||
}
|
||||
|
||||
public static function get_query_type( $sql ) {
|
||||
// Trim leading whitespace and brackets
|
||||
$sql = ltrim( $sql, ' \t\n\r\0\x0B(' );
|
||||
|
||||
if ( 0 === strpos( $sql, '/*' ) ) {
|
||||
// Strip out leading comments such as `/*NO_SELECT_FOUND_ROWS*/` before calculating the query type
|
||||
$sql = preg_replace( '|^/\*[^\*/]+\*/|', '', $sql );
|
||||
}
|
||||
|
||||
$words = preg_split( '/\b/', trim( $sql ), 2, PREG_SPLIT_NO_EMPTY );
|
||||
$type = strtoupper( $words[0] );
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
public static function display_variable( $value ) {
|
||||
if ( is_string( $value ) ) {
|
||||
return $value;
|
||||
} elseif ( is_bool( $value ) ) {
|
||||
return ( $value ) ? 'true' : 'false';
|
||||
} elseif ( is_scalar( $value ) ) {
|
||||
return $value;
|
||||
} elseif ( is_object( $value ) ) {
|
||||
$class = get_class( $value );
|
||||
|
||||
switch ( true ) {
|
||||
|
||||
case ( $value instanceof WP_Post ):
|
||||
case ( $value instanceof WP_User ):
|
||||
return sprintf( '%s (ID: %s)', $class, $value->ID );
|
||||
break;
|
||||
|
||||
case ( $value instanceof WP_Term ):
|
||||
return sprintf( '%s (term_id: %s)', $class, $value->term_id );
|
||||
break;
|
||||
|
||||
case ( $value instanceof WP_Comment ):
|
||||
return sprintf( '%s (comment_ID: %s)', $class, $value->comment_ID );
|
||||
break;
|
||||
|
||||
case ( $value instanceof WP_Error ):
|
||||
return sprintf( '%s (%s)', $class, $value->get_error_code() );
|
||||
break;
|
||||
|
||||
case ( $value instanceof WP_Role ):
|
||||
case ( $value instanceof WP_Post_Type ):
|
||||
case ( $value instanceof WP_Taxonomy ):
|
||||
return sprintf( '%s (%s)', $class, $value->name );
|
||||
break;
|
||||
|
||||
case ( $value instanceof WP_Network ):
|
||||
return sprintf( '%s (id: %s)', $class, $value->id );
|
||||
break;
|
||||
|
||||
case ( $value instanceof WP_Site ):
|
||||
return sprintf( '%s (blog_id: %s)', $class, $value->blog_id );
|
||||
break;
|
||||
|
||||
case ( $value instanceof WP_Theme ):
|
||||
return sprintf( '%s (%s)', $class, $value->get_stylesheet() );
|
||||
break;
|
||||
|
||||
default:
|
||||
return $class;
|
||||
break;
|
||||
|
||||
}
|
||||
} else {
|
||||
return gettype( $value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortens a fully qualified name to reduce the length of the names of long namespaced symbols.
|
||||
*
|
||||
* This initialises portions that do not form the first or last portion of the name. For example:
|
||||
*
|
||||
* Inpsyde\Wonolog\HookListener\HookListenersRegistry->hook_callback()
|
||||
*
|
||||
* becomes:
|
||||
*
|
||||
* Inpsyde\W\H\HookListenersRegistry->hook_callback()
|
||||
*
|
||||
* @param string $fqn A fully qualified name.
|
||||
* @return string A shortened version of the name.
|
||||
*/
|
||||
public static function shorten_fqn( $fqn ) {
|
||||
return preg_replace_callback( '#\\\\[a-zA-Z0-9_\\\\]{4,}\\\\#', function( array $matches ) {
|
||||
preg_match_all( '#\\\\([a-zA-Z0-9_])#', $matches[0], $m );
|
||||
return '\\' . implode( '\\', $m[1] ) . '\\';
|
||||
}, $fqn );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for JSON encoding data and formatting it in a consistent and compatible manner.
|
||||
*
|
||||
* @param mixed $data The data to be JSON encoded.
|
||||
* @return string The JSON encoded data.
|
||||
*/
|
||||
public static function json_format( $data ) {
|
||||
$json_options = JSON_PRETTY_PRINT;
|
||||
|
||||
if ( defined( 'JSON_UNESCAPED_SLASHES' ) ) {
|
||||
// phpcs:ignore PHPCompatibility.Constants.NewConstants.json_unescaped_slashesFound
|
||||
$json_options |= JSON_UNESCAPED_SLASHES;
|
||||
}
|
||||
|
||||
$json = json_encode( $data, $json_options );
|
||||
|
||||
if ( ! defined( 'JSON_UNESCAPED_SLASHES' ) ) {
|
||||
$json = wp_unslash( $json );
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
public static function is_stringy( $data ) {
|
||||
return ( is_string( $data ) || ( is_object( $data ) && method_exists( $data, '__toString' ) ) );
|
||||
}
|
||||
|
||||
public static function sort( array &$array, $field ) {
|
||||
self::$sort_field = $field;
|
||||
usort( $array, array( __CLASS__, '_sort' ) );
|
||||
}
|
||||
|
||||
public static function rsort( array &$array, $field ) {
|
||||
self::$sort_field = $field;
|
||||
usort( $array, array( __CLASS__, '_rsort' ) );
|
||||
}
|
||||
|
||||
private static function _rsort( $a, $b ) {
|
||||
$field = self::$sort_field;
|
||||
|
||||
if ( $a[ $field ] === $b[ $field ] ) {
|
||||
return 0;
|
||||
} else {
|
||||
return ( $a[ $field ] > $b[ $field ] ) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static function _sort( $a, $b ) {
|
||||
$field = self::$sort_field;
|
||||
|
||||
if ( $a[ $field ] === $b[ $field ] ) {
|
||||
return 0;
|
||||
} else {
|
||||
return ( $a[ $field ] > $b[ $field ] ) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
65
wordpress_plugins/query-monitor/classes/debug_bar.php
Normal file
65
wordpress_plugins/query-monitor/classes/debug_bar.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* Mock 'Debug Bar' plugin class.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
class Debug_Bar {
|
||||
public $panels = array();
|
||||
|
||||
public function __construct() {
|
||||
add_action( 'wp_head', array( $this, 'ensure_ajaxurl' ), 1 );
|
||||
|
||||
$this->enqueue();
|
||||
$this->init_panels();
|
||||
}
|
||||
|
||||
public function enqueue() {
|
||||
// phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
|
||||
wp_register_style( 'debug-bar', false, array(
|
||||
'query-monitor',
|
||||
) );
|
||||
// phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
|
||||
wp_register_script( 'debug-bar', false, array(
|
||||
'query-monitor',
|
||||
) );
|
||||
|
||||
/**
|
||||
* Fires after scripts have been enqueued. This mimics the same action fired in the Debug Bar plugin.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
do_action( 'debug_bar_enqueue_scripts' );
|
||||
}
|
||||
|
||||
public function init_panels() {
|
||||
require_once 'debug_bar_panel.php';
|
||||
|
||||
/**
|
||||
* Filters the debug bar panel list. This mimics the same filter called in the Debug Bar plugin.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @param Debug_Bar_Panel[] $panels Array of Debug Bar panel instances.
|
||||
*/
|
||||
$this->panels = apply_filters( 'debug_bar_panels', array() );
|
||||
}
|
||||
|
||||
public function ensure_ajaxurl() {
|
||||
$dispatcher = QM_Dispatchers::get( 'html' );
|
||||
|
||||
if ( $this->panels && $dispatcher::user_can_view() ) {
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
var ajaxurl = '<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>';
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
public function Debug_Bar() {
|
||||
self::__construct();
|
||||
}
|
||||
|
||||
}
|
||||
60
wordpress_plugins/query-monitor/classes/debug_bar_panel.php
Normal file
60
wordpress_plugins/query-monitor/classes/debug_bar_panel.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* Mock 'Debug Bar' panel class.
|
||||
*
|
||||
* @package query-monitor
|
||||
*/
|
||||
|
||||
abstract class Debug_Bar_Panel {
|
||||
|
||||
public $_title = '';
|
||||
public $_visible = true;
|
||||
|
||||
public function __construct( $title = '' ) {
|
||||
$this->title( $title );
|
||||
|
||||
if ( $this->init() === false ) {
|
||||
$this->set_visible( false );
|
||||
return;
|
||||
}
|
||||
|
||||
# @TODO convert to QM classes
|
||||
add_filter( 'debug_bar_classes', array( $this, 'debug_bar_classes' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the panel.
|
||||
*/
|
||||
public function init() {}
|
||||
|
||||
public function prerender() {}
|
||||
|
||||
/**
|
||||
* Renders the panel.
|
||||
*/
|
||||
public function render() {}
|
||||
|
||||
public function is_visible() {
|
||||
return $this->_visible;
|
||||
}
|
||||
|
||||
public function set_visible( $visible ) {
|
||||
$this->_visible = $visible;
|
||||
}
|
||||
|
||||
public function title( $title = null ) {
|
||||
if ( ! isset( $title ) ) {
|
||||
return $this->_title;
|
||||
}
|
||||
$this->_title = $title;
|
||||
}
|
||||
|
||||
public function debug_bar_classes( $classes ) {
|
||||
return $classes;
|
||||
}
|
||||
|
||||
public function Debug_Bar_Panel( $title = '' ) {
|
||||
self::__construct( $title );
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user