Opened 10 years ago
Closed 10 years ago
#29070 closed defect (bug) (fixed)
Calling remove_all_filters() causes has_filter() with no $function_to_check to always return true
Reported by: | pseudoxiah | Owned by: | wonderboymusic |
---|---|---|---|
Milestone: | 4.0 | Priority: | normal |
Severity: | normal | Version: | 4.0 |
Component: | Plugins | Keywords: | has-patch |
Focuses: | Cc: |
Description
Changes in 28883 cause has_filter()
to return true
if no $function_to_check
is specified and remove_all_filters()
was called.
The issues is that has_filter()
does only a ! empty()
check:
$has = !empty($wp_filter[$tag]);
The workaround is to iterate through the tag and detect if there are any non-empty arrays:
if( ! empty( $wp_filter[ $tag ] ) { $has = false; foreach( $wp_filter[ $tag ] as $priority => $functions ) { if( ! empty( $wp_filter[ $tag ][ $priority ] ) ) $has = true; } }
Attachments (4)
Change History (17)
#1
@
10 years ago
- Keywords needs-patch needs-unit-tests added
- Milestone changed from Awaiting Review to 4.0
#3
@
10 years ago
- Keywords has-patch needs-testing added; needs-patch needs-unit-tests removed
Isn't this the expected behaviour? remove_all_filters() removes all of the hooks from a filter, but not the filter itself.
has_filter()
should return true if there are filter callbacks registered for that particular hook. After remove_all_filters()
, has_filter()
should return false.
I was able to reproduce the error only by adding filters at different priorities, and then calling remove_all_filters( $hook, $priority )
for each priority separately. This does leave some empty arrays laying around as a result of r28883.
Attached patch has a unit test that demonstrates the bug, as well as a cleaned up version of pseudoxiah's original suggested solution. Test passes before r28883, fails on current trunk, passes with the fix. Entire test suite passes with the patch.
#4
@
10 years ago
- Owner set to wonderboymusic
- Resolution set to fixed
- Status changed from new to closed
In 29422:
#5
@
10 years ago
- Keywords needs-testing removed
- Resolution fixed deleted
- Status changed from closed to reopened
There's a problem with r29422. The new foreach loop resets the internal array counter which do_action() and apply_filters() rely on. This can cause infinite loops. Here's an example:
add_action( 'foo', '__return_null', 1 ); add_action( 'foo', '__return_null', 2 ); add_action( 'foo', '__return_null', 3 ); add_action( 'foo', 'bar', 4 ); function bar() { has_action( 'foo', 'something' ); } do_action( 'foo' );
Patch in 29070.diff.
#8
@
10 years ago
- Keywords needs-unit-tests added; has-patch removed
- Resolution fixed deleted
- Status changed from closed to reopened
[29422] could strongly benefit from a unit test.
#12
@
10 years ago
- Keywords has-patch added; needs-unit-tests removed
attachment:29070.3.diff removes the nested current()
call from attachment:29070.2.diff, which looks odd and isn't supposed to work.
Isn't this the expected behaviour?
remove_all_filters()
removes all of the hooks from a filter, but not the filter itself.So, having run
remove_all_filters()
, if I ranhas_filter()
without a function to check, I'd still expect it to returntrue
.Having said this, I'm actually a bit confused. I'm running trunk locally (up-to-date), and for me it's returning
false
under the circumstances above…http://codex.wordpress.org/Function_Reference/has_filter
http://codex.wordpress.org/Function_Reference/remove_all_filters