Plugins: Introduce did_filter() function.

While most of the action functions are aliases for the respective filter functions, using `did_action()` to detect whether a filter has been run is not possible, as it only works specifically for actions.

This is now resolved by introducing a new function, `did_filter()`, which retrieves the number of times a filter has been applied during the current request, bringing parity with `did_action()`.

Follow-up to [4630], [6318], [27294].

Props mordauk, chriscct7, andykeith, nacin, dd32, markparnell, SergeyBiryukov.
Fixes #35357.

git-svn-id: https://develop.svn.wordpress.org/trunk@53803 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Sergey Biryukov 2022-07-31 14:18:36 +00:00
parent 95efa62a7d
commit 65e266ede6
2 changed files with 68 additions and 2 deletions

View File

@ -30,6 +30,9 @@ global $wp_filter;
/** @var int[] $wp_actions */
global $wp_actions;
/** @var int[] $wp_filters */
global $wp_filters;
/** @var string[] $wp_current_filter */
global $wp_current_filter;
@ -43,6 +46,10 @@ if ( ! isset( $wp_actions ) ) {
$wp_actions = array();
}
if ( ! isset( $wp_filters ) ) {
$wp_filters = array();
}
if ( ! isset( $wp_current_filter ) ) {
$wp_current_filter = array();
}
@ -155,6 +162,7 @@ function add_filter( $hook_name, $callback, $priority = 10, $accepted_args = 1 )
* by adding it to the function signature.
*
* @global WP_Hook[] $wp_filter Stores all of the filters and actions.
* @global int[] $wp_filters Stores the number of times each filter was triggered.
* @global string[] $wp_current_filter Stores the list of current filters with the current one last.
*
* @param string $hook_name The name of the filter hook.
@ -163,7 +171,13 @@ function add_filter( $hook_name, $callback, $priority = 10, $accepted_args = 1 )
* @return mixed The filtered value after all hooked functions are applied to it.
*/
function apply_filters( $hook_name, $value, ...$args ) {
global $wp_filter, $wp_current_filter;
global $wp_filter, $wp_filters, $wp_current_filter;
if ( ! isset( $wp_filters[ $hook_name ] ) ) {
$wp_filters[ $hook_name ] = 1;
} else {
++$wp_filters[ $hook_name ];
}
// Do 'all' actions first.
if ( isset( $wp_filter['all'] ) ) {
@ -204,6 +218,7 @@ function apply_filters( $hook_name, $value, ...$args ) {
* functions hooked to `$hook_name` are supplied using an array.
*
* @global WP_Hook[] $wp_filter Stores all of the filters and actions.
* @global int[] $wp_filters Stores the number of times each filter was triggered.
* @global string[] $wp_current_filter Stores the list of current filters with the current one last.
*
* @param string $hook_name The name of the filter hook.
@ -211,7 +226,13 @@ function apply_filters( $hook_name, $value, ...$args ) {
* @return mixed The filtered value after all hooked functions are applied to it.
*/
function apply_filters_ref_array( $hook_name, $args ) {
global $wp_filter, $wp_current_filter;
global $wp_filter, $wp_filters, $wp_current_filter;
if ( ! isset( $wp_filters[ $hook_name ] ) ) {
$wp_filters[ $hook_name ] = 1;
} else {
++$wp_filters[ $hook_name ];
}
// Do 'all' actions first.
if ( isset( $wp_filter['all'] ) ) {
@ -377,6 +398,26 @@ function doing_filter( $hook_name = null ) {
return in_array( $hook_name, $wp_current_filter, true );
}
/**
* Retrieves the number of times a filter has been applied during the current request.
*
* @since 6.1.0
*
* @global int[] $wp_filters Stores the number of times each filter was triggered.
*
* @param string $hook_name The name of the filter hook.
* @return int The number of times the filter hook has been applied.
*/
function did_filter( $hook_name ) {
global $wp_filters;
if ( ! isset( $wp_filters[ $hook_name ] ) ) {
return 0;
}
return $wp_filters[ $hook_name ];
}
/**
* Adds a callback function to an action hook.
*

View File

@ -150,6 +150,31 @@ class Tests_Filters extends WP_UnitTestCase {
$this->assertSame( $expected, $a->get_events() );
}
/**
* @covers ::did_filter
*/
public function test_did_filter() {
$tag1 = 'filter1';
$tag2 = 'filter2';
$val = __FUNCTION__ . '_val';
// Apply filter $tag1 but not $tag2.
apply_filters( $tag1, $val );
$this->assertSame( 1, did_filter( $tag1 ) );
$this->assertSame( 0, did_filter( $tag2 ) );
// Apply filter $tag2 10 times.
$count = 10;
for ( $i = 0; $i < $count; $i++ ) {
apply_filters( $tag2, $val );
}
// $tag1's count hasn't changed, $tag2 should be correct.
$this->assertSame( 1, did_filter( $tag1 ) );
$this->assertSame( $count, did_filter( $tag2 ) );
}
public function test_all_filter() {
$a = new MockAction();
$tag1 = __FUNCTION__ . '_1';