WordPress remove filter with anonymous function / object

PHP 5.3 introduced anonymous functions and those can passed as an argument to WordPress add_filter function

add_filter( 'the_content', function( $content ){ 
	return trim( $content ); 
}, 10 );

This is super helpful as we don’t have to create new functions for such simple filtering as trimming of the content is. Plus this approach gives us an option to add custom arguments/parameters to a WordPress filter (checkout my another article on this topic).

A problem might arise when we need to remove such filter. How do we do that? WordPress is storing all filters in a global associative array. And does it store with unique filter_id generated by a _wp_filter_build_unique_id function.

This function is called from inside of add_filter and remove_filter function and it’s output stay constant for same input ( tag, function, priority ). So we can take advantage of this function and create our remove_filter_by_unique_id function. It’s derived from original remove_filter function, just with one line left (commented out in this example):

function remove_filter_by_unique_id( $tag, $function_to_remove, $priority = 10 ) {
	//$function_to_remove = _wp_filter_build_unique_id($tag, $function_to_remove, $priority);
	$r = isset($GLOBALS['wp_filter'][$tag][$priority][$function_to_remove]);
	if ( true === $r) {
		unset($GLOBALS['wp_filter'][$tag][$priority][$function_to_remove]);
		if ( empty($GLOBALS['wp_filter'][$tag][$priority]) ){
			unset($GLOBALS['wp_filter'][$tag][$priority]);
		}
		unset($GLOBALS['merged_filters'][$tag]);
	}	
	return $r;
}

We can use that function in this way:

$filter_id = _wp_filter_build_unique_id( 'the_content', function( $content ){
	return trim( $content );
}, 10  );
add_filter( 'the_content', function( $content ){
	return trim( $content );
}, 10 );
the_content();
remove_filter_by_unique_id( 'the_content', $filter_id, 10 );

But wait, we have still have to copy the anonymous function itself twice. This is not good. Let’s create our own add_filter function returning unique_filter_id for us. Again, simple, it’s just about updating a single line:

function add_annonymous_function_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
	global $wp_filter, $merged_filters;
	$idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
	$wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
	unset( $merged_filters[ $tag ] );
	//return true; -- we've replaced this line by the following one
	return $idx;
}

So the final usage will look like this:

$filter_id = add_annonymous_function_filter( 'the_content', function( $content ){
	return trim( $content );
}, 10 );
the_content();
remove_filter_by_unique_id( 'the_content', $filter_id, 10 );

This example is really simple, we could use get_the_content() instead of the_content() function and trim the output just before echoing it, but keep in mind, that this is just an example of anonymous function in WordPress filters.