alleyinteractive/wp-captain-hook

WordPress中操作私有动作/过滤器回调的工具。

v1.0.0 2024-09-09 14:47 UTC

This package is auto-updated.

Last update: 2024-09-10 03:39:29 UTC


README

Captain Hook 是一个库,帮助 WordPress 开发者操作被动作和过滤器钩入的对象和方法。

关于

通常,插件会在函数作用域或全局作用域之外创建一个对象实例,然后使用该实例将方法钩入动作或过滤器。以下是一个例子

class Plugin_Main {
  public function __construct(
    protected \Logger $logger
  ) {
    add_action( 'init', [ $this, 'init' ], 1 );
    add_filter( 'the_content', [ $this, 'filter_the_content' ], 99 );
  }

  public function init() {
    register_post_type( 'book' );
    register_taxonomy( 'genre', 'book' );
  }

  public function filter_the_content( $content ) {
    if ( preg_match_all( '/\[([^\)]+)\]\((\d+)\)/', $content, $matches, PREG_SET_ORDER ) ) {
      foreach ( $matches as $match ) {
        $book = get_post( $match[2] );
        if ( $book ) {
          $content = str_replace( $match[0], '<a href="' . get_permalink( $book ) . '">' . $match[1] . '</a>', $content );
        } else {
          $this->logger->error( 'Book not found: ' . $match[2] );
        }
      }
    }
    return $content;
  }

  public function get_logger() {
    return $this->logger;
  }

  public function set_logger( \Logger $logger ) {
    $this->logger = $logger;
  }
}
add_action( 'after_setup_theme', function () {
  new Plugin_Main( new \Logger( 'path/to/file.log' ) );
} );

如果开发者想要从 init 动作中取消钩或修改 init 方法,他们需要访问 $plugin 实例。由于实例是在创建它的匿名函数作用域之外创建的,这是不可能的。

Captain Hook 为开发者提供了一种访问和操作这些对象和方法的方法,即使它们不可从全局作用域访问。该库的功能包括

  • 强制删除动作或过滤器:从钩子中删除动作或过滤器。
  • 重新优先级排序动作和过滤器:更改动作或过滤器方法的优先级。
  • 检索对象实例:获取钩入动作或过滤器的其他方法不可访问的对象实例。

安装

使用以下命令安装最新版本

$ composer require alleyinteractive/wp-captain-hook

基本用法

强制删除动作或过滤器

<?php
use function Alley\WP\remove_action_by_force;
use function Alley\WP\remove_filter_by_force;

remove_action_by_force( 'init', [ '\Plugin_Main', 'init' ], 1 );
remove_filter_by_force( 'the_content', [ '\Plugin_Main', 'filter_the_content' ], 99 );

重新优先级排序动作和过滤器

<?php
use function Alley\WP\reprioritize_action;
use function Alley\WP\reprioritize_filter;

reprioritize_action( 'init', [ '\Plugin_Main', 'init' ], 1, 10 );
reprioritize_filter( 'the_content', [ '\Plugin_Main', 'the_content' ], 99, 20 );

检索对象实例

以下是一个使用上述插件代码的虚构示例。该代码使用依赖注入将基于文件的记录器传递给 Plugin_Main 类。假设我们想要将日志记录到 Redis 而不是文件,看起来我们应该能够使用 set_logger() 方法替换依赖,然而,我们无法这样做,因为我们无法访问 Plugin_Main 的实例。下面,我们利用 get_hooked_object 获取插件实例,然后调用其上的 set_logger 方法,将文件记录器替换为 Redis 记录器。

<?php
use function Alley\WP\get_hooked_object;

$plugin = get_hooked_object( 'init', [ '\Plugin_Main', 'init' ], 1 );
$plugin->set_logger( new \Redis_Logger() );

许可证

GPL-2.0-or-later

维护者

Alley Interactive