Make WordPress Core

Changeset 27294


Ignore:
Timestamp:
02/26/2014 06:43:59 PM (11 years ago)
Author:
nacin
Message:

Introduce doing_filter() and doing_action() to identify hooks in progress.

did_action() returns true the moment a hook is initially run, leaving you no way to tell if the hook is still in progress. Hooks can be nested and this checks the entire stack, versus current_filter() which only identifies the final hook in the stack. This commit also introduces current_action() for parity.

To tell if a hook has completed, one can use did_action() and ! doing_action() together.

The functions do not require an argument. In that situation, they indicate whether the stack is empty.

props ericmann for the initial unit tests.
fixes #14994.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/plugin.php

    r27262 r27294  
    323323    global $wp_current_filter;
    324324    return end( $wp_current_filter );
     325}
     326
     327/**
     328 * Retrieve the name of the current action.
     329 *
     330 * @since 3.9.0
     331 * @uses current_filter()
     332 *
     333 * @return string Hook name of the current action.
     334 */
     335function current_action() {
     336    return current_filter();
     337}
     338
     339/**
     340 * Retrieve the name of a filter currently being processed.
     341 *
     342 * The function current_filter() only returns the most recent filter or action
     343 * being executed.  did_action() returns true once the action is initially
     344 * processed.  This function allows detection for any filter currently being
     345 * executed (despite not being the most recent filter to fire, in the case of
     346 * hooks called from hook callbacks) to be verified.
     347 *
     348 * @since 3.9.0
     349 * @see current_filter()
     350 * @see did_action()
     351 *
     352 * @param string $filter Optional. Filter to check. Defaults to null, which checks if any filter is currently being run.
     353 *
     354 * @global array $wp_current_filter
     355 *
     356 * @return bool Whether the filter is currently in the stack
     357 */
     358function doing_filter( $filter = null ) {
     359    global $wp_current_filter;
     360
     361    if ( null === $filter ) {
     362        return ! empty( $wp_current_filter );
     363    }
     364
     365    return in_array( $filter, $wp_current_filter );
     366}
     367
     368/**
     369 * Retrieve the name of an action currently being processed.
     370 *
     371 * @since 3.9.0
     372 * @uses doing_filter()
     373 *
     374 * @param string $action Optional. Action to check. Defaults to null, which checks if any action is currently being run.
     375 *
     376 * @return bool Whether the action is currently in the stack.
     377 */
     378function doing_action( $action = null ) {
     379    return doing_filter( $action );
    325380}
    326381
  • trunk/tests/phpunit/tests/actions.php

    r25373 r27294  
    257257        remove_action( 'test_action_self_removal', array( $this, 'action_self_removal' ) );
    258258    }
     259
     260    /**
     261     * Make sure current_action() behaves as current_filter()
     262     *
     263     * @ticket 14994
     264     */
     265    function test_current_action() {
     266        global $wp_current_filter;
     267        $wp_current_filter[] = 'first';
     268        $wp_current_filter[] = 'second'; // Let's say a second action was invoked.
     269
     270        $this->assertEquals( 'second', current_action() );
     271    }
     272
     273    /**
     274     * @ticket 14994
     275     */
     276    function test_doing_filter() {
     277        global $wp_current_filter;
     278        $wp_current_filter = array(); // Set to an empty array first
     279
     280        $this->assertFalse( doing_filter() ); // No filter is passed in, and no filter is being processed
     281        $this->assertFalse( doing_filter( 'testing' ) ); // Filter is passed in but not being processed
     282
     283        $wp_current_filter[] = 'testing';
     284
     285        $this->assertTrue( doing_filter() ); // No action is passed in, and a filter is being processed
     286        $this->assertTrue( doing_filter( 'testing') ); // Filter is passed in and is being processed
     287        $this->assertFalse( doing_filter( 'something_else' ) ); // Filter is passed in but not being processed
     288
     289        $wp_current_filter = array();
     290    }
     291
     292    /**
     293     * @ticket 14994
     294     */
     295    function test_doing_action() {
     296        global $wp_current_filter;
     297        $wp_current_filter = array(); // Set to an empty array first
     298
     299        $this->assertFalse( doing_action() ); // No action is passed in, and no filter is being processed
     300        $this->assertFalse( doing_action( 'testing' ) ); // Action is passed in but not being processed
     301
     302        $wp_current_filter[] = 'testing';
     303
     304        $this->assertTrue( doing_action() ); // No action is passed in, and a filter is being processed
     305        $this->assertTrue( doing_action( 'testing') ); // Action is passed in and is being processed
     306        $this->assertFalse( doing_action( 'something_else' ) ); // Action is passed in but not being processed
     307
     308        $wp_current_filter = array();
     309    }
     310
     311    /**
     312     * @ticket 14994
     313     */
     314    function test_doing_filter_real() {
     315        $this->assertFalse( doing_filter() ); // No filter is passed in, and no filter is being processed
     316        $this->assertFalse( doing_filter( 'testing' ) ); // Filter is passed in but not being processed
     317
     318        add_filter( 'testing', array( $this, 'apply_testing_filter' ) );
     319        $this->assertTrue( has_action( 'testing' ) );
     320        $this->assertEquals( 10, has_action( 'testing', array( $this, 'apply_testing_filter' ) ) );
     321
     322        apply_filters( 'testing', '' );
     323
     324        // Make sure it ran.
     325        $this->assertTrue( $this->apply_testing_filter );
     326
     327        $this->assertFalse( doing_filter() ); // No longer doing any filters
     328        $this->assertFalse( doing_filter( 'testing' ) ); // No longer doing this filter
     329    }
     330
     331    function apply_testing_filter() {
     332        $this->apply_testing_filter = true;
     333
     334        $this->assertTrue( doing_filter() );
     335        $this->assertTrue( doing_filter( 'testing' ) );
     336        $this->assertFalse( doing_filter( 'something_else' ) );
     337        $this->assertFalse( doing_filter( 'testing_nested' ) );
     338
     339        add_filter( 'testing_nested', array( $this, 'apply_testing_nested_filter' ) );
     340        $this->assertTrue( has_action( 'testing_nested' ) );
     341        $this->assertEquals( 10, has_action( 'testing_nested', array( $this, 'apply_testing_nested_filter' ) ) );
     342
     343        apply_filters( 'testing_nested', '' );
     344
     345        // Make sure it ran.
     346        $this->assertTrue( $this->apply_testing_nested_filter );
     347
     348        $this->assertFalse( doing_filter( 'testing_nested' ) );
     349        $this->assertFalse( doing_filter( 'testing_nested' ) );
     350    }
     351
     352    function apply_testing_nested_filter() {
     353        $this->apply_testing_nested_filter = true;
     354        $this->assertTrue( doing_filter() );
     355        $this->assertTrue( doing_filter( 'testing' ) );
     356        $this->assertTrue( doing_filter( 'testing_nested' ) );
     357        $this->assertFalse( doing_filter( 'something_else' ) );
     358    }
    259359}
Note: See TracChangeset for help on using the changeset viewer.