mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2025-10-16 12:05:38 +00:00
Adds happy (integer) and unhappy (non-integer) tests for validating the priority call order for: * `do_action()` * `WP_Hook::do_action()` * `apply_filters()` * `WP_Hook::apply_filters()` As each of these functions have differing code, the tests are added to each to ensure expected results and protect against future regressions. Follow-up to [53804], [52010], [25002], [25/tests], [62/tests]. Props hellofromTonya, mukesh27, dd32, valendesigns, drrobotnik. Fixes #60193. git-svn-id: https://develop.svn.wordpress.org/trunk@57257 602fd350-edb4-49c9-b593-d223f7449a82
834 lines
25 KiB
PHP
834 lines
25 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Test do_action() and related functions
|
|
*
|
|
* @group hooks
|
|
*/
|
|
class Tests_Actions extends WP_UnitTestCase {
|
|
|
|
/**
|
|
* Flag to keep track whether a certain filter has been applied.
|
|
*
|
|
* Used in the `test_doing_filter_real()` test method.
|
|
*
|
|
* @var bool
|
|
*/
|
|
private $apply_testing_filter = false;
|
|
|
|
/**
|
|
* Flag to keep track whether a certain filter has been applied.
|
|
*
|
|
* Used in the `test_doing_filter_real()` test method.
|
|
*
|
|
* @var bool
|
|
*/
|
|
private $apply_testing_nested_filter = false;
|
|
|
|
/**
|
|
* Clean up after each test.
|
|
*/
|
|
public function tear_down() {
|
|
// Make sure potentially changed properties are reverted to their default value.
|
|
$this->apply_testing_filter = false;
|
|
$this->apply_testing_nested_filter = false;
|
|
|
|
parent::tear_down();
|
|
}
|
|
|
|
/**
|
|
* @covers ::do_action
|
|
*/
|
|
public function test_simple_action() {
|
|
$a = new MockAction();
|
|
$hook_name = __FUNCTION__;
|
|
|
|
add_action( $hook_name, array( &$a, 'action' ) );
|
|
do_action( $hook_name );
|
|
|
|
// Only one event occurred for the hook, with empty args.
|
|
$this->assertSame( 1, $a->get_call_count() );
|
|
// Only our hook was called.
|
|
$this->assertSame( array( $hook_name ), $a->get_hook_names() );
|
|
|
|
$argsvar = $a->get_args();
|
|
$args = array_pop( $argsvar );
|
|
$this->assertSame( array( '' ), $args );
|
|
}
|
|
|
|
/**
|
|
* @covers ::remove_action
|
|
*/
|
|
public function test_remove_action() {
|
|
$a = new MockAction();
|
|
$hook_name = __FUNCTION__;
|
|
|
|
add_action( $hook_name, array( &$a, 'action' ) );
|
|
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() );
|
|
|
|
// Now remove the action, do it again, and make sure it's not called this time.
|
|
remove_action( $hook_name, array( &$a, 'action' ) );
|
|
do_action( $hook_name );
|
|
$this->assertSame( 1, $a->get_call_count() );
|
|
$this->assertSame( array( $hook_name ), $a->get_hook_names() );
|
|
}
|
|
|
|
/**
|
|
* @covers ::has_action
|
|
*/
|
|
public function test_has_action() {
|
|
$hook_name = __FUNCTION__;
|
|
$callback = __FUNCTION__ . '_func';
|
|
|
|
$this->assertFalse( has_action( $hook_name, $callback ) );
|
|
$this->assertFalse( has_action( $hook_name ) );
|
|
|
|
add_action( $hook_name, $callback );
|
|
$this->assertSame( 10, has_action( $hook_name, $callback ) );
|
|
$this->assertTrue( has_action( $hook_name ) );
|
|
|
|
remove_action( $hook_name, $callback );
|
|
$this->assertFalse( has_action( $hook_name, $callback ) );
|
|
$this->assertFalse( has_action( $hook_name ) );
|
|
}
|
|
|
|
/**
|
|
* One tag with multiple actions.
|
|
*
|
|
* @covers ::do_action
|
|
*/
|
|
public function test_multiple_actions() {
|
|
$a1 = new MockAction();
|
|
$a2 = new MockAction();
|
|
$hook_name = __FUNCTION__;
|
|
|
|
// Add both actions to the hook.
|
|
add_action( $hook_name, array( &$a1, 'action' ) );
|
|
add_action( $hook_name, array( &$a2, 'action' ) );
|
|
|
|
do_action( $hook_name );
|
|
|
|
// Both actions called once each.
|
|
$this->assertSame( 1, $a1->get_call_count() );
|
|
$this->assertSame( 1, $a2->get_call_count() );
|
|
}
|
|
|
|
/**
|
|
* One tag with multiple actions.
|
|
*
|
|
* @covers ::do_action
|
|
*/
|
|
public function test_action_args_1() {
|
|
$a = new MockAction();
|
|
$hook_name = __FUNCTION__;
|
|
$val = __FUNCTION__ . '_val';
|
|
|
|
add_action( $hook_name, array( &$a, 'action' ) );
|
|
// Call the action with a single argument.
|
|
do_action( $hook_name, $val );
|
|
|
|
$call_count = $a->get_call_count();
|
|
$this->assertSame( 1, $call_count );
|
|
$argsvar = $a->get_args();
|
|
$this->assertSame( array( $val ), array_pop( $argsvar ) );
|
|
}
|
|
|
|
/**
|
|
* One tag with multiple actions.
|
|
*
|
|
* @covers ::do_action
|
|
*/
|
|
public function test_action_args_2() {
|
|
$a1 = new MockAction();
|
|
$a2 = new MockAction();
|
|
$hook_name = __FUNCTION__;
|
|
$val1 = __FUNCTION__ . '_val1';
|
|
$val2 = __FUNCTION__ . '_val2';
|
|
|
|
// $a1 accepts two arguments, $a2 doesn't.
|
|
add_action( $hook_name, array( &$a1, 'action' ), 10, 2 );
|
|
add_action( $hook_name, array( &$a2, 'action' ) );
|
|
// Call the action with two arguments.
|
|
do_action( $hook_name, $val1, $val2 );
|
|
|
|
$call_count = $a1->get_call_count();
|
|
// $a1 should be called with both args.
|
|
$this->assertSame( 1, $call_count );
|
|
$argsvar1 = $a1->get_args();
|
|
$this->assertSame( array( $val1, $val2 ), array_pop( $argsvar1 ) );
|
|
|
|
// $a2 should be called with one only.
|
|
$this->assertSame( 1, $a2->get_call_count() );
|
|
$argsvar2 = $a2->get_args();
|
|
$this->assertSame( array( $val1 ), array_pop( $argsvar2 ) );
|
|
}
|
|
|
|
/**
|
|
* Test that multiple callbacks receive the correct number of args even when the number
|
|
* is less than, or greater than previous hooks.
|
|
*
|
|
* @see https://core.trac.wordpress.org/ticket/17817#comment:72
|
|
* @ticket 17817
|
|
*
|
|
* @covers ::do_action
|
|
*/
|
|
public function test_action_args_3() {
|
|
$a1 = new MockAction();
|
|
$a2 = new MockAction();
|
|
$a3 = new MockAction();
|
|
$hook_name = __FUNCTION__;
|
|
$val1 = __FUNCTION__ . '_val1';
|
|
$val2 = __FUNCTION__ . '_val2';
|
|
|
|
// $a1 accepts two arguments, $a2 doesn't, $a3 accepts two arguments.
|
|
add_action( $hook_name, array( &$a1, 'action' ), 10, 2 );
|
|
add_action( $hook_name, array( &$a2, 'action' ) );
|
|
add_action( $hook_name, array( &$a3, 'action' ), 10, 2 );
|
|
// Call the action with two arguments.
|
|
do_action( $hook_name, $val1, $val2 );
|
|
|
|
$call_count = $a1->get_call_count();
|
|
// $a1 should be called with both args.
|
|
$this->assertSame( 1, $call_count );
|
|
$argsvar1 = $a1->get_args();
|
|
$this->assertSame( array( $val1, $val2 ), array_pop( $argsvar1 ) );
|
|
|
|
// $a2 should be called with one only.
|
|
$this->assertSame( 1, $a2->get_call_count() );
|
|
$argsvar2 = $a2->get_args();
|
|
$this->assertSame( array( $val1 ), array_pop( $argsvar2 ) );
|
|
|
|
// $a3 should be called with both args.
|
|
$this->assertSame( 1, $a3->get_call_count() );
|
|
$argsvar3 = $a3->get_args();
|
|
$this->assertSame( array( $val1, $val2 ), array_pop( $argsvar3 ) );
|
|
}
|
|
|
|
/**
|
|
* Tests PHP 4 notation for calling actions while passing in an object by reference.
|
|
*
|
|
* @ticket 48312
|
|
*
|
|
* @covers ::do_action
|
|
*/
|
|
public function test_action_args_with_php4_syntax() {
|
|
$a = new MockAction();
|
|
$hook_name = __FUNCTION__;
|
|
$val = new stdClass();
|
|
|
|
add_action( $hook_name, array( &$a, 'action' ) );
|
|
// Call the action with PHP 4 notation for passing object by reference.
|
|
do_action( $hook_name, array( &$val ) );
|
|
|
|
$call_count = $a->get_call_count();
|
|
$argsvar = $a->get_args();
|
|
$this->assertSame( array( $val ), array_pop( $argsvar ) );
|
|
}
|
|
|
|
/**
|
|
* @ticket 60193
|
|
*
|
|
* @dataProvider data_priority_callback_order_with_integers
|
|
* @dataProvider data_priority_callback_order_with_unhappy_path_nonintegers
|
|
*
|
|
* @covers ::do_action
|
|
*
|
|
* @param array $priorities {
|
|
* Indexed array of the priorities for the MockAction callbacks.
|
|
*
|
|
* @type mixed $0 Priority for 'action' callback.
|
|
* @type mixed $1 Priority for 'action2' callback.
|
|
* }
|
|
* @param array $expected_call_order An array of callback names in expected call order.
|
|
* @param string $expected_deprecation Optional. Deprecation message. Default ''.
|
|
*/
|
|
public function test_priority_callback_order( $priorities, $expected_call_order, $expected_deprecation = '' ) {
|
|
$mock = new MockAction();
|
|
$hook_name = __FUNCTION__;
|
|
|
|
if ( $expected_deprecation && PHP_VERSION_ID >= 80100 ) {
|
|
$this->expectDeprecation();
|
|
$this->expectDeprecationMessage( $expected_deprecation );
|
|
}
|
|
|
|
add_action( $hook_name, array( $mock, 'action' ), $priorities[0] );
|
|
add_action( $hook_name, array( $mock, 'action2' ), $priorities[1] );
|
|
do_action( $hook_name );
|
|
|
|
$this->assertSame( 2, $mock->get_call_count(), 'The number of call counts does not match' );
|
|
|
|
$actual_call_order = wp_list_pluck( $mock->get_events(), 'action' );
|
|
$this->assertSame( $expected_call_order, $actual_call_order, 'The action callback order does not match the expected order' );
|
|
}
|
|
|
|
/**
|
|
* Happy path data provider.
|
|
*
|
|
* @return array[]
|
|
*/
|
|
public function data_priority_callback_order_with_integers() {
|
|
return array(
|
|
'int DESC' => array(
|
|
'priorities' => array( 10, 9 ),
|
|
'expected_call_order' => array( 'action2', 'action' ),
|
|
),
|
|
'int ASC' => array(
|
|
'priorities' => array( 9, 10 ),
|
|
'expected_call_order' => array( 'action', 'action2' ),
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Unhappy path data provider.
|
|
*
|
|
* @return array[]
|
|
*/
|
|
public function data_priority_callback_order_with_unhappy_path_nonintegers() {
|
|
return array(
|
|
// Numbers as strings and floats.
|
|
'int as string DESC' => array(
|
|
'priorities' => array( '10', '9' ),
|
|
'expected_call_order' => array( 'action2', 'action' ),
|
|
),
|
|
'int as string ASC' => array(
|
|
'priorities' => array( '9', '10' ),
|
|
'expected_call_order' => array( 'action', 'action2' ),
|
|
),
|
|
'float DESC' => array(
|
|
'priorities' => array( 10.0, 9.5 ),
|
|
'expected_call_order' => array( 'action2', 'action' ),
|
|
'expected_deprecation' => 'Implicit conversion from float 9.5 to int loses precision',
|
|
),
|
|
'float ASC' => array(
|
|
'priorities' => array( 9.5, 10.0 ),
|
|
'expected_call_order' => array( 'action', 'action2' ),
|
|
'expected_deprecation' => 'Implicit conversion from float 9.5 to int loses precision',
|
|
),
|
|
'float as string DESC' => array(
|
|
'priorities' => array( '10.0', '9.5' ),
|
|
'expected_call_order' => array( 'action2', 'action' ),
|
|
),
|
|
'float as string ASC' => array(
|
|
'priorities' => array( '9.5', '10.0' ),
|
|
'expected_call_order' => array( 'action', 'action2' ),
|
|
),
|
|
|
|
// Non-numeric.
|
|
'null' => array(
|
|
'priorities' => array( null, null ),
|
|
'expected_call_order' => array( 'action', 'action2' ),
|
|
),
|
|
'bool DESC' => array(
|
|
'priorities' => array( true, false ),
|
|
'expected_call_order' => array( 'action2', 'action' ),
|
|
),
|
|
'bool ASC' => array(
|
|
'priorities' => array( false, true ),
|
|
'expected_call_order' => array( 'action', 'action2' ),
|
|
),
|
|
'non-numerical string DESC' => array(
|
|
'priorities' => array( 'test1', 'test2' ),
|
|
'expected_call_order' => array( 'action', 'action2' ),
|
|
),
|
|
'non-numerical string ASC' => array(
|
|
'priorities' => array( 'test1', 'test2' ),
|
|
'expected_call_order' => array( 'action', 'action2' ),
|
|
),
|
|
'int, non-numerical string DESC' => array(
|
|
'priorities' => array( 10, 'test' ),
|
|
'expected_call_order' => array( 'action2', 'action' ),
|
|
),
|
|
'int, non-numerical string ASC' => array(
|
|
'priorities' => array( 'test', 10 ),
|
|
'expected_call_order' => array( 'action', 'action2' ),
|
|
),
|
|
'float, non-numerical string DESC' => array(
|
|
'priorities' => array( 10.0, 'test' ),
|
|
'expected_call_order' => array( 'action2', 'action' ),
|
|
),
|
|
'float, non-numerical string ASC' => array(
|
|
'priorities' => array( 'test', 10.0 ),
|
|
'expected_call_order' => array( 'action', 'action2' ),
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @covers ::did_action
|
|
*/
|
|
public function test_did_action() {
|
|
$hook_name1 = 'action1';
|
|
$hook_name2 = 'action2';
|
|
|
|
// Do action $hook_name1 but not $hook_name2.
|
|
do_action( $hook_name1 );
|
|
$this->assertSame( 1, did_action( $hook_name1 ) );
|
|
$this->assertSame( 0, did_action( $hook_name2 ) );
|
|
|
|
// Do action $hook_name2 10 times.
|
|
$count = 10;
|
|
for ( $i = 0; $i < $count; $i++ ) {
|
|
do_action( $hook_name2 );
|
|
}
|
|
|
|
// $hook_name1's count hasn't changed, $hook_name2 should be correct.
|
|
$this->assertSame( 1, did_action( $hook_name1 ) );
|
|
$this->assertSame( $count, did_action( $hook_name2 ) );
|
|
}
|
|
|
|
/**
|
|
* @covers ::do_action
|
|
*/
|
|
public function test_all_action() {
|
|
$a = new MockAction();
|
|
$hook_name1 = __FUNCTION__ . '_1';
|
|
$hook_name2 = __FUNCTION__ . '_2';
|
|
|
|
// Add an 'all' action.
|
|
add_action( 'all', array( &$a, 'action' ) );
|
|
$this->assertSame( 10, has_filter( 'all', array( &$a, 'action' ) ) );
|
|
// Do some actions.
|
|
do_action( $hook_name1 );
|
|
do_action( $hook_name2 );
|
|
do_action( $hook_name1 );
|
|
do_action( $hook_name1 );
|
|
|
|
// Our action should have been called once for each tag.
|
|
$this->assertSame( 4, $a->get_call_count() );
|
|
// Only our hook was called.
|
|
$this->assertSame( array( $hook_name1, $hook_name2, $hook_name1, $hook_name1 ), $a->get_hook_names() );
|
|
|
|
remove_action( 'all', array( &$a, 'action' ) );
|
|
$this->assertFalse( has_filter( 'all', array( &$a, 'action' ) ) );
|
|
}
|
|
|
|
/**
|
|
* @covers ::remove_action
|
|
*/
|
|
public function test_remove_all_action() {
|
|
$a = new MockAction();
|
|
$hook_name = __FUNCTION__;
|
|
|
|
add_action( 'all', array( &$a, 'action' ) );
|
|
$this->assertSame( 10, has_filter( 'all', array( &$a, 'action' ) ) );
|
|
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() );
|
|
|
|
// Now remove the action, do it again, and make sure it's not called this time.
|
|
remove_action( 'all', array( &$a, 'action' ) );
|
|
$this->assertFalse( has_filter( 'all', array( &$a, 'action' ) ) );
|
|
do_action( $hook_name );
|
|
$this->assertSame( 1, $a->get_call_count() );
|
|
$this->assertSame( array( $hook_name ), $a->get_hook_names() );
|
|
}
|
|
|
|
/**
|
|
* @covers ::do_action_ref_array
|
|
*/
|
|
public function test_action_ref_array() {
|
|
$obj = new stdClass();
|
|
$a = new MockAction();
|
|
$hook_name = __FUNCTION__;
|
|
|
|
add_action( $hook_name, array( &$a, 'action' ) );
|
|
|
|
do_action_ref_array( $hook_name, array( &$obj ) );
|
|
|
|
$args = $a->get_args();
|
|
$this->assertSame( $args[0][0], $obj );
|
|
// Just in case we don't trust assertSame().
|
|
$obj->foo = true;
|
|
$this->assertNotEmpty( $args[0][0]->foo );
|
|
}
|
|
|
|
/**
|
|
* @ticket 11241
|
|
*
|
|
* @covers ::do_action
|
|
*/
|
|
public function test_action_keyed_array() {
|
|
$a = new MockAction();
|
|
$hook_name = __FUNCTION__;
|
|
|
|
add_action( $hook_name, array( &$a, 'action' ) );
|
|
|
|
$context = array( 'key1' => 'val1' );
|
|
do_action( $hook_name, $context );
|
|
|
|
$args = $a->get_args();
|
|
$this->assertSame( $args[0][0], $context );
|
|
|
|
$context2 = array(
|
|
'key2' => 'val2',
|
|
'key3' => 'val3',
|
|
);
|
|
do_action( $hook_name, $context2 );
|
|
|
|
$args = $a->get_args();
|
|
$this->assertSame( $args[1][0], $context2 );
|
|
}
|
|
|
|
/**
|
|
* @ticket 10493
|
|
*
|
|
* @covers ::add_action
|
|
* @covers ::has_action
|
|
* @covers ::do_action
|
|
*/
|
|
public function test_action_closure() {
|
|
$hook_name = __FUNCTION__;
|
|
$closure = static function ( $a, $b ) {
|
|
$GLOBALS[ $a ] = $b;
|
|
};
|
|
add_action( $hook_name, $closure, 10, 2 );
|
|
|
|
$this->assertSame( 10, has_action( $hook_name, $closure ) );
|
|
|
|
$context = array( 'val1', 'val2' );
|
|
do_action( $hook_name, $context[0], $context[1] );
|
|
|
|
$this->assertSame( $GLOBALS[ $context[0] ], $context[1] );
|
|
|
|
$hook_name2 = __FUNCTION__ . '_2';
|
|
$closure2 = static function () {
|
|
$GLOBALS['closure_no_args'] = true;
|
|
};
|
|
add_action( $hook_name2, $closure2 );
|
|
|
|
$this->assertSame( 10, has_action( $hook_name2, $closure2 ) );
|
|
|
|
do_action( $hook_name2 );
|
|
|
|
$this->assertTrue( $GLOBALS['closure_no_args'] );
|
|
|
|
remove_action( $hook_name, $closure );
|
|
remove_action( $hook_name2, $closure2 );
|
|
}
|
|
|
|
/**
|
|
* @ticket 23265
|
|
*
|
|
* @covers ::add_action
|
|
*/
|
|
public function test_action_callback_representations() {
|
|
$hook_name = __FUNCTION__;
|
|
|
|
$this->assertFalse( has_action( $hook_name ) );
|
|
|
|
add_action( $hook_name, array( 'Class', 'method' ) );
|
|
|
|
$this->assertSame( 10, has_action( $hook_name, array( 'Class', 'method' ) ) );
|
|
|
|
$this->assertSame( 10, has_action( $hook_name, 'Class::method' ) );
|
|
}
|
|
|
|
/**
|
|
* @covers ::remove_action
|
|
*/
|
|
public function test_action_self_removal() {
|
|
add_action( 'test_action_self_removal', array( $this, 'action_self_removal' ) );
|
|
do_action( 'test_action_self_removal' );
|
|
$this->assertSame( 1, did_action( 'test_action_self_removal' ) );
|
|
}
|
|
|
|
public function action_self_removal() {
|
|
remove_action( 'test_action_self_removal', array( $this, 'action_self_removal' ) );
|
|
}
|
|
|
|
/**
|
|
* @ticket 17817
|
|
*
|
|
* @covers ::do_action
|
|
*/
|
|
public function test_action_recursion() {
|
|
$hook_name = __FUNCTION__;
|
|
$a = new MockAction();
|
|
$b = new MockAction();
|
|
|
|
add_action( $hook_name, array( $a, 'action' ), 11, 1 );
|
|
add_action( $hook_name, array( $b, 'action' ), 13, 1 );
|
|
add_action( $hook_name, array( $this, 'action_that_causes_recursion' ), 12, 1 );
|
|
do_action( $hook_name, $hook_name );
|
|
|
|
$this->assertSame( 2, $a->get_call_count(), 'recursive actions should call all callbacks with earlier priority' );
|
|
$this->assertSame( 2, $b->get_call_count(), 'recursive actions should call callbacks with later priority' );
|
|
}
|
|
|
|
/**
|
|
* @covers ::do_action
|
|
*/
|
|
public function action_that_causes_recursion( $hook_name ) {
|
|
static $recursing = false;
|
|
if ( ! $recursing ) {
|
|
$recursing = true;
|
|
do_action( $hook_name, $hook_name );
|
|
}
|
|
$recursing = false;
|
|
}
|
|
|
|
/**
|
|
* @ticket 9968
|
|
* @ticket 17817
|
|
*
|
|
* @covers ::remove_action
|
|
* @covers ::add_action
|
|
*/
|
|
public function test_action_callback_manipulation_while_running() {
|
|
$hook_name = __FUNCTION__;
|
|
$a = new MockAction();
|
|
$b = new MockAction();
|
|
$c = new MockAction();
|
|
$d = new MockAction();
|
|
$e = new MockAction();
|
|
|
|
add_action( $hook_name, array( $a, 'action' ), 11, 2 );
|
|
add_action( $hook_name, array( $this, 'action_that_manipulates_a_running_hook' ), 12, 2 );
|
|
add_action( $hook_name, array( $b, 'action' ), 12, 2 );
|
|
|
|
do_action( $hook_name, $hook_name, array( $a, $b, $c, $d, $e ) );
|
|
do_action( $hook_name, $hook_name, array( $a, $b, $c, $d, $e ) );
|
|
|
|
$this->assertSame( 2, $a->get_call_count(), 'callbacks should run unless otherwise instructed' );
|
|
$this->assertSame( 1, $b->get_call_count(), 'callback removed by same priority callback should still get called' );
|
|
$this->assertSame( 1, $c->get_call_count(), 'callback added by same priority callback should not get called' );
|
|
$this->assertSame( 2, $d->get_call_count(), 'callback added by earlier priority callback should get called' );
|
|
$this->assertSame( 1, $e->get_call_count(), 'callback added by later priority callback should not get called' );
|
|
}
|
|
|
|
public function action_that_manipulates_a_running_hook( $hook_name, $mocks ) {
|
|
remove_action( $hook_name, array( $mocks[1], 'action' ), 12, 2 );
|
|
add_action( $hook_name, array( $mocks[2], 'action' ), 12, 2 );
|
|
add_action( $hook_name, array( $mocks[3], 'action' ), 13, 2 );
|
|
add_action( $hook_name, array( $mocks[4], 'action' ), 10, 2 );
|
|
}
|
|
|
|
/**
|
|
* @ticket 17817
|
|
*
|
|
* This specificaly addresses the concern raised at
|
|
* https://core.trac.wordpress.org/ticket/17817#comment:52
|
|
*
|
|
* @covers ::remove_filter
|
|
*/
|
|
public function test_remove_anonymous_callback() {
|
|
$hook_name = __FUNCTION__;
|
|
$a = new MockAction();
|
|
add_action( $hook_name, array( $a, 'action' ), 12, 1 );
|
|
$this->assertTrue( has_action( $hook_name ) );
|
|
|
|
$hook = $GLOBALS['wp_filter'][ $hook_name ];
|
|
|
|
// From http://wordpress.stackexchange.com/a/57088/6445
|
|
foreach ( $hook as $priority => $filter ) {
|
|
foreach ( $filter as $identifier => $function ) {
|
|
if ( is_array( $function )
|
|
&& $function['function'][0] instanceof MockAction
|
|
&& 'action' === $function['function'][1]
|
|
) {
|
|
remove_filter(
|
|
$hook_name,
|
|
array( $function['function'][0], 'action' ),
|
|
$priority
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->assertFalse( has_action( $hook_name ) );
|
|
}
|
|
|
|
|
|
/**
|
|
* Test the ArrayAccess methods of WP_Hook
|
|
*
|
|
* @ticket 17817
|
|
*
|
|
* @covers WP_Hook::offsetGet
|
|
* @covers WP_Hook::offsetSet
|
|
* @covers WP_Hook::offsetUnset
|
|
*/
|
|
public function test_array_access_of_wp_filter_global() {
|
|
global $wp_filter;
|
|
|
|
$hook_name = __FUNCTION__;
|
|
|
|
add_action( $hook_name, '__return_null', 11, 1 );
|
|
|
|
$this->assertArrayHasKey( 11, $wp_filter[ $hook_name ] );
|
|
$this->assertArrayHasKey( '__return_null', $wp_filter[ $hook_name ][11] );
|
|
|
|
unset( $wp_filter[ $hook_name ][11] );
|
|
$this->assertFalse( has_action( $hook_name, '__return_null' ) );
|
|
|
|
$wp_filter[ $hook_name ][11] = array(
|
|
'__return_null' => array(
|
|
'function' => '__return_null',
|
|
'accepted_args' => 1,
|
|
),
|
|
);
|
|
$this->assertSame( 11, has_action( $hook_name, '__return_null' ) );
|
|
}
|
|
|
|
/**
|
|
* Make sure current_action() behaves as current_filter()
|
|
*
|
|
* @ticket 14994
|
|
*
|
|
* @covers ::current_action
|
|
*/
|
|
public function test_current_action() {
|
|
global $wp_current_filter;
|
|
|
|
$wp_current_filter[] = 'first';
|
|
$wp_current_filter[] = 'second'; // Let's say a second action was invoked.
|
|
|
|
$this->assertSame( 'second', current_action() );
|
|
}
|
|
|
|
/**
|
|
* @ticket 14994
|
|
*
|
|
* @covers ::doing_filter
|
|
*/
|
|
public function test_doing_filter() {
|
|
global $wp_current_filter;
|
|
|
|
$wp_current_filter = array(); // Set to an empty array first.
|
|
|
|
$this->assertFalse( doing_filter() ); // No filter is passed in, and no filter is being processed.
|
|
$this->assertFalse( doing_filter( 'testing' ) ); // Filter is passed in but not being processed.
|
|
|
|
$wp_current_filter[] = 'testing';
|
|
|
|
$this->assertTrue( doing_filter() ); // No action is passed in, and a filter is being processed.
|
|
$this->assertTrue( doing_filter( 'testing' ) ); // Filter is passed in and is being processed.
|
|
$this->assertFalse( doing_filter( 'something_else' ) ); // Filter is passed in but not being processed.
|
|
|
|
$wp_current_filter = array();
|
|
}
|
|
|
|
/**
|
|
* @ticket 14994
|
|
*
|
|
* @covers ::doing_filter
|
|
*/
|
|
public function test_doing_action() {
|
|
global $wp_current_filter;
|
|
|
|
$wp_current_filter = array(); // Set to an empty array first.
|
|
|
|
$this->assertFalse( doing_action() ); // No action is passed in, and no filter is being processed.
|
|
$this->assertFalse( doing_action( 'testing' ) ); // Action is passed in but not being processed.
|
|
|
|
$wp_current_filter[] = 'testing';
|
|
|
|
$this->assertTrue( doing_action() ); // No action is passed in, and a filter is being processed.
|
|
$this->assertTrue( doing_action( 'testing' ) ); // Action is passed in and is being processed.
|
|
$this->assertFalse( doing_action( 'something_else' ) ); // Action is passed in but not being processed.
|
|
|
|
$wp_current_filter = array();
|
|
}
|
|
|
|
/**
|
|
* @ticket 14994
|
|
*
|
|
* @covers ::doing_filter
|
|
*/
|
|
public function test_doing_filter_real() {
|
|
$this->assertFalse( doing_filter() ); // No filter is passed in, and no filter is being processed.
|
|
$this->assertFalse( doing_filter( 'testing' ) ); // Filter is passed in but not being processed.
|
|
|
|
add_filter( 'testing', array( $this, 'apply_testing_filter' ) );
|
|
$this->assertTrue( has_action( 'testing' ) );
|
|
$this->assertSame( 10, has_action( 'testing', array( $this, 'apply_testing_filter' ) ) );
|
|
|
|
apply_filters( 'testing', '' );
|
|
|
|
// Make sure it ran.
|
|
$this->assertTrue( $this->apply_testing_filter );
|
|
|
|
$this->assertFalse( doing_filter() ); // No longer doing any filters.
|
|
$this->assertFalse( doing_filter( 'testing' ) ); // No longer doing this filter.
|
|
}
|
|
|
|
public function apply_testing_filter() {
|
|
$this->apply_testing_filter = true;
|
|
|
|
$this->assertTrue( doing_filter() );
|
|
$this->assertTrue( doing_filter( 'testing' ) );
|
|
$this->assertFalse( doing_filter( 'something_else' ) );
|
|
$this->assertFalse( doing_filter( 'testing_nested' ) );
|
|
|
|
add_filter( 'testing_nested', array( $this, 'apply_testing_nested_filter' ) );
|
|
$this->assertTrue( has_action( 'testing_nested' ) );
|
|
$this->assertSame( 10, has_action( 'testing_nested', array( $this, 'apply_testing_nested_filter' ) ) );
|
|
|
|
apply_filters( 'testing_nested', '' );
|
|
|
|
// Make sure it ran.
|
|
$this->assertTrue( $this->apply_testing_nested_filter );
|
|
|
|
$this->assertFalse( doing_filter( 'testing_nested' ) );
|
|
$this->assertFalse( doing_filter( 'testing_nested' ) );
|
|
}
|
|
|
|
public function apply_testing_nested_filter() {
|
|
$this->apply_testing_nested_filter = true;
|
|
$this->assertTrue( doing_filter() );
|
|
$this->assertTrue( doing_filter( 'testing' ) );
|
|
$this->assertTrue( doing_filter( 'testing_nested' ) );
|
|
$this->assertFalse( doing_filter( 'something_else' ) );
|
|
}
|
|
|
|
/**
|
|
* @ticket 10441
|
|
* @expectedDeprecated tests_do_action_deprecated
|
|
*
|
|
* @covers ::do_action_deprecated
|
|
*/
|
|
public function test_do_action_deprecated() {
|
|
$p = new WP_Post( (object) array( 'post_title' => 'Foo' ) );
|
|
|
|
add_action( 'tests_do_action_deprecated', array( __CLASS__, 'deprecated_action_callback' ) );
|
|
do_action_deprecated( 'tests_do_action_deprecated', array( $p ), '4.6.0' );
|
|
remove_action( 'tests_do_action_deprecated', array( __CLASS__, 'deprecated_action_callback' ) );
|
|
|
|
$this->assertSame( 'Bar', $p->post_title );
|
|
}
|
|
|
|
public static function deprecated_action_callback( $p ) {
|
|
$p->post_title = 'Bar';
|
|
}
|
|
|
|
/**
|
|
* @ticket 10441
|
|
* @expectedDeprecated tests_do_action_deprecated
|
|
*
|
|
* @covers ::do_action_deprecated
|
|
*/
|
|
public function test_do_action_deprecated_with_multiple_params() {
|
|
$p1 = new WP_Post( (object) array( 'post_title' => 'Foo1' ) );
|
|
$p2 = new WP_Post( (object) array( 'post_title' => 'Foo2' ) );
|
|
|
|
add_action( 'tests_do_action_deprecated', array( __CLASS__, 'deprecated_action_callback_multiple_params' ), 10, 2 );
|
|
do_action_deprecated( 'tests_do_action_deprecated', array( $p1, $p2 ), '4.6.0' );
|
|
remove_action( 'tests_do_action_deprecated', array( __CLASS__, 'deprecated_action_callback_multiple_params' ), 10, 2 );
|
|
|
|
$this->assertSame( 'Bar1', $p1->post_title );
|
|
$this->assertSame( 'Bar2', $p2->post_title );
|
|
}
|
|
|
|
public static function deprecated_action_callback_multiple_params( $p1, $p2 ) {
|
|
$p1->post_title = 'Bar1';
|
|
$p2->post_title = 'Bar2';
|
|
}
|
|
}
|