hooks - How can I remove a hooked action created by a plugin?

public function orddd_capabilities() {$role = get_role( 'shop_manager' );if ( $role != '' ) {$role-&

public function orddd_capabilities() {
        $role = get_role( 'shop_manager' );
        if ( $role != '' ) {
            $role->add_cap( 'manage_options' );
        }
    }
add_action( 'admin_init', array( &$this, 'orddd_capabilities' ) );

this action was added by a plugin and would always reapply the "manage_options" capabilities to shop_manager after I disable it using User Role Editor. How can I disable this action using the function.php of my child theme?

public function orddd_capabilities() {
        $role = get_role( 'shop_manager' );
        if ( $role != '' ) {
            $role->add_cap( 'manage_options' );
        }
    }
add_action( 'admin_init', array( &$this, 'orddd_capabilities' ) );

this action was added by a plugin and would always reapply the "manage_options" capabilities to shop_manager after I disable it using User Role Editor. How can I disable this action using the function.php of my child theme?

Share Improve this question edited Jul 2, 2020 at 3:46 codeinwill asked Jul 1, 2020 at 20:06 codeinwillcodeinwill 413 bronze badges 3
  • Note that the plugin uses &$this, it should be $this, the use of & is for compatibility with PHP v4 which hasn't worked with WordPress in decades. Which plugin is this? – Tom J Nowell Commented Jul 1, 2020 at 21:12
  • @TomJNowell I'm not the OP, but I think this is Order Delivery Date Pro from Tyche Software. Their coding style sometimes make me cry. – Ivan Shatsky Commented Jul 1, 2020 at 21:22
  • 2 It may turn out that this can't be answered without a copy of the plugin and contacting their support channels, as to answer this would need to know what $this is referring to and if we can get references to it – Tom J Nowell Commented Jul 1, 2020 at 21:24
Add a comment  | 

1 Answer 1

Reset to default 1

This one is tricky. You need to remove a hooked function which is a member of dynamically created class instance and the usual methods like remove_action( 'hook_name', 'hook_function', priority ) and even remove_action( 'hook_name', array( 'class_name', 'member_function' ), priority ) won't work. I once had to solve a similar problem. Mine was more complicated, I had to change the priority of such a hooked function. After spending a couple of time I've finished up with the following code (modified according to your needs):

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 );

The get_hooked_function() function walks through global $wp_filter array of WP_Hook objects where all hooks are registered (to be more precise only through its item named as this function first parameter) and searches for the function named as its second parameter. When a hook is registered with a global function, it returns its name and registered priority, e.g.

$result = Array (
    [0] => register_admin_color_schemes
    [1] => 1
)

but when a hook is registered with a class member function, it returns an array like

$result = Array (
    [0] => Array (
        [0] => order_delivery_date Object
        [1] => orddd_capabilities
    )
    [1] => 10
)

(the basic idea of this function is taken from this stackoverflow answer, you can look there for additional technical details). Then the $result[0] array is applicable to use with remove_action() function. Next we should make sure that our code will be called after the hook is set by plugin, but before it is fired. The most simple way to do it is to register our code to the same hook with a slightly less priority. Since your plugin register its hook with the default priority 10, to deregister it we can use a priority of 9.

Please note that this solution won't work with WordPress earlier than 4.7 due to this change in filter processing mechanism (though I believe you don't use something that ancient).

Afterwords

If someone would search an answer on how to change the priority on such a hooked function, the solution is

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> );

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742299413a4417756.html

相关推荐

  • hooks - How can I remove a hooked action created by a plugin?

    public function orddd_capabilities() {$role = get_role( 'shop_manager' );if ( $role != '' ) {$role-&

    16小时前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信