#35357 closed enhancement (fixed)
Introduce did_filter()
Reported by: | mordauk | Owned by: | chriscct7 |
---|---|---|---|
Milestone: | 6.1 | Priority: | normal |
Severity: | normal | Version: | 2.1 |
Component: | Plugins | Keywords: | has-patch has-unit-tests needs-dev-note |
Focuses: | Cc: |
Description
I think there should a did_filter( $tag )
function that mimics the existing did_action( $tag )
function.
While actions and filters are pretty much the same thing, it turns out that you can't actually use did_action()
to detect when a filter has been run.
function did_filter( $tag = '' ) { global $wp_filter; if ( ! isset( $wp_filter[ $tag ] ) ) { return 0; } return $wp_filter[ $tag ]; }
Attachments (7)
Change History (33)
#3
@
9 years ago
- Keywords has-patch has-unit-tests added
- Milestone changed from Awaiting Review to 4.5
- Version trunk deleted
Implemented a method of counting filters as they run similar to to how actions are counted.
If run after a filter is run, returns the number of functions that ran on the filter. If run in a function attached to a filter, returns the number of functions that have run on the filter before the current function. This works the same ways as did_action does, but for filters.
Attached patch, and passing unit tests which test:
- Filter with no functions attached
- Filter with 1 function attached
- Filter with 2 functions attached
Unit tests are passing. Let's get this in 4.5.
#7
follow-up:
↓ 9
@
9 years ago
- Keywords needs-patch added; has-patch has-unit-tests commit removed
If we are to do this, I wonder if it should just be an alias of did_action()
and use $wp_actions
. That would mimic current_filter()
and add_filter()
behavior as well, making it clear they share the same namespace.
I've never seen much utility for this, because filters are often run in different, repeated contexts, rather than a single-time action. But I stand corrected and I'm not against adding it.
This requires unit tests, and preferably ones that would catch that the increment is currently in the wrong spot. If you had 4 callbacks tied to the test_did_filter
filter, calling apply_filters( 'test_did_filter' ); var_dump( did_filter( 'test_did_filter' );
would return 4, not 1.
If run after a filter is run, returns the number of functions that ran on the filter. If run in a function attached to a filter, returns the number of functions that have run on the filter before the current function. This works the same ways as did_action does, but for filters.
That is not how did_action()
works. :-)
#8
@
9 years ago
The instance that made me open this was when I wanted to detect if a particular filter had run and then prevent it from ever running again. Definitely a rare scenario but it was one that made sense in my particular case.
#9
in reply to:
↑ 7
@
9 years ago
A use case of the proposed function is to allow a function attached to a filter to detect that another function has run and shortcircuit. For example, if you had a filter that could be called multiple times to avoid a loop.
Replying to nacin:
If we are to do this, I wonder if it should just be an alias of
did_action()
and use$wp_actions
. That would mimiccurrent_filter()
andadd_filter()
behavior as well, making it clear they share the same namespace.
I've never seen much utility for this, because filters are often run in different, repeated contexts, rather than a single-time action. But I stand corrected and I'm not against adding it.
This requires unit tests, and preferably ones that would catch that the increment is currently in the wrong spot. If you had 4 callbacks tied to the
test_did_filter
filter, callingapply_filters( 'test_did_filter' ); var_dump( did_filter( 'test_did_filter' );
would return 4, not 1.
If run after a filter is run, returns the number of functions that ran on the filter. If run in a function attached to a filter, returns the number of functions that have run on the filter before the current function. This works the same ways as did_action does, but for filters.
That is not how
did_action()
works. :-)
If I adjust the PHP file I uploaded above to use actions instead of filters, that's how it seems to work. Attaching a copy.
#10
follow-up:
↓ 12
@
9 years ago
I stand corrected. It does indeed return 1. Therefore there is a difference, however I don't see a use case where the way did_action which counts per do_action call as opposed to the number of functions that run on it (like my above patch does) makes sense for filters. I actually think the patch method of counting is more expected for filters because of exactly this:
I've never seen much utility for this, because filters are often run in different, repeated contexts, rather than a single-time action.
#11
@
9 years ago
With filters I think its more interesting to count the number of functions that have run on it, rather than the number of times a filter has been called, and that's what the patch was designed to solve (thus why the unit tests passed). Despite apparently being misconcieved on what did_action does, the application of 4 functions to a single filter should return 4 based on what I've written if did_filter is run after the filter, and 0 , 1, 2, and 3 respectively if run inside each of the functions.
Perhaps a different function name for it, and then something like https://core.trac.wordpress.org/attachment/ticket/35357/35357.patch for the did_filter
#12
in reply to:
↑ 10
@
9 years ago
Replying to chriscct7:
I stand corrected. It does indeed return 1. Therefore there is a difference, however I don't see a use case where the way did_action which counts per do_action call as opposed to the number of functions that run on it (like my above patch does) makes sense for filters. I actually think the patch method of counting is more expected for filters because of exactly this:
I've never seen much utility for this, because filters are often run in different, repeated contexts, rather than a single-time action.
Just to throw another opinion at it
- I don't see the point of counting the number of functions that've run.
- I don't think "detecting another function has already run on this filter" is a valid use-case that should be supported. If a filter *shouldn't* run, it should either be
remove_action()
'd or not hooked in the first place if another filter is already hooked in. - As filters are more likely to be called multiple times per page load it feels more sane that it'd return the number of times that filter has run on the current load, "the_title has run 15 times" is a lot more useful than "the_title has had 150 functions run on it".
#13
@
9 years ago
I needed to detect if a filter had been applied because the callback function tied to the filter had the possibility of triggering an infinite loop since it resulting in the class that ran the filter getting instantiated again.
#14
@
9 years ago
I needed to detect if a filter had been applied because the callback function tied to the filter had the possibility of triggering an infinite loop since it resulting in the class that ran the filter getting instantiated again.
In that case, I think something like doing_filter( 'the_filter_name' )
is a better option
#15
@
9 years ago
- Keywords has-patch has-unit-tests added; needs-patch removed
In 35357.4.patch:
- Adjusted did_filter to work similar to did_action to count the number of times a filter is called by having it wrap did_action and adjusting the filter run functions to count the times a filter is called the same way they do in the action call functions
- Adjusted did_filter unit tests to test the number of times a filter that is called 1 and 2 times and one that is never called
- Introduced filter_functions_run to count the number of functions run on a filter
- Adjusted filter_functions_run unit tests to do what patch 3's unit tests did.
This ticket was mentioned in Slack in #core by jorbin. View the logs.
9 years ago
#17
@
9 years ago
- Milestone changed from 4.5 to Future Release
7 weeks since the last activity, so this is being punted.
This ticket was mentioned in Slack in #core by manzoorwanijk. View the logs.
4 years ago
#20
@
4 years ago
- Keywords needs-refresh added
- Version set to 2.1
Hi @manzoorwanijk,
Given how long it's been I imagine it's very unlikely the existing patch will still apply cleanly, so at the least it will require someone to refresh the patch against the latest trunk.
From a quick read through the ticket it's also not clear that there was really a consensus as to the preferred approach (and again a lot has changed in 5 years), so there may need to be some additional discussion too.
I'd suggest that if you'd like to see this move forward the first step would be to refresh the existing patch, and then perhaps bring it up during the open floor of one of the weekly dev chats in the #core
Slack channel (0500 and 2000 UTC each Wednesday). If you're not able to make either of those meetings then you can leave a comment on the agenda which is posted on the Make Core blog prior to the earlier meeting and the meeting facilitator will raise it for you.
#21
@
4 years ago
I would be interested in adding this to core. I've created a patch which adds a did_filter
function which operates in a similar way to did_action
, but counts the number of times a filter has run. It creates a new global $wp_filters
to store the counts (c.f. $wp_actions
and did_action
). If added it would round out the functions in this area to give the following:
- add_action
- do_action
- doing_action
- did_action
- add_filter
- apply_filters
- doing_filter
- did_filter [new]
#23
@
3 years ago
- Keywords needs-testing added; needs-refresh removed
- Milestone set to 6.1
Hi @VibeThemes, we're already in the beta period for 6.0
so it's too late for it to be considered for inclusion in the next major release, but I've moved it into the 6.1
milestone for visibility.
Per my previous comment, feel free to raise it during devchat in #core to get some more eyes on it (though I'd recommend waiting after 6.0
is released as until then that will be the focus).
Pinging @chriscct7 also to check whether he's still happy to own this one?
That patch doesn't work for numerous reasons I've now realized but I still think some form of this should happen.