2016-10-08 06:37:41 -07:00
< ? php
namespace runcommand\Profile ;
use WP_CLI ;
class Profiler {
private $type ;
private $focus ;
2018-08-10 19:18:48 +02:00
private $loggers = array ();
private $stage_hooks = array (
'bootstrap' => array (
2016-10-08 06:37:41 -07:00
'muplugins_loaded' ,
'plugins_loaded' ,
'setup_theme' ,
'after_setup_theme' ,
'init' ,
'wp_loaded' ,
),
2018-08-10 19:18:48 +02:00
'main_query' => array (
2016-10-08 06:37:41 -07:00
'parse_request' ,
'send_headers' ,
'pre_get_posts' ,
'the_posts' ,
'wp' ,
),
2018-08-10 19:18:48 +02:00
'template' => array (
2016-10-08 06:37:41 -07:00
'template_redirect' ,
'template_include' ,
'wp_head' ,
'loop_start' ,
'loop_end' ,
'wp_footer' ,
),
);
2018-08-10 19:18:48 +02:00
private $current_stage_hooks = array ();
private $running_hook = null ;
private $previous_filter = null ;
2016-10-08 06:37:41 -07:00
private $previous_filter_callbacks = null ;
2018-08-10 19:18:48 +02:00
private $filter_depth = 0 ;
2016-10-08 06:37:41 -07:00
2018-08-10 19:18:48 +02:00
private $tick_callback = null ;
private $tick_location = null ;
private $tick_start_time = null ;
private $tick_query_offset = null ;
private $tick_cache_hit_offset = null ;
2016-10-09 10:33:48 -07:00
private $tick_cache_miss_offset = null ;
2016-10-08 06:37:41 -07:00
public function __construct ( $type , $focus ) {
2018-08-10 19:18:48 +02:00
$this -> type = $type ;
2016-10-08 06:37:41 -07:00
$this -> focus = $focus ;
}
public function get_loggers () {
2018-08-10 19:18:48 +02:00
foreach ( $this -> loggers as $i => $logger ) {
2016-10-09 16:15:16 -07:00
if ( is_array ( $logger ) ) {
$this -> loggers [ $i ] = $logger = new Logger ( $logger );
}
if ( ! isset ( $logger -> callback ) ) {
continue ;
}
if ( ! isset ( $logger -> location ) ) {
list ( $name , $location ) = self :: get_name_location_from_callback ( $logger -> callback );
2018-08-10 19:18:48 +02:00
$logger -> callback = $name ;
$logger -> location = $location ;
2016-10-09 16:15:16 -07:00
}
2018-08-10 19:18:48 +02:00
$logger -> location = self :: get_short_location ( $logger -> location );
2016-10-09 16:15:16 -07:00
$this -> loggers [ $i ] = $logger ;
}
2016-10-08 06:37:41 -07:00
return $this -> loggers ;
}
/**
* Run the profiler against WordPress
*/
public function run () {
2018-08-10 19:18:48 +02:00
WP_CLI :: add_wp_hook (
'muplugins_loaded' , function () {
if ( $url = WP_CLI :: get_runner () -> config [ 'url' ] ) {
WP_CLI :: set_url ( trailingslashit ( $url ) );
} else {
WP_CLI :: set_url ( home_url ( '/' ) );
}
2016-10-08 06:37:41 -07:00
}
2018-08-10 19:18:48 +02:00
);
WP_CLI :: add_hook (
'after_wp_config_load' , function () {
if ( defined ( 'SAVEQUERIES' ) && ! SAVEQUERIES ) {
WP_CLI :: error ( " 'SAVEQUERIES' is defined as false, and must be true. Please check your wp-config.php " );
}
if ( ! defined ( 'SAVEQUERIES' ) ) {
define ( 'SAVEQUERIES' , true );
}
2016-10-08 06:37:41 -07:00
}
2018-08-10 19:18:48 +02:00
);
2016-10-09 15:43:02 -07:00
if ( 'hook' === $this -> type
&& ':before' === substr ( $this -> focus , - 7 , 7 ) ) {
$stage_hooks = array ();
2018-08-10 19:18:48 +02:00
foreach ( $this -> stage_hooks as $hooks ) {
2016-10-09 15:43:02 -07:00
$stage_hooks = array_merge ( $stage_hooks , $hooks );
}
$end_hook = substr ( $this -> focus , 0 , - 7 );
2018-08-10 19:18:48 +02:00
$key = array_search ( $end_hook , $stage_hooks );
2016-10-19 04:56:53 -07:00
if ( isset ( $stage_hooks [ $key - 1 ] ) ) {
$start_hook = $stage_hooks [ $key - 1 ];
WP_CLI :: add_wp_hook ( $start_hook , array ( $this , 'wp_tick_profile_begin' ), 9999 );
} else {
WP_CLI :: add_hook ( 'after_wp_config_load' , array ( $this , 'wp_tick_profile_begin' ) );
}
2016-10-09 15:43:02 -07:00
WP_CLI :: add_wp_hook ( $end_hook , array ( $this , 'wp_tick_profile_end' ), - 9999 );
2018-08-10 19:18:48 +02:00
} elseif ( 'hook' === $this -> type
2016-10-26 06:54:43 -07:00
&& ':after' === substr ( $this -> focus , - 6 , 6 ) ) {
$start_hook = substr ( $this -> focus , 0 , - 6 );
WP_CLI :: add_wp_hook ( $start_hook , array ( $this , 'wp_tick_profile_begin' ), 9999 );
2016-10-09 15:43:02 -07:00
} else {
WP_CLI :: add_wp_hook ( 'all' , array ( $this , 'wp_hook_begin' ) );
}
2016-10-08 06:37:41 -07:00
WP_CLI :: add_wp_hook ( 'pre_http_request' , array ( $this , 'wp_request_begin' ) );
WP_CLI :: add_wp_hook ( 'http_api_debug' , array ( $this , 'wp_request_end' ) );
$this -> load_wordpress_with_template ();
2016-10-09 15:43:02 -07:00
}
/**
* Start profiling function calls on the end of this filter
*/
public function wp_tick_profile_begin ( $value = null ) {
2016-10-19 18:14:28 -07:00
2016-11-15 08:06:31 -08:00
if ( version_compare ( PHP_VERSION , '7.0.0' ) >= 0 ) {
2018-08-10 19:18:48 +02:00
WP_CLI :: error ( 'Profiling intermediate hooks is broken in PHP 7, see https://bugs.php.net/bug.php?id=72966' );
2016-11-15 08:06:31 -08:00
}
2016-10-19 18:14:28 -07:00
// Disable opcode optimizers. These "optimize" calls out of the stack
// and hide calls from the tick handler and backtraces.
// Copied from P3 Profiler
if ( extension_loaded ( 'xcache' ) ) {
2018-08-11 15:33:50 +02:00
@ ini_set ( 'xcache.optimizer' , false ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- ini_set can be disabled on server.
2016-10-19 18:14:28 -07:00
} elseif ( extension_loaded ( 'apc' ) ) {
2018-08-11 15:33:50 +02:00
@ ini_set ( 'apc.optimization' , 0 ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- ini_set can be disabled on server.
2016-10-19 18:14:28 -07:00
apc_clear_cache ();
} elseif ( extension_loaded ( 'eaccelerator' ) ) {
2018-08-11 15:33:50 +02:00
@ ini_set ( 'eaccelerator.optimizer' , 0 ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- ini_set can be disabled on server.
2016-10-19 18:14:28 -07:00
if ( function_exists ( 'eaccelerator_optimizer' ) ) {
2018-08-11 15:33:50 +02:00
@ eaccelerator_optimizer ( false ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- disabling eaccelerator on runtime can faild
2016-10-19 18:14:28 -07:00
}
} elseif ( extension_loaded ( 'Zend Optimizer+' ) ) {
2018-08-11 15:33:50 +02:00
@ ini_set ( 'zend_optimizerplus.optimization_level' , 0 ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- ini_set can be disabled on server.
2016-10-19 18:14:28 -07:00
}
2016-10-09 15:43:02 -07:00
register_tick_function ( array ( $this , 'handle_function_tick' ) );
declare ( ticks = 1 );
return $value ;
}
/**
* Stop profiling function calls at the beginning of this filter
*/
public function wp_tick_profile_end ( $value = null ) {
unregister_tick_function ( array ( $this , 'handle_function_tick' ) );
$this -> tick_callback = null ;
return $value ;
2016-10-08 06:37:41 -07:00
}
/**
* Profiling verbosity at the beginning of every action and filter
*/
public function wp_hook_begin () {
2018-08-10 19:18:48 +02:00
foreach ( Logger :: $active_loggers as $logger ) {
2016-10-08 06:37:41 -07:00
$logger -> start_hook_timer ();
}
$current_filter = current_filter ();
2016-10-08 07:27:46 -07:00
if ( ( 'stage' === $this -> type && in_array ( $current_filter , $this -> current_stage_hooks ) )
|| ( 'hook' === $this -> type && ! $this -> focus ) ) {
2016-10-09 09:05:27 -07:00
$pseudo_hook = " { $current_filter } :before " ;
2016-10-08 06:37:41 -07:00
if ( isset ( $this -> loggers [ $pseudo_hook ] ) ) {
$this -> loggers [ $pseudo_hook ] -> stop ();
}
$callback_count = 0 ;
2018-08-10 19:18:48 +02:00
$callbacks = self :: get_filter_callbacks ( $current_filter );
2016-10-08 06:49:28 -07:00
if ( false !== $callbacks ) {
2018-08-10 19:18:48 +02:00
foreach ( $callbacks as $priority => $cbs ) {
2016-10-08 06:49:28 -07:00
$callback_count += count ( $cbs );
2016-10-08 06:37:41 -07:00
}
}
2018-08-10 19:18:48 +02:00
$this -> loggers [ $current_filter ] = new Logger (
array (
'hook' => $current_filter ,
'callback_count' => $callback_count ,
)
);
2016-10-08 06:37:41 -07:00
$this -> loggers [ $current_filter ] -> start ();
}
2016-10-08 16:02:46 -07:00
if ( 0 === $this -> filter_depth
&& ! is_null ( $this -> previous_filter_callbacks ) ) {
2016-10-08 06:49:28 -07:00
self :: set_filter_callbacks ( $this -> previous_filter , $this -> previous_filter_callbacks );
2016-10-08 06:37:41 -07:00
$this -> previous_filter_callbacks = null ;
}
2016-10-09 15:43:02 -07:00
if ( 'hook' === $this -> type
&& 0 === $this -> filter_depth
&& ( $current_filter === $this -> focus || true === $this -> focus ) ) {
$this -> wrap_current_filter_callbacks ( $current_filter );
2016-10-08 06:37:41 -07:00
}
2016-10-09 10:33:48 -07:00
2016-10-08 16:02:46 -07:00
$this -> filter_depth ++ ;
2016-10-08 06:37:41 -07:00
2016-10-08 16:02:46 -07:00
WP_CLI :: add_wp_hook ( $current_filter , array ( $this , 'wp_hook_end' ), 9999 );
2016-10-08 06:37:41 -07:00
}
/**
* Wrap current filter callbacks with a timer
*/
private function wrap_current_filter_callbacks ( $current_filter ) {
2016-10-08 06:49:28 -07:00
$callbacks = self :: get_filter_callbacks ( $current_filter );
if ( false === $callbacks ) {
2016-10-08 06:37:41 -07:00
return ;
}
2018-08-10 19:18:48 +02:00
$this -> previous_filter = $current_filter ;
2016-10-08 06:49:28 -07:00
$this -> previous_filter_callbacks = $callbacks ;
2016-10-08 06:37:41 -07:00
2018-08-10 19:18:48 +02:00
foreach ( $callbacks as $priority => $priority_callbacks ) {
foreach ( $priority_callbacks as $i => $the_ ) {
2016-10-08 06:37:41 -07:00
$callbacks [ $priority ][ $i ] = array (
2018-08-10 19:18:48 +02:00
'function' => function () use ( $the_ , $i ) {
2016-10-08 06:37:41 -07:00
if ( ! isset ( $this -> loggers [ $i ] ) ) {
2018-08-10 19:18:48 +02:00
$this -> loggers [ $i ] = new Logger (
array (
'callback' => $the_ [ 'function' ],
)
);
2016-10-08 06:37:41 -07:00
}
$this -> loggers [ $i ] -> start ();
$value = call_user_func_array ( $the_ [ 'function' ], func_get_args () );
$this -> loggers [ $i ] -> stop ();
return $value ;
},
2018-08-10 19:18:48 +02:00
'accepted_args' => $the_ [ 'accepted_args' ],
2016-10-08 06:37:41 -07:00
);
}
}
2016-10-08 06:49:28 -07:00
self :: set_filter_callbacks ( $current_filter , $callbacks );
2016-10-08 06:37:41 -07:00
}
/**
* Profiling verbosity at the end of every action and filter
*/
public function wp_hook_end ( $filter_value = null ) {
2018-08-10 19:18:48 +02:00
foreach ( Logger :: $active_loggers as $logger ) {
2016-10-08 06:37:41 -07:00
$logger -> stop_hook_timer ();
}
$current_filter = current_filter ();
2016-10-08 07:27:46 -07:00
if ( ( 'stage' === $this -> type && in_array ( $current_filter , $this -> current_stage_hooks ) )
|| ( 'hook' === $this -> type && ! $this -> focus ) ) {
2016-10-08 06:37:41 -07:00
$this -> loggers [ $current_filter ] -> stop ();
2016-10-08 07:27:46 -07:00
if ( 'stage' === $this -> type ) {
$key = array_search ( $current_filter , $this -> current_stage_hooks );
if ( false !== $key && isset ( $this -> current_stage_hooks [ $key + 1 ] ) ) {
2016-10-09 09:05:27 -07:00
$pseudo_hook = " { $this -> current_stage_hooks [ $key + 1 ] } :before " ;
2016-10-08 07:27:46 -07:00
} else {
2018-08-10 19:18:48 +02:00
$pseudo_hook = " { $this -> current_stage_hooks [ $key ] } :after " ;
;
2016-10-09 09:05:27 -07:00
$this -> running_hook = $pseudo_hook ;
2016-10-08 07:27:46 -07:00
}
2016-10-09 09:05:27 -07:00
$this -> loggers [ $pseudo_hook ] = new Logger ( array ( 'hook' => $pseudo_hook ) );
$this -> loggers [ $pseudo_hook ] -> start ();
2016-10-08 06:37:41 -07:00
}
}
2016-10-08 16:02:46 -07:00
$this -> filter_depth -- ;
2016-10-08 06:37:41 -07:00
return $filter_value ;
}
2016-10-09 10:33:48 -07:00
/**
* Handle the tick of a function
*/
public function handle_function_tick () {
global $wpdb , $wp_object_cache ;
2016-10-09 10:45:38 -07:00
if ( ! is_null ( $this -> tick_callback ) ) {
2016-10-09 10:33:48 -07:00
$time = microtime ( true ) - $this -> tick_start_time ;
2016-10-09 16:15:16 -07:00
$callback_hash = md5 ( serialize ( $this -> tick_callback . $this -> tick_location ) );
2016-10-09 10:33:48 -07:00
if ( ! isset ( $this -> loggers [ $callback_hash ] ) ) {
$this -> loggers [ $callback_hash ] = array (
2018-08-10 19:18:48 +02:00
'callback' => $this -> tick_callback ,
'location' => $this -> tick_location ,
'time' => 0 ,
'query_time' => 0 ,
'query_count' => 0 ,
'cache_hits' => 0 ,
'cache_misses' => 0 ,
'cache_ratio' => null ,
2016-10-09 10:33:48 -07:00
);
}
$this -> loggers [ $callback_hash ][ 'time' ] += $time ;
if ( isset ( $wpdb ) ) {
for ( $i = $this -> tick_query_offset ; $i < count ( $wpdb -> queries ); $i ++ ) {
$this -> loggers [ $callback_hash ][ 'query_time' ] += $wpdb -> queries [ $i ][ 1 ];
$this -> loggers [ $callback_hash ][ 'query_count' ] ++ ;
}
}
if ( isset ( $wp_object_cache ) ) {
2018-08-10 19:18:48 +02:00
$hits = ! empty ( $wp_object_cache -> cache_hits ) ? $wp_object_cache -> cache_hits : 0 ;
2016-10-09 10:33:48 -07:00
$misses = ! empty ( $wp_object_cache -> cache_misses ) ? $wp_object_cache -> cache_misses : 0 ;
2018-08-10 19:18:48 +02:00
$this -> loggers [ $callback_hash ][ 'cache_hits' ] = ( $hits - $this -> tick_cache_hit_offset ) + $this -> loggers [ $callback_hash ][ 'cache_hits' ];
2016-10-09 10:33:48 -07:00
$this -> loggers [ $callback_hash ][ 'cache_misses' ] = ( $misses - $this -> tick_cache_miss_offset ) + $this -> loggers [ $callback_hash ][ 'cache_misses' ];
$total = $this -> loggers [ $callback_hash ][ 'cache_hits' ] + $this -> loggers [ $callback_hash ][ 'cache_misses' ];
if ( $total ) {
$ratio = ( $this -> loggers [ $callback_hash ][ 'cache_hits' ] / $total ) * 100 ;
$this -> loggers [ $callback_hash ][ 'cache_ratio' ] = round ( $ratio , 2 ) . '%' ;
}
}
}
2018-08-10 19:18:48 +02:00
$bt = debug_backtrace ( DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT , 2 );
2016-10-09 10:33:48 -07:00
$frame = $bt [ 0 ];
if ( isset ( $bt [ 1 ] ) ) {
$frame = $bt [ 1 ];
}
2016-10-09 16:15:16 -07:00
$callback = $location = '' ;
2016-10-09 10:33:48 -07:00
if ( in_array ( strtolower ( $frame [ 'function' ] ), array ( 'include' , 'require' , 'include_once' , 'require_once' ) ) ) {
2016-10-09 16:15:16 -07:00
$callback = $frame [ 'function' ] . " ' " . $frame [ 'args' ][ 0 ] . " ' " ;
2018-08-10 19:18:48 +02:00
} elseif ( isset ( $frame [ 'object' ] ) && method_exists ( $frame [ 'object' ], $frame [ 'function' ] ) ) {
2016-10-09 16:15:16 -07:00
$callback = get_class ( $frame [ 'object' ] ) . '->' . $frame [ 'function' ] . '()' ;
2018-08-10 19:18:48 +02:00
} elseif ( isset ( $frame [ 'class' ] ) && method_exists ( $frame [ 'class' ], $frame [ 'function' ] ) ) {
2016-10-09 16:15:16 -07:00
$callback = $frame [ 'class' ] . '::' . $frame [ 'function' ] . '()' ;
2018-08-10 19:18:48 +02:00
} elseif ( ! empty ( $frame [ 'function' ] ) && function_exists ( $frame [ 'function' ] ) ) {
2016-10-09 16:15:16 -07:00
$callback = $frame [ 'function' ] . '()' ;
} elseif ( '__lambda_func' == $frame [ 'function' ] || '{closure}' == $frame [ 'function' ] ) {
$callback = 'function(){}' ;
}
if ( 'runcommand\Profile\Profiler->wp_tick_profile_begin()' === $callback ) {
2016-10-26 06:29:07 -07:00
$this -> tick_callback = null ;
2016-10-09 16:15:16 -07:00
return ;
}
if ( isset ( $frame [ 'file' ] ) ) {
$location = $frame [ 'file' ];
if ( isset ( $frame [ 'line' ] ) ) {
$location .= ':' . $frame [ 'line' ];
}
2016-10-09 10:33:48 -07:00
}
2018-08-10 19:18:48 +02:00
$this -> tick_callback = $callback ;
$this -> tick_location = $location ;
$this -> tick_start_time = microtime ( true );
$this -> tick_query_offset = ! empty ( $wpdb -> queries ) ? count ( $wpdb -> queries ) : 0 ;
$this -> tick_cache_hit_offset = ! empty ( $wp_object_cache -> cache_hits ) ? $wp_object_cache -> cache_hits : 0 ;
2016-10-09 10:33:48 -07:00
$this -> tick_cache_miss_offset = ! empty ( $wp_object_cache -> cache_misses ) ? $wp_object_cache -> cache_misses : 0 ;
}
2016-10-08 06:37:41 -07:00
/**
* Profiling request time for any active Loggers
*/
public function wp_request_begin ( $filter_value = null ) {
2018-08-10 19:18:48 +02:00
foreach ( Logger :: $active_loggers as $logger ) {
2016-10-08 06:37:41 -07:00
$logger -> start_request_timer ();
}
return $filter_value ;
}
/**
* Profiling request time for any active Loggers
*/
public function wp_request_end ( $filter_value = null ) {
2018-08-10 19:18:48 +02:00
foreach ( Logger :: $active_loggers as $logger ) {
2016-10-08 06:37:41 -07:00
$logger -> stop_request_timer ();
}
return $filter_value ;
}
/**
* Runs through the entirety of the WP bootstrap process
*/
private function load_wordpress_with_template () {
2016-11-14 06:30:19 -08:00
// WordPress already ran once.
if ( function_exists ( 'add_filter' ) ) {
return ;
}
2016-10-08 06:37:41 -07:00
if ( 'stage' === $this -> type && true === $this -> focus ) {
$hooks = array ();
2018-08-10 19:18:48 +02:00
foreach ( $this -> stage_hooks as $stage_hook ) {
2016-10-08 06:37:41 -07:00
$hooks = array_merge ( $hooks , $stage_hook );
}
$this -> set_stage_hooks ( $hooks );
}
if ( 'stage' === $this -> type ) {
if ( 'bootstrap' === $this -> focus ) {
$this -> set_stage_hooks ( $this -> stage_hooks [ 'bootstrap' ] );
2018-08-10 19:18:48 +02:00
} elseif ( ! $this -> focus ) {
2016-10-08 06:37:41 -07:00
$logger = new Logger ( array ( 'stage' => 'bootstrap' ) );
$logger -> start ();
}
}
WP_CLI :: get_runner () -> load_wordpress ();
2016-10-09 09:05:27 -07:00
if ( $this -> running_hook ) {
$this -> loggers [ $this -> running_hook ] -> stop ();
$this -> running_hook = null ;
2016-10-08 06:37:41 -07:00
}
2016-10-26 06:54:43 -07:00
if ( 'hook' === $this -> type && 'wp_loaded:after' === $this -> focus ) {
$this -> wp_tick_profile_end ();
}
2016-10-08 06:37:41 -07:00
if ( 'stage' === $this -> type && ! $this -> focus ) {
$logger -> stop ();
$this -> loggers [] = $logger ;
}
// Set up main_query main WordPress query.
if ( 'stage' === $this -> type ) {
if ( 'main_query' === $this -> focus ) {
$this -> set_stage_hooks ( $this -> stage_hooks [ 'main_query' ] );
2018-08-10 19:18:48 +02:00
} elseif ( ! $this -> focus ) {
2016-10-08 06:37:41 -07:00
$logger = new Logger ( array ( 'stage' => 'main_query' ) );
$logger -> start ();
}
}
wp ();
2016-10-09 09:05:27 -07:00
if ( $this -> running_hook ) {
$this -> loggers [ $this -> running_hook ] -> stop ();
$this -> running_hook = null ;
2016-10-08 06:37:41 -07:00
}
2016-10-26 06:54:43 -07:00
if ( 'hook' === $this -> type && 'wp:after' === $this -> focus ) {
$this -> wp_tick_profile_end ();
}
2016-10-08 06:37:41 -07:00
if ( 'stage' === $this -> type && ! $this -> focus ) {
$logger -> stop ();
$this -> loggers [] = $logger ;
}
define ( 'WP_USE_THEMES' , true );
2018-01-13 18:30:11 +00:00
// Template is normally loaded in global scope, so we need to replicate
2018-08-10 19:18:48 +02:00
foreach ( $GLOBALS as $key => $value ) {
2018-08-11 15:53:41 +02:00
global ${$key} ; // phpcs:ignore PHPCompatibility.PHP.ForbiddenGlobalVariableVariable.NonBareVariableFound -- Syntax is updated to compatible with php 5 and 7.
2016-10-08 06:37:41 -07:00
}
// Load the theme template.
if ( 'stage' === $this -> type ) {
if ( 'template' === $this -> focus ) {
$this -> set_stage_hooks ( $this -> stage_hooks [ 'template' ] );
2018-08-10 19:18:48 +02:00
} elseif ( ! $this -> focus ) {
2016-10-08 06:37:41 -07:00
$logger = new Logger ( array ( 'stage' => 'template' ) );
$logger -> start ();
}
}
ob_start ();
require_once ( ABSPATH . WPINC . '/template-loader.php' );
ob_get_clean ();
2016-10-09 09:05:27 -07:00
if ( $this -> running_hook ) {
$this -> loggers [ $this -> running_hook ] -> stop ();
$this -> running_hook = null ;
2016-10-08 06:37:41 -07:00
}
2016-10-26 06:54:43 -07:00
if ( 'hook' === $this -> type && 'wp_footer:after' === $this -> focus ) {
$this -> wp_tick_profile_end ();
}
2016-10-08 06:37:41 -07:00
if ( 'stage' === $this -> type && ! $this -> focus ) {
$logger -> stop ();
$this -> loggers [] = $logger ;
}
}
/**
* Get a human - readable name from a callback
*/
private static function get_name_location_from_callback ( $callback ) {
2018-08-10 19:18:48 +02:00
$name = $location = '' ;
2016-10-08 06:37:41 -07:00
$reflection = false ;
if ( is_array ( $callback ) && is_object ( $callback [ 0 ] ) ) {
$reflection = new \ReflectionMethod ( $callback [ 0 ], $callback [ 1 ] );
2018-08-10 19:18:48 +02:00
$name = get_class ( $callback [ 0 ] ) . '->' . $callback [ 1 ] . '()' ;
2016-10-08 06:37:41 -07:00
} elseif ( is_array ( $callback ) && method_exists ( $callback [ 0 ], $callback [ 1 ] ) ) {
$reflection = new \ReflectionMethod ( $callback [ 0 ], $callback [ 1 ] );
2018-08-10 19:18:48 +02:00
$name = $callback [ 0 ] . '::' . $callback [ 1 ] . '()' ;
2016-10-08 06:37:41 -07:00
} elseif ( is_object ( $callback ) && is_a ( $callback , 'Closure' ) ) {
$reflection = new \ReflectionFunction ( $callback );
2018-08-10 19:18:48 +02:00
$name = 'function(){}' ;
} elseif ( is_string ( $callback ) && function_exists ( $callback ) ) {
2016-10-08 06:37:41 -07:00
$reflection = new \ReflectionFunction ( $callback );
2018-08-10 19:18:48 +02:00
$name = $callback . '()' ;
2016-10-08 06:37:41 -07:00
}
if ( $reflection ) {
$location = $reflection -> getFileName () . ':' . $reflection -> getStartLine ();
}
return array ( $name , $location );
}
2016-10-09 16:15:16 -07:00
/**
* Get the short location from the full location
*
* @ param string $location
* @ return string
*/
private static function get_short_location ( $location ) {
$abspath = rtrim ( realpath ( ABSPATH ), '/' ) . '/' ;
if ( defined ( 'WP_PLUGIN_DIR' ) && 0 === stripos ( $location , WP_PLUGIN_DIR ) ) {
$location = str_replace ( trailingslashit ( WP_PLUGIN_DIR ), '' , $location );
2018-08-10 19:18:48 +02:00
} elseif ( defined ( 'WPMU_PLUGIN_DIR' ) && 0 === stripos ( $location , WPMU_PLUGIN_DIR ) ) {
2016-10-09 16:15:16 -07:00
$location = str_replace ( trailingslashit ( dirname ( WPMU_PLUGIN_DIR ) ), '' , $location );
2018-08-10 19:18:48 +02:00
} elseif ( function_exists ( 'get_theme_root' ) && 0 === stripos ( $location , get_theme_root () ) ) {
2016-10-09 16:15:16 -07:00
$location = str_replace ( trailingslashit ( get_theme_root () ), '' , $location );
2018-08-10 19:18:48 +02:00
} elseif ( 0 === stripos ( $location , $abspath . 'wp-admin/' ) ) {
2016-10-09 16:15:16 -07:00
$location = str_replace ( $abspath , '' , $location );
2018-08-10 19:18:48 +02:00
} elseif ( 0 === stripos ( $location , $abspath . 'wp-includes/' ) ) {
2016-10-09 16:15:16 -07:00
$location = str_replace ( $abspath , '' , $location );
}
return $location ;
}
2016-10-08 06:37:41 -07:00
/**
* Set the hooks for the current stage
*/
private function set_stage_hooks ( $hooks ) {
2018-08-10 19:18:48 +02:00
$this -> current_stage_hooks = $hooks ;
$pseudo_hook = " { $hooks [ 0 ] } :before " ;
2016-10-09 09:05:27 -07:00
$this -> loggers [ $pseudo_hook ] = new Logger ( array ( 'hook' => $pseudo_hook ) );
2016-10-08 06:37:41 -07:00
$this -> loggers [ $pseudo_hook ] -> start ();
}
2016-10-08 06:49:28 -07:00
/**
* Get the callbacks for a given filter
*
* @ param string
* @ return array | false
*/
private static function get_filter_callbacks ( $filter ) {
global $wp_filter ;
if ( ! isset ( $wp_filter [ $filter ] ) ) {
return false ;
}
if ( is_a ( $wp_filter [ $filter ], 'WP_Hook' ) ) {
$callbacks = $wp_filter [ $filter ] -> callbacks ;
} else {
$callbacks = $wp_filter [ $filter ];
}
if ( is_array ( $callbacks ) ) {
return $callbacks ;
}
return false ;
}
/**
* Set the callbacks for a given filter
*
* @ param string $filter
* @ param mixed $callbacks
*/
private static function set_filter_callbacks ( $filter , $callbacks ) {
global $wp_filter ;
if ( ! isset ( $wp_filter [ $filter ] ) && class_exists ( 'WP_Hook' ) ) {
$wp_filter [ $filter ] = new \WP_Hook ;
}
if ( is_a ( $wp_filter [ $filter ], 'WP_Hook' ) ) {
$wp_filter [ $filter ] -> callbacks = $callbacks ;
} else {
$wp_filter [ $filter ] = $callbacks ;
}
}
2018-08-10 19:18:48 +02:00
2016-10-08 06:37:41 -07:00
}