inpsyde/object-hooks-remover

用于移除使用对象方法或闭包的 WordPress 钩子回调的包。

1.0.0 2024-05-20 17:03 UTC

This package is auto-updated.

Last update: 2024-09-20 23:03:38 UTC


README

用于移除使用对象方法或闭包的 WordPress 钩子回调的包。

Static Analysis Unit Tests

这是什么?

WordPress 插件 API 部分实现不完整。

add_actionadd_filter 接受任何类型的 PHP 可调用函数作为 "回调"。

  • 命名函数
  • 静态对象方法
  • 动态对象方法
  • 匿名函数
  • 可调用对象

用于移除钩子的函数 remove_actionremove_filter 只在命名函数和静态对象方法(5种回调类型中的2种)上工作无误。

其余涉及对象实例的 remove_actionremove_filter 只能在访问用于添加钩子的对象实例时使用,但很多时候这并不可能。

此包提供了六个函数,可以在不访问原始对象实例的情况下移除使用对象方法或闭包的钩子。

包函数包括

  • Inpsyde\remove_object_hook()
  • Inpsyde\remove_closure_hook()
  • Inpsyde\remove_static_method_hook()
  • Inpsyde\remove_instance_hook()
  • Inpsyde\remove_invokable_hook()
  • Inpsyde\remove_all_object_hooks()

您可能注意到操作和过滤器之间没有区别,因为在移除时,两者之间绝对没有区别。

所有函数的返回值是移除的回调数。

Inpsyde\remove_object_hook()

function remove_object_hook(
	string $hook,
	class-string $targetClassName,
	?string $methodName = null,
	?int $targetPriority = null,
	bool $removeStaticCallbacks = false
): int

此函数用于移除使用对象方法的钩子回调。默认情况下,它仅针对动态方法,但可以通过将 true 传递给最后一个参数来用于静态方法。

使用示例

// Somewhere...
class Foo
{
	public function __construct()
	{
		add_action('init', [$this, 'init'], 99);
		add_action('template_redirect', [__CLASS__, 'templateRedirect']);
	}
	
	public function init(): void
	{
	}
	
	public static function templateRedirect(): void
	{
	}
}

new Foo();

// Somewhere else...
Inpsyde\remove_object_hook('init', Foo::class, 'init');
Inpsyde\remove_object_hook('init', Foo::class, 'init', removeStaticCallbacks: true);

Inpsyde\remove_closure_hook()

此函数针对使用匿名函数(也称为闭包)添加的钩子回调。

闭包是最难移除的回调之一,因为很难区分它们。

事实上,在 PHP 中,所有闭包都是同一类 Closure 的实例,并且由于没有方法名,很难区分一个闭包与另一个闭包。

此函数使用两种方式来区分闭包

  • 闭包绑定到的对象
  • 闭包参数的名称和类型

Inpsyde\remove_closure_hook 的签名是

function remove_closure_hook(
	string $hook,
	?object $targetThis = null,
	?array $targetArgs = null,
	?int $targetPriority = null
): int 

第二个可选参数$targetThis,可以用来识别要移除的闭包的 $this

它可以

  • null,表示 "全部",即函数不会考虑闭包所绑定的对象,以确定是否应该移除闭包
  • false,函数只会移除静态闭包或没有绑定对象的闭包
  • 包含类名的字符串,函数只会移除具有给定类绑定对象的闭包
  • 对象实例,函数只会移除绑定到给定对象的闭包

第三个可选参数$targetArgs 是一个数组,可以用来通过参数区分闭包。

例如,以下这样的闭包

$closure = function (string $foo, int $bar, $baz) { /*... */ };

可以通过参数 名称 来定位,传递如下数组

['$foo', '$bar', '$baz']

或通过参数 名称类型 来定位,传递如下数组

['$foo' => 'string', '$bar' => 'int', '$baz' => null]

两种样式不能混合使用,如果对一个参数使用了类型声明,则必须对所有参数都使用类型声明。如果任何参数没有类型声明,必须使用null"mixed"

还可以将null作为第三个参数传递(或者不传递任何参数,这与传递null相同,因为参数默认为null),在这种情况下,将要删除的闭包将只通过绑定的$this来区分。

当第二个和第三个参数都为null时(这是默认情况),将删除添加到指定钩子中的所有闭包(可选按优先级过滤)。

使用示例

// Somewhere in a plugin...
class Foo
{
	public function __construct() {
		add_filter('the_title', function($title) { /* ... */ });
		add_filter('the_content', function(string $content) { /* ... */ });
	}
}

new Foo();

// Somewhere else...
Inpsyde\remove_closure_hook('the_title', Foo::class, ['$title']);
Inpsyde\remove_closure_hook('the_content', Foo::class, ['$content' => 'string'], 10);

Inpsyde\remove_static_method_hook()

remove_object_hook()类似,此函数只针对静态方法

签名是

function remove_static_method_hook(
	string $hook,
	class-string $targetClassName,
	?string $targetMethodName = null,
	?int $targetPriority = null
): int

使用示例

// Somewhere...
class Foo {

	public static function instance()
	{
		add_action('init', [__CLASS__, 'init'], 99);
	}

	public static function init()
	{
	}
}

Foo::instance();

// Somewhere else...
Inpsyde\remove_static_method_hook('init', Foo::class, 'init');

即使静态类方法可以通过remove_action / remove_filter删除,此函数仍然可能有用,因为它可以从任何优先级删除回调,甚至无需指定方法名称。

例如,我们可以使用以下方法删除附加到init钩子的Foo::class的所有静态方法

remove_static_method_hook('init', Foo::class);

Inpsyde\remove_instance_hook()

此函数可用于删除使用特定对象实例添加的钩子回调。

当访问用于添加一些钩子的确切实例时,可以通过核心函数remove_action / remove_filter删除这些钩子,但此函数仍然有用,因为可以在单个调用中删除使用该实例的所有钩子,无论方法或优先级如何。

remove_instance_hook的签名是

remove_instance_hook( 
	string $hook,
	object $targetObject,
	?int $targetPriority = null
): int;

使用示例

// Somewhere...
class Foo
{
	public function __construct()
	{
		add_filter('the_title', [$this, 'the_title_early', 1]);
		add_filter('the_title', [$this, 'the_title_late', 9999]);
		add_filter('the_content', [$this, 'the_content']);
	}
}

global $foo;
$foo = new Foo();


// Somewhere else...
global $foo;
Inpsyde\remove_instance_hook('the_title', $foo); // remove 2 callbacks
Inpsyde\remove_instance_hook('the_content', $foo);

Inpsyde\remove_invokable_hook()

此函数针对使用可调用对象添加的钩子。

签名

function remove_invokable_hook(
	string $hook,
	class-string $targetClassName,
	?int $targetPriority = null
): int;

使用示例

// Somewhere...
class Foo
{
	public function __construct()
	{
		add_filter('template_redirect', $this);
	}
    
	public function __invoke()
	{
	}
}

new Foo();


// Somewhere else...
Inpsyde\remove_invokable_hook('template_redirect', Foo::class);

Inpsyde\remove_all_object_hooks()

function remove_all_object_hooks(
	class-string|object $targetObject,
	?bool $removeStaticCallbacks = null
): int

此函数用于删除使用给定对象或类名称的所有钩子回调。

当传递对象实例时,它删除使用该特定实例的所有钩子回调。

当传递类名称时,它删除使用该类(无论实例)的所有钩子回调。

当传递对象实例且$removeStaticCallbacks参数为true时,将删除静态方法

  • 传递类名称且$removeStaticCallbacks参数不为false
  • 删除静态方法

使用示例

// Somewhere...
class Foo
{
	public function __construct()
	{
		add_action('init', [$this, 'init'], 99);
		add_action('template_redirect', [__CLASS__, 'templateRedirect']);
	}
	
	public function init(): void
	{
	}
	
	public static function templateRedirect(): void
	{
	}
}

global $foo;
$foo = new Foo();

// Somewhere else...
global $foo;
Inpsyde\remove_all_object_hooks($foo); // remove "init" hook
Inpsyde\remove_all_object_hooks(Foo::class); // would remove both hooks, but only one left
Inpsyde\remove_all_object_hooks($foo, true); // would remove both hooks, but none left
Inpsyde\remove_all_object_hooks(Foo::class, false); // would remove the "init" hook, but none left

最低要求

Object Hooks Remover是一个Composer包,可以通过包名inpsyde/object-hooks-remover安装。

它没有依赖项,需要PHP 7.4+

经过测试并保证与WP 5.9+兼容,但应至少与WP 5.3+兼容(这是第一个官方支持PHP 7.4的版本)。

许可证

此存储库是免费软件,根据GNU通用公共许可证第2版或(根据您的选择)任何较新版本的条款发布。有关完整许可证,请参阅LICENSE