Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/wp-includes/class-wp-hook.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,16 +223,21 @@ public function remove_filter( $hook_name, $callback, $priority ) {
* that evaluates to false (e.g. 0), so use the `===` operator for testing the return value.
*
* @since 4.7.0
* @since 6.9.0 Added the `$priority` parameter.
*
* @param string $hook_name Optional. The name of the filter hook. Default empty.
* @param callable|string|array|false $callback Optional. The callback to check for.
* This method can be called unconditionally to speculatively check
* a callback that may or may not exist. Default false.
* @param int|false $priority Optional. The specific priority at which to check for the callback.
* Default false.
* @return bool|int If `$callback` is omitted, returns boolean for whether the hook has
* anything registered. When checking a specific function, the priority
* of that hook is returned, or false if the function is not attached.
* If `$callback` and `$priority` are both provided, a boolean is returned
* for whether the specific function is registered at that priority.
*/
public function has_filter( $hook_name = '', $callback = false ) {
public function has_filter( $hook_name = '', $callback = false, $priority = false ) {
if ( false === $callback ) {
return $this->has_filters();
}
Expand All @@ -243,9 +248,13 @@ public function has_filter( $hook_name = '', $callback = false ) {
return false;
}

foreach ( $this->callbacks as $priority => $callbacks ) {
if ( is_int( $priority ) ) {
return isset( $this->callbacks[ $priority ][ $function_key ] );
}

foreach ( $this->callbacks as $callback_priority => $callbacks ) {
if ( isset( $callbacks[ $function_key ] ) ) {
return $priority;
return $callback_priority;
}
}

Expand Down
18 changes: 14 additions & 4 deletions src/wp-includes/plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,25 +267,30 @@ function apply_filters_ref_array( $hook_name, $args ) {
* that evaluates to false (e.g. 0), so use the `===` operator for testing the return value.
*
* @since 2.5.0
* @since 6.9.0 Added the `$priority` parameter.
*
* @global WP_Hook[] $wp_filter Stores all of the filters and actions.
*
* @param string $hook_name The name of the filter hook.
* @param callable|string|array|false $callback Optional. The callback to check for.
* This function can be called unconditionally to speculatively check
* a callback that may or may not exist. Default false.
* @param int|false $priority Optional. The specific priority at which to check for the callback.
* Default false.
* @return bool|int If `$callback` is omitted, returns boolean for whether the hook has
* anything registered. When checking a specific function, the priority
* of that hook is returned, or false if the function is not attached.
* If `$callback` and `$priority` are both provided, a boolean is returned
* for whether the specific function is registered at that priority.
*/
function has_filter( $hook_name, $callback = false ) {
function has_filter( $hook_name, $callback = false, $priority = false ) {
global $wp_filter;

if ( ! isset( $wp_filter[ $hook_name ] ) ) {
return false;
}

return $wp_filter[ $hook_name ]->has_filter( $hook_name, $callback );
return $wp_filter[ $hook_name ]->has_filter( $hook_name, $callback, $priority );
}

/**
Expand Down Expand Up @@ -574,19 +579,24 @@ function do_action_ref_array( $hook_name, $args ) {
* that evaluates to false (e.g. 0), so use the `===` operator for testing the return value.
*
* @since 2.5.0
* @since 6.9.0 Added the `$priority` parameter.
*
* @see has_filter() This function is an alias of has_filter().
*
* @param string $hook_name The name of the action hook.
* @param callable|string|array|false $callback Optional. The callback to check for.
* This function can be called unconditionally to speculatively check
* a callback that may or may not exist. Default false.
* @param int|false $priority Optional. The specific priority at which to check for the callback.
* Default false.
* @return bool|int If `$callback` is omitted, returns boolean for whether the hook has
* anything registered. When checking a specific function, the priority
* of that hook is returned, or false if the function is not attached.
* If `$callback` and `$priority` are both provided, a boolean is returned
* for whether the specific function is registered at that priority.
*/
function has_action( $hook_name, $callback = false ) {
return has_filter( $hook_name, $callback );
function has_action( $hook_name, $callback = false, $priority = false ) {
return has_filter( $hook_name, $callback, $priority );
}

/**
Expand Down
24 changes: 20 additions & 4 deletions tests/phpunit/tests/actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,23 @@ public function test_remove_action() {
$hook_name = __FUNCTION__;

add_action( $hook_name, array( &$a, 'action' ) );
add_action( $hook_name, array( &$a, 'action' ), 100 );
do_action( $hook_name );

// Make sure our hook was called correctly.
$this->assertSame( 1, $a->get_call_count() );
$this->assertSame( array( $hook_name ), $a->get_hook_names() );
$this->assertSame( 2, $a->get_call_count() );
$this->assertSame( array( $hook_name, $hook_name ), $a->get_hook_names() );

// Now remove the action, do it again, and make sure it's not called this time.
remove_action( $hook_name, array( &$a, 'action' ) );
remove_action( $hook_name, array( &$a, 'action' ), 100 );
do_action( $hook_name );
$this->assertSame( 1, $a->get_call_count() );
$this->assertSame( array( $hook_name ), $a->get_hook_names() );
$this->assertSame( 2, $a->get_call_count() );
$this->assertSame( array( $hook_name, $hook_name ), $a->get_hook_names() );
}

/**
* @ticket 64186
* @covers ::has_action
*/
public function test_has_action() {
Expand All @@ -89,8 +92,21 @@ public function test_has_action() {

add_action( $hook_name, $callback );
$this->assertSame( 10, has_action( $hook_name, $callback ) );
$this->assertFalse( has_action( $hook_name, $callback, 9 ) );
$this->assertTrue( has_action( $hook_name ) );

add_action( $hook_name, $callback, 9 );
add_action( $hook_name, $callback, 11 );
$this->assertSame( 9, has_action( $hook_name, $callback ) );
$this->assertTrue( has_action( $hook_name, $callback, 9 ) );
$this->assertTrue( has_action( $hook_name, $callback, 10 ) );
$this->assertTrue( has_action( $hook_name, $callback, 11 ) );
$this->assertTrue( has_action( $hook_name ) );

remove_action( $hook_name, $callback, 9 );
remove_action( $hook_name, $callback, 11 );
$this->assertSame( 10, has_action( $hook_name, $callback ) );

remove_action( $hook_name, $callback );
$this->assertFalse( has_action( $hook_name, $callback ) );
$this->assertFalse( has_action( $hook_name ) );
Expand Down
30 changes: 26 additions & 4 deletions tests/phpunit/tests/filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,34 @@ public function test_simple_filter() {
$this->assertSame( array( $val ), $args );
}

/**
* @covers ::remove_filter
*/
public function test_remove_filter() {
$a = new MockAction();
$hook_name = __FUNCTION__;
$val = __FUNCTION__ . '_val';

add_filter( $hook_name, array( $a, 'filter' ) );
add_filter( $hook_name, array( $a, 'filter' ), 100 );
$this->assertSame( $val, apply_filters( $hook_name, $val ) );

// Make sure our hook was called correctly.
$this->assertSame( 1, $a->get_call_count() );
$this->assertSame( array( $hook_name ), $a->get_hook_names() );
$this->assertSame( 2, $a->get_call_count() );
$this->assertSame( array( $hook_name, $hook_name ), $a->get_hook_names() );

// Now remove the filter, do it again, and make sure it's not called this time.
remove_filter( $hook_name, array( $a, 'filter' ) );
remove_filter( $hook_name, array( $a, 'filter' ), 100 );
$this->assertSame( $val, apply_filters( $hook_name, $val ) );
$this->assertSame( 1, $a->get_call_count() );
$this->assertSame( array( $hook_name ), $a->get_hook_names() );
$this->assertSame( 2, $a->get_call_count() );
$this->assertSame( array( $hook_name, $hook_name ), $a->get_hook_names() );
}

/**
* @ticket 64186
* @covers ::has_filter
*/
public function test_has_filter() {
$hook_name = __FUNCTION__;
$callback = __FUNCTION__ . '_func';
Expand All @@ -53,8 +62,21 @@ public function test_has_filter() {

add_filter( $hook_name, $callback );
$this->assertSame( 10, has_filter( $hook_name, $callback ) );
$this->assertFalse( has_filter( $hook_name, $callback, 9 ) );
$this->assertTrue( has_filter( $hook_name ) );

add_filter( $hook_name, $callback, 9 );
add_filter( $hook_name, $callback, 11 );
$this->assertSame( 9, has_filter( $hook_name, $callback ) );
$this->assertTrue( has_filter( $hook_name, $callback, 9 ) );
$this->assertTrue( has_filter( $hook_name, $callback, 10 ) );
$this->assertTrue( has_filter( $hook_name, $callback, 11 ) );
$this->assertTrue( has_filter( $hook_name ) );

remove_filter( $hook_name, $callback, 9 );
remove_filter( $hook_name, $callback, 11 );
$this->assertSame( 10, has_filter( $hook_name, $callback ) );

remove_filter( $hook_name, $callback );
$this->assertFalse( has_filter( $hook_name, $callback ) );
$this->assertFalse( has_filter( $hook_name ) );
Expand Down
15 changes: 12 additions & 3 deletions tests/phpunit/tests/hooks/hasFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,25 @@
*/
class Tests_Hooks_HasFilter extends WP_UnitTestCase {

/**
* @ticket 64186
*/
public function test_has_filter_with_function() {
$callback = '__return_null';
$hook = new WP_Hook();
$hook_name = __FUNCTION__;
$priority = 1;
$priority_a = 1;
$priority_b = 10;
$accepted_args = 2;

$hook->add_filter( $hook_name, $callback, $priority, $accepted_args );
$hook->add_filter( $hook_name, $callback, $priority_a, $accepted_args );
$hook->add_filter( $hook_name, $callback, $priority_b, $accepted_args );

$this->assertSame( $priority, $hook->has_filter( $hook_name, $callback ) );
$this->assertSame( $priority_a, $hook->has_filter( $hook_name, $callback ) );
$this->assertTrue( $hook->has_filter( $hook_name, $callback, $priority_a ) );
$this->assertTrue( $hook->has_filter( $hook_name, $callback, $priority_b ) );
$hook->remove_filter( $hook_name, $callback, $priority_a );
$this->assertSame( $priority_b, $hook->has_filter( $hook_name, $callback ) );
}

public function test_has_filter_with_object() {
Expand Down
Loading