Non existing Callbacks
One of the nice things is, that neither do_action()
, nor apply_filters()
do trigger an error if a callback isn’t present. This means that its the safest way to insert plugin data into templates: If a plugin is turned off and do_action()
/apply_filters()
don’t find the callback in the global $wp_filters
array, nothing happens.
Error Output
Now when you’re calling remove_filter()
in the function/method that originally hooked the callback, the callback simply will be removed from the global array, which means that the callback will never be executed as it’s not registered anymore.
The solution is simple: Remove the callback after it was triggered, by removing it from within the callback itself.
Removing Callbacks
We all know that WPs plugin “API” is a pain when it comes to removing. The problem mainly is the strange construct to add “unique” names to keys in the global $wp_filter;
array. A very simple solution is to just use __METHOD__
and call filters that you want to remove in static context:
class FOoooo
{
public function __construct()
{
add_filter( 'hook', array( __CLASS__, 'bar' ) );
}
public static function bar( $baz )
{
remove_filter( current_filter(), __METHOD__ );
return $baz;
}
}
While this isn’t nice, it’s … sort of a solution for some use cases. But don’t even think about removing a closure.
Above just removes the callback, still executes it. Still you can go further and use remove_all_actions()
(or remove_all_filters()
).
// Check if a callback is attached and tell about the deprecated stuff
if ( has_action( 'before_main_content' ) )
_deprecated_function( 'display_price', '2.0', 'my_custom_plugin()->display->display_input' );
// Remove the callback
remove_all_actions( 'before_main_content' );
You maybe could even go further, extract the callback from the global filters array and re-attach it to the new hook/filter (if they’re compatible).