Created
November 2, 2016 17:58
-
-
Save tivnet/e0e35282865b2c4ee43509b08c8f230f to your computer and use it in GitHub Desktop.
Generate list of hooks (for WPGlobus)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* File: apigen-hooks.php | |
* | |
* NOTE: this code is used internally in WPGlobus project. | |
* It's a W.I.P. - please use it, but do not forget to adapt for your project. | |
* | |
* @package WPGlobus\APIGen | |
* @author Gregory Karpinsky (@tivnet) | |
*/ | |
/** | |
* Generate documentation for hooks. | |
* Idea borrowed from: | |
* @link https://github.com/woothemes/woocommerce/blob/master/apigen/hook-docs.php | |
*/ | |
class WPGlobus_APIGen_Hooks { | |
protected static $current_file = ''; | |
protected static $custom_hooks_found = array(); | |
protected static $base_path = 'app/plugins/wpglobus/'; // TODO. | |
public static function process_hooks() { | |
$class_files = self::get_files( self::$base_path . 'includes/' ); | |
/* | |
$template_files = self::get_files( '*.php', GLOB_MARK, '../templates/' ); | |
$template_files[] = '../includes/wc-template-functions.php'; | |
$template_files[] = '../includes/wc-template-hooks.php'; | |
$shortcode_files = self::get_files( '*.php', GLOB_MARK, '../includes/shortcodes/' ); | |
$widget_files = self::get_files( '*.php', GLOB_MARK, '../includes/widgets/' ); | |
$admin_files = self::get_files( '*.php', GLOB_MARK, '../includes/admin/' ); | |
$other_files = array( | |
'../woocommerce.php' | |
);*/ | |
$files_to_scan = array( | |
'Class Hooks' => $class_files, | |
/* | |
'Template Hooks' => $template_files, | |
'Shortcode Hooks' => $shortcode_files, | |
'Widget Hooks' => $widget_files, | |
'Admin Hooks' => $admin_files, | |
'Other Hooks' => $other_files,*/ | |
); | |
$scanned = array(); | |
ob_start(); | |
foreach ( $files_to_scan as $heading => $files ) { | |
self::$custom_hooks_found = array(); | |
/** @var array $files */ | |
foreach ( $files as $f ) { | |
self::$current_file = basename( $f ); | |
$tokens = token_get_all( file_get_contents( $f ) ); | |
$token_type = false; | |
$current_class = ''; | |
$current_function = ''; | |
/* @noinspection DisconnectedForeachInstructionInspection */ | |
if ( in_array( self::$current_file, $scanned, true ) ) { | |
continue; | |
} | |
$scanned[] = self::$current_file; | |
foreach ( $tokens as $index => $token ) { | |
if ( is_array( $token ) ) { | |
$trimmed_token_1 = trim( $token[1] ); | |
if ( T_CLASS === $token[0] ) { | |
$token_type = 'class'; | |
} elseif ( T_FUNCTION === $token[0] ) { | |
$token_type = 'function'; | |
} elseif ( 'do_action' === $token[1] ) { | |
$token_type = 'action'; | |
} elseif ( 'apply_filters' === $token[1] ) { | |
$token_type = 'filter'; | |
} elseif ( $token_type && ! empty( $trimmed_token_1 ) ) { | |
switch ( $token_type ) { | |
case 'class' : | |
$current_class = $token[1]; | |
break; | |
case 'function' : | |
$current_function = $token[1]; | |
break; | |
case 'filter' : | |
case 'action' : | |
$hook = trim( $token[1], "'" ); | |
$loop = 0; | |
/* @noinspection SubStrUsedAsArrayAccessInspection */ | |
if ( '_' === substr( $hook, '-1', 1 ) ) { | |
$hook .= '{'; | |
$open = true; | |
// Keep adding to hook until we find a comma or colon | |
while ( 1 ) { | |
$loop ++; | |
$next_hook = trim( trim( is_string( $tokens[ $index + $loop ] ) ? $tokens[ $index + $loop ] : $tokens[ $index + $loop ][1], '"' ), "'" ); | |
if ( in_array( $next_hook, array( '.', '{', '}', '"', "'", ' ' ), true ) ) { | |
continue; | |
} | |
/* @noinspection SubStrUsedAsArrayAccessInspection */ | |
$hook_first = substr( $next_hook, 0, 1 ); | |
/* @noinspection SubStrUsedAsArrayAccessInspection */ | |
$hook_last = substr( $next_hook, - 1, 1 ); | |
if ( in_array( $next_hook, array( ',', ';' ), true ) ) { | |
if ( $open ) { | |
$hook .= '}'; | |
/* @noinspection PhpUnusedLocalVariableInspection */ | |
$open = false; | |
} | |
break; | |
} | |
if ( '_' === $hook_first ) { | |
$next_hook = '}' . $next_hook; | |
$open = false; | |
} | |
if ( '_' === $hook_last ) { | |
$next_hook .= '{'; | |
$open = true; | |
} | |
$hook .= $next_hook; | |
} | |
} | |
if ( isset( self::$custom_hooks_found[ $hook ] ) ) { | |
self::$custom_hooks_found[ $hook ]['file'][] = self::$current_file; | |
} else { | |
self::$custom_hooks_found[ $hook ] = array( | |
'line' => $token[2], | |
'class' => $current_class, | |
'function' => $current_function, | |
'file' => array( self::$current_file ), | |
'type' => $token_type, | |
'path' => $f, | |
); | |
} | |
break; | |
} | |
$token_type = false; | |
} | |
} | |
} | |
} | |
foreach ( self::$custom_hooks_found as $hook => $details ) { | |
if ( | |
false === strpos( $hook, 'wpglobus_' ) | |
) { | |
unset( self::$custom_hooks_found[ $hook ] ); | |
} | |
} | |
ksort( self::$custom_hooks_found ); | |
if ( ! empty( self::$custom_hooks_found ) ) { | |
echo '<!DOCTYPE html>'; | |
?> | |
<html> | |
<head> | |
<title>WPGlobus Hooks</title> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous" /> | |
</head> | |
<body> | |
<div class="container"> | |
<h1>WPGlobus Action and Filter Hooks</h1> | |
<p>Updated: <?php echo esc_html( date( 'r' ) ); ?></p> | |
<!-- <h2>--><?php //echo esc_html( $heading ); ?><!--</h2>--> | |
<table class="table table-bordered table-striped"> | |
<thead> | |
<tr> | |
<th>Hook</th> | |
<th>Type</th> | |
<th>File(s)</th> | |
</tr> | |
</thead> | |
<tbody> | |
<?php | |
foreach ( self::$custom_hooks_found as $hook => $details ) { | |
$_hook_link = self::get_hook_link( $hook, $details ); | |
?> | |
<tr> | |
<td><?php echo $_hook_link; // WPCS: XSS ok. ?></td> | |
<td><?php echo esc_html( $details['type'] ); ?></td> | |
<td><?php echo esc_html( implode( ', ', array_unique( $details['file'] ) ) ); ?></td> | |
</tr> | |
<?php | |
} | |
?> | |
</tbody> | |
</table> | |
<div> | |
<hr/> | |
Copyright © 2014-<?php echo esc_html( date( 'Y' ) ); ?> | |
<a href="http://www.wpglobus.com/">WPGlobus</a> | |
</div> | |
</div> | |
</body> | |
</html> | |
<?php | |
} | |
} | |
// echo ob_get_clean(); // WPCS: XSS ok. | |
file_put_contents( 'C:\var\www\u\qa.wpglobus.com\wpglobus-api-docs\docs\wpglobus-hooks.html', ob_get_clean() ); // TODO. | |
} | |
/** | |
* @param string $hook | |
* @param array $details | |
* | |
* @return string | |
*/ | |
protected static function get_hook_link( $hook, array $details = array() ) { | |
if ( ! empty( $details['path'] ) ) { | |
$relative_url = str_replace( self::$base_path, '', $details['path'] ); | |
$link = 'https://github.com/WPGlobus/WPGlobus/blob/develop/' . $relative_url . '#L' . $details['line']; // TODO. | |
} else { | |
$link = 'https://github.com/WPGlobus/WPGlobus/search?q=' . $hook; | |
} | |
return '<a href="' . $link . '">' . $hook . '</a>'; | |
} | |
/** | |
* Find all PHP files in a folder. | |
* | |
* @param string $folder Folder to scan. | |
* | |
* @return array Array of files found. | |
*/ | |
public static function get_files( $folder ) { | |
$iterator_php = new RegexIterator( | |
new RecursiveIteratorIterator( | |
new RecursiveDirectoryIterator( $folder ) | |
), '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH | |
); | |
$found_files = array(); | |
foreach ( $iterator_php as $path ) { | |
$found_files[] = str_replace( '\\', '/', $path[0] ); | |
} | |
return $found_files; | |
} | |
} | |
if ( ! function_exists( 'esc_html' ) ) { | |
/** | |
* Escaping for HTML blocks. | |
* | |
* @since 2.8.0 | |
* | |
* @param string $text | |
* | |
* @return string | |
*/ | |
function esc_html( $text ) { | |
return htmlentities( $text ); | |
} | |
} | |
WPGlobus_APIGen_Hooks::process_hooks(); | |
/* EOF */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment