如何删除由插件创建的挂钩操作?

时间:2020-07-01 作者:codeinwill

public function orddd_capabilities() {
        $role = get_role( \'shop_manager\' );
        if ( $role != \'\' ) {
            $role->add_cap( \'manage_options\' );
        }
    }
add_action( \'admin_init\', array( &$this, \'orddd_capabilities\' ) );
此操作是由插件添加的,并且始终会重新应用;“管理\\u选项”;使用用户角色编辑器禁用\\u管理器后,可以购买它。如何使用函数禁用此操作。我的孩子主题的php?

1 个回复
SO网友:Ivan Shatsky

这个很棘手。您需要删除一个钩住的函数,该函数是动态创建的类实例的一个成员,以及以下常用方法remove_action( \'hook_name\', \'hook_function\', priority ) 甚至remove_action( \'hook_name\', array( \'class_name\', \'member_function\' ), priority ) 行不通。我曾经不得不解决一个类似的问题。我的函数更复杂,我必须更改这样一个挂钩函数的优先级。花了几次时间后,我完成了以下代码(根据您的需要进行修改):

function get_hooked_function( $hook = \'\', $function = \'\' ) {
    global $wp_filter;
    if ( isset( $wp_filter[$hook]->callbacks ) ) {      
        array_walk( $wp_filter[$hook]->callbacks, function( $callbacks, $priority ) use ( &$hooks ) {           
            foreach ( $callbacks as $id => $callback )
                $hooks[] = array_merge( [ \'id\' => $id, \'priority\' => $priority ], $callback );
        });         
    } else {
        return NULL;
    }
    foreach( $hooks as &$item ) {
        // skip if callback does not exist
        if ( !is_callable( $item[\'function\'] ) ) continue;

        // function name as string or static class method eg. \'Foo::Bar\'
        if ( is_string( $item[\'function\'] ) ) {
            if ( $item[\'function\'] === $function ) return [ $function, $item[\'priority\'] ];
        } elseif ( is_array( $item[\'function\'] ) ) {
            if ( $item[\'function\'][1] === $function ) return [ $item[\'function\'], $item[\'priority\'] ];
        }       
    }
    return NULL;
}
add_action( \'admin_init\', function () {
    if ( $hooked_function = get_hooked_function( \'admin_init\', \'orddd_capabilities\' ) )
        remove_action( \'admin_init\', $hooked_function[0], $hooked_function[1] );
}, 9 );
这个get_hooked_function() 函数遍历全局$wp_filter 的数组WP_Hook 对象,其中注册了所有挂钩(更准确地说,仅通过名为此函数第一个参数的项),并搜索名为其第二个参数的函数。当钩子注册到全局函数时,它将返回其名称和注册的优先级,例如。

$result = Array (
    [0] => register_admin_color_schemes
    [1] => 1
)
但是当一个钩子注册到一个类成员函数时,它会返回一个数组,如

$result = Array (
    [0] => Array (
        [0] => order_delivery_date Object
        [1] => orddd_capabilities
    )
    [1] => 10
)
(此函数的基本思想取自this stackoverflow答案,您可以在那里查看其他技术细节)。然后$result[0] 数组适用于与一起使用remove_action() 作用接下来,我们应该确保我们的代码将在插件设置挂钩之后,但在触发挂钩之前被调用。最简单的方法是将代码注册到同一个钩子上,优先级稍微低一点。因为你的插件用默认的优先级注册它的钩子10, 要取消注册,我们可以使用以下优先级9.

请注意,由于以下原因,此解决方案无法与4.7之前的WordPress配合使用this 过滤器处理机制的变化(尽管我相信你没有使用那么古老的东西)。

Afterwords

如果有人想搜索关于如何更改这种挂钩函数的优先级的答案,那么解决方案是

add_action( \'<HOOK_NAME>\', function () {
    if ( $hooked_function = get_hooked_function( \'<HOOK_NAME>\', \'<FUNCTION_NAME>\' ) )
        if ( remove_action( \'<HOOK_NAME>\', $hooked_function[0], $hooked_function[1] ) )
            add_action( \'<HOOK_NAME>\', $hooked_function[0], <NEW_PRIORITY> );
}, <SOME_PRIORITY_LESS_THAN_MIN_OF_OLD_AND_NEW_PRIORITIES> );

相关推荐

Conditional action hooks

我正在开发一个使用AJAX的插件,但我在控制代码流方面遇到了困难。我想在运行条件后挂接函数。我的钩子在控制结构内部添加时不会启动,但在外部会启动。我还有一个触发AJAX请求的事件,这只能在用户点击触发事件后,在加载所有DOM之后发生。AJAX请求告诉PHP函数设置cookie。它设置了cookie,但在阅读关于cookie的PHP文档时,我发现它们只能在发送任何输出后设置,但我还是做到了这一点?我读过WordPress初始化序列,但这并没有帮助我解决这个问题。这是我的密码:add_action(\'wp_