4

例如,我有这样的代码:

<?php
/**
 * Order
 *
 * The WooCommerce order class handles order data.
 *
 * @class       WC_Order
 * @version     1.6.4
 * @package     WooCommerce/Classes
 * @category    Class
 * @author      WooThemes
 */
class WC_Order {

    /** @public int Order (post) ID */
    public $id;

    /** @public string Order status. */
    public $status;

    /** @public string Order date (placed). */
    public $order_date;

    /** @public string Order date (paid). */
    public $modified_date;

    /** @public string Note added by the customer. */
    public $customer_note;

    /** @public array Order (post) meta/custom fields. */
    public $order_custom_fields;

        global $wpdb, $woocommerce;

        if ( empty( $type ) )
            $type = array( 'line_item' );

        if ( ! is_array( $type ) )
            $type = array( $type );

        $items = $this->get_items( $type );

        $count = 0;

        foreach ( $items as $item ) {
            if ( ! empty( $item['qty'] ) )
                $count += $item['qty'];
            else
                $count ++;
        }

        return apply_filters( 'woocommerce_get_item_count', $count, $type, $this );
    }

    /**
     * Return an array of fees within this order.
     *
     * @access public
     * @return array
     */
    public function get_fees() {
        return $this->get_items( 'fee' );
    }

    /**
     * Return an array of taxes within this order.
     *
     * @access public
     * @return void
     */
    public function get_taxes() {
        return $this->get_items( 'tax' );
    }

    /**
     * Get taxes, merged by code, formatted ready for output.
     *
     * @access public
     * @return void
     */
    public function get_tax_totals() {
        $taxes      = $this->get_items( 'tax' );
        $tax_totals = array();

        foreach ( $taxes as $key => $tax ) {

            $code = $tax[ 'name' ];

            if ( ! isset( $tax_totals[ $code ] ) ) {
                $tax_totals[ $code ] = new stdClass();
                $tax_totals[ $code ]->amount = 0;
            }

            $tax_totals[ $code ]->is_compound       = $tax[ 'compound' ];
            $tax_totals[ $code ]->label             = isset( $tax[ 'label' ] ) ? $tax[ 'label' ] : $tax[ 'name' ];
            $tax_totals[ $code ]->amount           += $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ];
            $tax_totals[ $code ]->formatted_amount  = woocommerce_price( $tax_totals[ $code ]->amount );
        }

        return apply_filters( 'woocommerce_order_tax_totals', $tax_totals, $this );
    }

    /**
     * has_meta function for order items.
     *
     * @access public
     * @return array of meta data
     */
    public function has_meta( $order_item_id ) {
        global $wpdb;

        return $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value, meta_id, order_item_id
            FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id = %d
            ORDER BY meta_key,meta_id", absint( $order_item_id ) ), ARRAY_A );
    }

    /**
     * Get order item meta.
     *
     * @access public
     * @param mixed $item_id
     * @param string $key (default: '')
     * @param bool $single (default: false)
     * @return void
     */
    public function get_item_meta( $order_item_id, $key = '', $single = false ) {
        return get_metadata( 'order_item', $order_item_id, $key, $single );
}

我想用三个选项匹配所有的 Wordpress 钩子:“do_action”和“apply_filters”:apply_filters( 'woocommerce_order_tax_totals', $tax_totals, $this ), file, line number

我正在尝试做的一个例子可以在这里看到:http: //etivite.com/api-hooks/buddypress/trigger/apply_filters/bp_get_total_mention_count_for_user/

http://adambrown.info/p/wp_hooks/hook/activated_plugin?version=3.6&file=wp-admin/includes/plugin.php

我确实试图拉出一些东西但没有成功:

<?php
$path = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/iphorm-form-builder';
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
    if (substr($filename, -3) == 'php') {
        $file = file($filename);
        if ($file !== false) {
            $matches1 = preg_grep( '/do_action\((.+)\);/', $file);
            $matches2 = preg_grep( '/apply_filters\((.+)\);/', $file );
            $arr = array_filter(array_merge($matches1, $matches2));
            $out = '';
            echo "found in $filename:";
            echo "<pre>";
            foreach ($arr as $key => $value) {
                $out .= $file[$key-2];
                $out .= $file[$key-1];
                $out .= $file[$key];
                $out .= $file[$key+1];
                $out .= $file[$key+2];
            }
            echo htmlentities($out);
            echo "</pre>";
        } else {
            echo "failed reading to array";
        }
    }
}
4

3 回答 3

1

这可以通过利用内置的 shell 命令非常简单地完成。

<?php
$path = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/iphorm-form-builder';
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
    if (substr($filename, -3) == 'php') {
        $context = shell_exec('grep -H -n -C4 do_action ' . escapeshellarg($filename));
        if (!empty($context)) {
            echo "found in $filename:";
            echo "<pre>";
            echo htmlentities($context);
            echo "</pre>";
        } else {
            echo "failed reading to array";
        }
    }
}

相关文件:

php shell_exec

通过 shell 执行命令并将完整的输出作为字符串返回

php 转义shellarg

转义要用作 shell 参数的字符串

重击

   Grep  searches the named input FILEs (or standard input if no files are
   named, or the file name - is given) for lines containing a match to the
   given PATTERN.  By default, grep prints the matching lines.

   -C NUM, --context=NUM
      Print  NUM lines of output context.  Places a line containing --
      between contiguous groups of matches.

   -H, --with-filename
      Print the filename for each match.

   -n, --line-number
      Prefix each line of output with the line number within its input
      file.

编辑

根据您的项目中有多少目录和文件,它可能无法执行。您基本上是在为每个文件在新外壳中创建一个新进程。那不是很好。如果您希望获得大量数据并稍后解析出来,请改为执行以下操作:

<?php
$path = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/iphorm-form-builder';
$grep = shell_exec('grep --include=*.php -RHn -C4 do_action ' . escapeshellarg($path));
$matches = explode("\n--\n", $grep);
if (empty($matches)) {
    echo "failed reading to array";
}
else {
    foreach ($matches as $match) {
        echo "<pre>";
        echo htmlentities($match);
        echo "</pre>";
    }
}
于 2013-09-18T20:15:54.003 回答
0

您不需要逐行遍历文件数据。只需读取变量中的数据并应用正则表达式:

$data = file_get_contents( $filename );
if (preg_match_all(
      '~((?:[^\n]*\n){0,4}) *do_action\s*\(\s*([^)]+)\s*\)\s*;[^\n]*\n((?:[^\n]*\n){0,4})~',
       $data, $arr)) {
   // match found, now dump the results
   // $arr[1] will print 4 lines before the match
   // $arr[2] will print function arguments for do_action
   // $arr[3] will print 4 lines after the match
   print_r($arr);
}
于 2013-09-18T19:29:35.840 回答
0

鉴于 PHP 正则表达式引擎的限制,仅靠正则表达式无法做到这一点。具体来说,让我感到惊讶的是,你不能有可变长度的外观。

你需要后看的原因是如果你在连续的行上出现了do_actionapply_filters,那么如果你没有前瞻,第一个匹配将阻止第二个匹配,即使你使用前瞻,也没有办法得到第二场比赛的前两行没有后视。更不用说我什至不知道您是否可以在结果中包含环视断言的内容。

此解决方案创建一个正则表达式来查找函数出现的行,然后使用另外两个正则表达式来查找之前和之后的行。在设计正则表达式时,我注意注意文件的开头和结尾。

$offset = 0;
while (preg_match('/^.*?(?:apply_filters|do_action)\s*\(.+?\)\s*;.*(?:\n\r|\n|\r|$)/m', $file, $match, PREG_OFFSET_CAPTURE, $offset))
{
    $index = $match[0][1];
    $offset = $index + strlen($match[0][0]);
    $hasBefore = preg_match('/(?:.*(?:\n\r|\n|\r).*$)|[^\n\r].*$/', 
        substr($file, 0, $index), $beforeMatch);
    $hasAfter = preg_match('/^(?:.*(?:\n\r|\n|\r|$)){0,2}/', 
        substr($file, $offset), $afterMatch);

    if ($hasBefore) print_r($beforeMatch);
    print_r($match[0][0]);
    if ($hasAfter) print_r($afterMatch);
}

phpFiddle

这仅显示之前的两行和之后的两行。如果你想要更多,你可以使用重复,但在我尝试的解决方案中,这似乎是操作真正想要的。

于 2013-09-19T00:57:33.390 回答