-
-
Save mikeschinkel/523831 to your computer and use it in GitHub Desktop.
<?php | |
/* | |
Plugin Name: Instrument Hooks for WordPress | |
Description: Instruments Hooks for a Page. Outputs during the Shutdown Hook. | |
Version: 0.1 | |
Author: Mike Schinkel | |
Author URI: http://mikeschinkel.com | |
*/ | |
if (isset($_GET['instrument']) && $_GET['instrument']=='hooks') { | |
add_action('shutdown','instrument_hooks'); | |
function instrument_hooks() { | |
global $wpdb; | |
$hooks = $wpdb->get_results("SELECT * FROM wp_hook_list ORDER BY first_call"); | |
$html = array(); | |
$html[] = '<style>#instrumented-hook-list table,#instrumented-hook-list th,#instrumented-hook-list td {border:1px solid gray;padding:2px 5px;}</style> | |
<div align="center" id="instrumented-hook-list"> | |
<table> | |
<tr> | |
<th>First Call</th> | |
<th>Hook Name</th> | |
<th>Hook Type</th> | |
<th>Arg Count</th> | |
<th>Called By</th> | |
<th>Line #</th> | |
<th>File Name</th> | |
</tr>'; | |
foreach($hooks as $hook) { | |
$html[] = "<tr> | |
<td>{$hook->first_call}</td> | |
<td>{$hook->hook_name}</td> | |
<td>{$hook->hook_type}</td> | |
<td>{$hook->arg_count}</td> | |
<td>{$hook->called_by}</td> | |
<td>{$hook->line_num}</td> | |
<td>{$hook->file_name}</td> | |
</tr>"; | |
} | |
$html[] = '</table></div>'; | |
echo implode("\n",$html); | |
} | |
add_action('all','record_hook_usage'); | |
function record_hook_usage($hook){ | |
global $wpdb; | |
static $in_hook = false; | |
static $first_call = 1; | |
static $doc_root; | |
$callstack = debug_backtrace(); | |
if (!$in_hook) { | |
$in_hook = true; | |
if ($first_call==1) { | |
$doc_root = $_SERVER['DOCUMENT_ROOT']; | |
$results = $wpdb->get_results("SHOW TABLE STATUS LIKE 'wp_hook_list'"); | |
if (count($results)==1) { | |
$wpdb->query("TRUNCATE TABLE wp_hook_list"); | |
} else { | |
$wpdb->query("CREATE TABLE wp_hook_list ( | |
called_by varchar(96) NOT NULL, | |
hook_name varchar(96) NOT NULL, | |
hook_type varchar(15) NOT NULL, | |
first_call int(11) NOT NULL, | |
arg_count tinyint(4) NOT NULL, | |
file_name varchar(128) NOT NULL, | |
line_num smallint NOT NULL, | |
PRIMARY KEY (first_call,hook_name))" | |
); | |
} | |
} | |
$args = func_get_args(); | |
$arg_count = count($args)-1; | |
$hook_type = str_replace('do_','', | |
str_replace('apply_filters','filter', | |
str_replace('_ref_array','[]', | |
$callstack[3]['function']))); | |
$file_name = addslashes(str_replace($doc_root,'',$callstack[3]['file'])); | |
$line_num = $callstack[3]['line']; | |
$called_by = $callstack[4]['function']; | |
$wpdb->query("INSERT wp_hook_list | |
(first_call,called_by,hook_name,hook_type,arg_count,file_name,line_num) | |
VALUES ($first_call,'$called_by()','$hook','$hook_type',$arg_count,'$file_name',$line_num)"); | |
$first_call++; | |
$in_hook = false; | |
} | |
} | |
} |
Can you explain the solution? I'm not sure what you are suggesting.
Oh, sorry I wasn't clear.
Basically, when the instrumentation table is displayed it, the file name does not take into account the fact that Windows file names use backslashes.
So, if the file path is: C:\Wamp\www\network, it will show up as C:wampwww[\n]etwork, where [\n] is now new line.
I think changing line 77 to use addslashes does the trick:
$file_name = addslashes(str_replace($doc_root,'',$callstack[3]['file']));
Perfect, thanks! I've edited. Can you confirm it works for you?
Seems to work fine. Thank you.
You should do an isset
or empty
check for $_GET['instrument']
to prevent undefined variable errors.
@GeertDD - Sure, done.
perfect just what im looking for...
made small customisation where i could filter which hook type i need to view
https://gist.github.com/thejuanwhocode/7ddb83d2a1fb0c78d359
$_GET['type']=filter
Tested with WordPress 6.5-alpha-57224 but when I added ?instrument=hooks to the URL, table is shown but no list and everything seems to be stopped for unknown reason. No errors show up or no in debug.log.
I try to wrap if (isset($_GET['instrument']) && $_GET['instrument']=='hooks') {...}
with only add_action('all','record_hook_usage');
part and it seems to work (DB inserted) but table result did not show.
I come back to normal page and result is showing full.
I have no idea why it stopped inside record_hook_usage()
without any errors.
@ve3 — I have not worked with WordPress for over 4 years so can’t tell you what’s wrong.
My best suggestion is to get PhpStorm, and use it’s debugger to figure out why it does not work.
Thanks @mikeschinkel for your work. May I post a link to my gist here? It's a simple plugin that can be trace actions/filters hooks on enabled trace option.
The difference than other plugins is most of them can list actions and filters of current page but when the page is redirect or act by normal user you cannot know anything about it. My simple plugin can work on any request as long as enable trace hook option is turn on.
Sure.
https://gist.github.com/ve3/96c50c671e06dde475f6e3c80492f7e5
WP hooks trace
I am not setup for that right now. Sorry. So, just a bug report for now.