生成休眠钩子引用


10

似乎很多插件开发人员都花时间添加过滤器/操作挂钩,以使用户可以调整其产品的功能。很棒,但是他们通常不做的是提供钩子列表以及它们接受多少个参数。

有没有人找到最好的自动方式来指向插件(或主题)目录并查看所有可用钩子的列表?

我似乎有些扫描钩子的插件,但据我所知,它们向您显示了实际上正在调用哪些插件来呈现给定页面。我得到的可以很方便。但是有时候,如果我知道我正在与特定的插件交互,我想知道它可能让我钩住动作或过滤器的每个地方。

因此,我真正要寻找的是给定插件根目录将创建一个列表的列表,其中每个项目均包括:

  • 标签
  • 类型(动作或过滤器)
  • 参数数量
  • 在源中被称为(通过do_action()apply_filter())的位置

脚本会很棒,因为这大概可以很好地将整个事情HTML化,并在每个插件的管理UI中向我展示。但是,即使输出有用的静态文件的命令行脚本也很棒。


那是什么问题呢?如果您寻找插件推荐,那么这里就不对了
Mark Kaplun

抱歉,不想深入了解WordPress开发元杂草,但是a)我是新来的,所以我没有意识到要求插件推荐是OT。我可能对此有一些意见……但是,我仍然应该首先意识到这一点。b)OTOH,我只是想为我的问题找到任何解决方案,无论是现有的插件或Shell脚本,还是从头开始的东西。因此,问题严格是插件推荐要求!
yonatron

好吧,似乎每个人都在开心,所以没有造成伤害。我对这个问题的“反对”实际上更多地是关于一个文本解析问题,对于喜欢编写编译器样式软件但与实际的wordpress编码关系不大的人来说,这是很有趣的。为了记录,甚至有关wordpress.org的问题(如如何提交插件)通常也会被选为脱题。
马克·卡普伦

Answers:


6

我不知道要执行所需的脚本或插件。如前所述,有一些脚本(甚至全局变量)可用于打印当前使用的过滤器和操作。

至于休眠过滤器和动作,我已经写了两个非常基本的功能(在这里一些帮助,有),它找到所有apply_filtersdo_action实例在一个文件中,然后打印出来

基本

  • 我们将使用RecursiveDirectoryIteratorRecursiveIteratorIteratorRegexIteratorPHP类来获得一个目录内的所有PHP文件。例如,在我的本地主机上,E:\xammp\htdocs\wordpress\wp-includes

  • 然后,我们将遍历文件,搜索和返回(preg_match_all)的所有实例apply_filtersdo_action。我已将其设置为匹配括号的嵌套实例,并且还匹配apply_filters/ do_action和第一个括号之间的可能空白

然后,我们将简单地创建一个包含所有过滤器和操作的数组,然后遍历该数组并输出文件名以及过滤器和操作。我们将跳过没有过滤器/操作的文件

重要笔记

  • 此功能非常昂贵。仅在本地测试安装上运行它们。

  • 根据需要修改功能。您可以决定将输出写入文件,为此创建一个特殊的后端页面,选项是无限的

选项1

第一个选项功能非常简单,我们将使用file_get_contents,以字符串形式返回文件的内容,搜索apply_filters/ do_action实例,然后简单地输出文件名和过滤器/操作名称

我对代码进行了注释,以便于跟踪

function get_all_filters_and_actions( $path = '' )
{
    //Check if we have a path, if not, return false
    if ( !$path ) 
        return false;

    // Validate and sanitize path
    $path = filter_var( $path, FILTER_SANITIZE_URL );
    /**
     * If valiadtion fails, return false
     *
     * You can add an error message of something here to tell
     * the user that the URL validation failed
     */
    if ( !$path ) 
        return false;

    // Get each php file from the directory or URL  
    $dir   = new RecursiveDirectoryIterator( $path );
    $flat  = new RecursiveIteratorIterator( $dir );
    $files = new RegexIterator( $flat, '/\.php$/i' );

    if ( $files ) {

        $output = '';
        foreach($files as $name=>$file) {
            /**
             * Match and return all instances of apply_filters(**) or do_action(**)
             * The regex will match the following
             * - Any depth of nesting of parentheses, so apply_filters( 'filter_name', parameter( 1,2 ) ) will be matched
             * - Whitespaces that might exist between apply_filters or do_action and the first parentheses
             */
            // Use file_get_contents to get contents of the php file
            $get_file_content =  file_get_contents( $file );
            // Use htmlspecialchars() to avoid HTML in filters from rendering in page
            $save_content = htmlspecialchars( $get_file_content );
            preg_match_all( '/(apply_filters|do_action)\s*(\([^()]*(?:(?-1)[^()]*)*+\))/', $save_content, $matches );

            // Build an array to hold the file name as key and apply_filters/do_action values as value
            if ( $matches[0] )
                $array[$name] = $matches[0];
        }
        foreach ( $array as $file_name=>$value ) {

            $output .= '<ul>';
                $output .= '<strong>File Path: ' . $file_name .'</strong></br>';
                $output .= 'The following filters and/or actions are available';
                foreach ( $value as $k=>$v ) {
                    $output .= '<li>' . $v . '</li>';
                }
            $output .= '</ul>';
        }
        return $output;
    }

    return false;
}

您可以在模板,前端或后端上使用

echo get_all_filters_and_actions( 'E:\xammp\htdocs\wordpress\wp-includes' );

这将打印

在此处输入图片说明

选项2

此选项运行起来有点贵。此函数返回可以找到过滤器/操作的行号。

在这里,我们用于file将文件分解为数组,然后搜索并返回过滤器/操作和行号

function get_all_filters_and_actions2( $path = '' )
{
    //Check if we have a path, if not, return false
    if ( !$path ) 
        return false;

    // Validate and sanitize path
    $path = filter_var( $path, FILTER_SANITIZE_URL );
    /**
     * If valiadtion fails, return false
     *
     * You can add an error message of something here to tell
     * the user that the URL validation failed
     */
    if ( !$path ) 
        return false;

    // Get each php file from the directory or URL  
    $dir   = new RecursiveDirectoryIterator( $path );
    $flat  = new RecursiveIteratorIterator( $dir );
    $files = new RegexIterator( $flat, '/\.php$/i' );

    if ( $files ) {

        $output = '';
        $array  = [];
        foreach($files as $name=>$file) {
            /**
             * Match and return all instances of apply_filters(**) or do_action(**)
             * The regex will match the following
             * - Any depth of nesting of parentheses, so apply_filters( 'filter_name', parameter( 1,2 ) ) will be matched
             * - Whitespaces that might exist between apply_filters or do_action and the first parentheses
             */
            // Use file_get_contents to get contents of the php file
            $get_file_contents =  file( $file );
            foreach ( $get_file_contents as  $key=>$get_file_content ) {
                preg_match_all( '/(apply_filters|do_action)\s*(\([^()]*(?:(?-1)[^()]*)*+\))/', $get_file_content, $matches );

                if ( $matches[0] )
                    $array[$name][$key+1] = $matches[0];
            }
        }

        if ( $array ) {
            foreach ( $array as $file_name=>$values ) {
                $output .= '<ul>';
                    $output .= '<strong>File Path: ' . $file_name .'</strong></br>';
                    $output .= 'The following filters and/or actions are available';

                    foreach ( $values as $line_number=>$string ) {
                        $whitespaces = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
                        $output .= '<li>Line reference ' . $line_number . $whitespaces . $string[0] . '</li>';
                    }
                $output .= '</ul>';
            }
        }
        return $output;

    }

    return false;
}

您可以在模板,前端或后端上使用

echo get_all_filters_and_actions2( 'E:\xammp\htdocs\wordpress\wp-includes' );

这将打印

在此处输入图片说明

编辑

基本上,我可以在不使脚本超时或内存不足的情况下完成所有工作。使用选项2中的代码,就像转到源代码中的所述文件和所述行,然后获取过滤器/操作的所有有效参数值一样简单,而且重要的是,获得函数和进一步的上下文。使用过滤器/操作


1
您有太多的空闲时间;)但是最后,仅知道过滤器是什么,还不知道预期的参数值和结果是什么,如果没有bactracking来获取doc块,就无法从源头上实现。核心文件,在非核心插件和主题中可能根本不可用。
马克·卡普伦

1
@MarkKaplun这只是我快速进行的工作:-)。上面的功能至少可以告诉您过滤器和操作在特定的plugin / theme / core目录中的哪个位置。回到源头并确保您了解特定过滤器的特定功能仍然非常重要。一些插件和主题的文档记录很少,因此您仍然需要某种知识和背景知识才能知道或弄清楚特定功能在特定过滤器中的作用;-)
Pieter Goosen 2015年

@PieterGoosen是的,我通常可以跳回去看看源代码。如果我首先这样做,则意味着该插件具有挂钩,但不一定具有它们的文档块。但是,如果我看看它们的实际用途,它可以帮助我弄清楚它们是否有价值。无论如何,它们看起来可能很棒。我什至可以将它们修改为仅写入HTML文件的第2个,因为这样我就可以将函数声明粘贴在本地服务器上的MU插件中,然后从WP CLI运行它。
yonatron

@yonatron很高兴我的两分钱在某种程度上有所帮助。如果您打算从我的代码中编写自己的修改,则可以随时添加代码和说明作为答案(这将是很不错的; ;-)。享受
Pieter Goosen 2015年

1
@PieterGoosen您花了多少时间编写该脚本以及进行文档编写,其
精妙的

6

听起来像WP Parser可以满足您的需求。它用于生成正式的开发人员参考。它列出了参数,@ since标签和对源的引用。它适用于所有WordPress插件,可以通过命令行访问:

wp parser create /path/to/source/code --user=<id|login>

1
我对该脚本不是很熟悉,但是似乎需要过滤器或操作来对其进行详细记录。非常感谢@Rarst ;-)的反馈
Pieter Goosen

我还没有尝试过,但是根据描述,我认为Pieter的关注已经达到目标。我想找到所有的钩子,而不仅仅是格式正确的doc块之前的钩子。我认为那些花时间使用WordPress约定注释其钩子/函数的人已经在运行此类脚本并将API参考发布在其支持站点上。我意识到其中存在固有的风险,因为如果开发人员未公开记录过滤器,则可能会在没有警告的情况下进行更改/弃用,但是对于我使用的某些插件,我迫不及待地希望文档能在线显示。
yonatron

它还解析未记录的钩子。示例:developer.wordpress.org/reference/hooks/graceful_fail
Jan Beck

4

速度与激情

好的ol' *nix命令行总是很方便:

# grep  --line-number                                         \
        --exclude-dir=/path/to/some/directory                 \
        --include=*.php                                       \ 
        --recursive                                           \
        "add_filter\|do_action\|apply_filters"                \
        /path/to/wp-content/plugins/some-plugin               \ 
 | less

通过提供更多选项#man grep

然后我们甚至可以创建一个简单的bash脚本wp-search.sh

#!/bash/bin
grep --line-number                            \
    --exclude-dir=/path/to/some/directory     \
    --include=*.$1                            \
    --recursive $2 $3

并运行它。

 # bash wp-search.sh php "add_filter\|do_action\|apply_filters" /path/to/some-plugin

漂亮的输出

我们可以使用--colorattribute来为的输出着色grep,但是请注意,它不适用于less

另一种选择是为搜索结果生成HTML表。

这是awk我构建的示例,该示例将搜索结果作为HTML表输出到results.html文件中:

  | sed 's/:/: /2' \
  | awk ' \
        BEGIN { \
            print "<table><tr><th>Results</th><th>Location</th></tr>"  \
        } \
        { \
            $1=$1; location=$1; $1=""; print "<tr><td>" $0 "</td><td>" location "</td><tr>" \
        } \
        END {  \
           print "</table>" \
       }' \
 > results.html

在这里我用这种伎俩来删除所有前导空格和这一个打印所有领域,但第一个。

sed在这里只是在第二个冒号(:)之后添加多余的空间,以防万一那里没有空间。

脚本

我们可以将其添加到wp-search.sh脚本中:

#!/bash/bin
grep   --with-filename \
       --line-number \
       --exclude-dir=/path/to/some/directory \
       --include=*.$1 \
       --recursive $2 $3 \
| sed 's/:/: /2' \
| awk ' BEGIN { \
        print "<table><tr><th>Results</th><th>Location</th></tr>"  \
    } \
    { \
        $1=$1; location=$1; $1=""; print "<tr><td>" $0 "</td><td>" location "</td><tr>" \
    } \
    END {  \
        print "</table>" \
    }' \
> /path/to/results.html

您必须根据需要调整/path/to/some/directory/path/to/results.html

示例-搜索插件

如果我们在wordpress-importer插件上尝试使用以下命令:

bash wp-search.sh php "add_filter\|do_action" /path/to/wp-content/plugins/wordpress-importer/

那么该results.html文件将显示为:

结果

示例-搜索核心

我对核心进行了时间测试:

time bash wp-search.sh php "add_filter\|do_action" /path/to/wordpress/core/

real    0m0.083s
user    0m0.067s
sys     0m0.017s

而且速度很快!

笔记

为了获得更多的上下文,我们可以使用-C NUMBERgrep。

我们可以通过各种方式修改HTML输出,但希望您可以根据需要进行进一步调整。


谢谢!我在紧要关头使用grep,但是我对shell东西还是个新手,我什至从来没有考虑过将管道用于OR。我想添加的另一件事是一些漂亮打印的选项。上面的grep行的输出仍然很难浏览。
yonatron

2
我用漂亮的印刷品@yonatron示例更新了答案
birgire
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.