Get all MyBB hooks on your current installed version

3 Apr 2016 Edited
#1
When building a plugin one of the most annoying operations you need to do is finding your desired hook. You just lose your mind gathering through the source code of single files, and end up wasting tons of precious minutes you would spend doing something better. MyBB devs already provide a list of hooks ordered by filename along with their code line but the list is updated manually using the awesome MyBB Hooks Finder, a script written in Ruby by @euantorano. This means that the list is often not up to date and line numbers might not be accurate, as they specify in the page. This is usually not a big deal since, you know, no one looks for something in a file knowing its line number, they just CTRL/CMD + F and use a search&replace functionality which is built in the majority of available text editors. However this might be a problem when dealing with outdated MyBB versions since hooks might have been added or removed in the process. Also, the hooks list is not easily manipulable by developers willing to use the hooks for their personal purposes.

Since euantorano's script is written in Ruby, and I have no idea how to integrate a Ruby script within the PHP environment, I decided to write down a PHP version of the script which basically does the same thing, but it orders hooks both by filename AND by hooksname providing a flexible and ever-up-to-date list of MyBB hooks which are currently running on your MyBB installation.

function get_hooks($order_by 'filename')
    {
        
// Set up the recursive iterator
        
$dir = new RecursiveIteratorIterator(
            new 
RecursiveDirectoryIterator(MYBB_ROOTRecursiveDirectoryIterator::SKIP_DOTS),
            
RecursiveIteratorIterator::SELF_FIRST,
            
RecursiveIteratorIterator::CATCH_GET_CHILD
        
);
        
        
$order_by_filename $order_by_hookname = [];
        
        
// Iterate through all directories
        
foreach ($dir as $fileinfo) {
            
            
$filename $fileinfo->getFilename();
            
$pathname $fileinfo->getPathname();
            
$clean_pathname str_replace(MYBB_ROOT''$pathname);
            
            
// Check if this file is a valid .php file
            
if (pathinfo($filenamePATHINFO_EXTENSION) == 'php') {
                
                
$grep_matches = [];
                
                
// Match with a low-memory bash grep command every hook run in the current file
                
exec('grep -n ' escapeshellarg('$plugins->run_hooks').' ' $pathname$grep_matches);
                
                
// Tidy the results given by grep, filtering line number, hook's name and eventual arguments
                
preg_match_all('#(\d+):(?:[^"\']*)["\']([^"\']*)["\'](?:\)|,\s*([^)]*))#im'implode("#"$grep_matches), $matchesPREG_SET_ORDER);
                
                foreach (
$matches as $match) {
                    
                    
// Hooks ordered by filename (eg.: inc/functions.php => pre_output_page)
                    
$order_by_filename[$clean_pathname][$match[1]] = [
                        
'name' => $match[2]
                    ];
                    
                    
// Deal with eventual arguments matched
                    
if ($match[3]) {
                        
$output[$clean_pathname][$match[1]]['arguments'] = $match[3];
                    }
                    
                    
// Hooks ordered by hookname (eg.: pre_output_page => inc/functions.php, inc/plugins/mycustomplugin.php)
                    
$order_by_hookname[$match[2]][$match[1]] = $clean_pathname;
                    
                }
                
            }

        }
        
        if (
$order_by == 'filename') {
            return (array) 
$order_by_filename;
        }
        else {
            return (array) 
$order_by_hookname;
        }
        
    } 
Whether you are on MyBB 1.6 or on the latest version, you can integrate this script in your plugins and instantaneously get all the available hooks with additional informations like the precise code line and eventual arguments passed. The purpose of having an ordered-by-hooksname list is that hooks might be run multiple times in different scripts, even in third party plugins, so you exactly know where and how many times a hook is run.

That's it. Results are given as arrays. You can play around with them as you may like, building select boxes or informative pages for your dev team containing all the hooks currently running. Passing an argument different from the string "filename" gets the list ordered by hookname instead. The script requires PHP 5.4 or newer, but can easily be adapted to be compatible with PHP 5.3 by replacing [] with array() as the shortcut syntax has been introduced with 5.4.