正如我在对问题的评论中所说,您可以使用PHP内部ReflectionFunction 类以获取可调用的文件名。下面的代码应该是帮助您的良好开端。它需要更多的逻辑来确定回调,而且其中大部分都应该从Monitor类中抽象出来。我也没有编写代码来获得主题、插件、核心或其他可能从文件名中添加挂钩的名称。如果您知道添加挂钩的文件,那么这应该相对容易做到。
<?php
/**
* Plugin Name: Monitor
*/
namespace WPSE\\Monitor;
class Monitor {
protected $callbacks = [];
protected function addCallback( $callback ) {
$this->callbacks[] = $callback;
}
public function shutdown() {
var_dump( $this->callbacks );
}
public function monitor() {
global $wp_filter;
$name = \\current_filter();
if( ! isset( $wp_filter[ $name ] ) ) {
return;
}
$action = $wp_filter[ $name ];
foreach ( $action->callbacks as $priority => $callbacks ) {
foreach( $callbacks as $callback ) {
try {
if( \\is_array( $callback[ \'function\' ] ) ) {
if( \\is_object( $callback[ \'function\' ][ 0 ] ) ) {
$class = \\get_class( $callback[ \'function\' ][ 0 ] );
$callback[ \'name\' ] = $class . \'->\' . $callback[ \'function\' ][ 1 ] . \'()\';
$ref = new \\ReflectionMethod( $class, $callback[ \'function\' ][ 1 ] );
}
elseif( \\is_string( $callback[ \'function\' ][ 0 ] ) ) {
$callback[ \'name\' ] = $callback[ \'function\' ][ 0 ] . \'::\' . $callback[ \'function\' ][ 1 ];
$ref = new \\ReflectionMethod( $callback[ \'function\' ][ 0 ], $callback[ \'function\' ][ 1 ] );
}
}
elseif( $callback[ \'function\' ] instanceOf Closure ) {
$callback[ \'name\' ] = \'closure\';
$ref = new \\ReflectionMethod( $callback[ \'function\' ] );
}
elseif( \\is_string( $callback[ \'function\' ] ) ) {
$callback[ \'name\' ] = $callback[ \'function\' ] . \'()\';
$ref = new \\ReflectionMethod( $callback[ \'name\' ] );
}
else{
return;
}
$callback[ \'filename\' ] = $ref->getFileName();
$this->addCallback( $callback );
} catch( \\ReflectionException $e ) {
$callback[\'error\'] = new \\WP_Error( \'reflection_exception\', $e->getMessage() );
}
}
}
}
}
class MonitorInit {
private static $monitor;
public static function init() {
self::$monitor = new Monitor();
\\add_action( \'all\', [ self::$monitor, \'monitor\' ] );
\\add_action( \'shutdown\', [ self::$monitor, \'shutdown\' ] );
}
}
\\add_action( \'plugins_loaded\', __NAMESPACE__ . \'\\MonitorInit::init\', 0 );
The
plugins_loaded
hook是第一个可用于常规插件的插件。因此,如果您想捕获在此之前添加的挂钩,您需要做一些棘手的事情。