mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2026-04-01 03:04:34 +00:00
Cron: Add hooks and a function to allow hijacking cron implementation.
This allows sites with a large cron option or a custom cron implementation to hijack the cron option to store cron data using custom functionality. `wp_get_scheduled_event()` is new function to retrieve the event object for a given event based on the hook name, arguments and timestamp. If no timestamp is specified the next occurence is returned. Preflight filters are added to all functions that read from or modify the cron option: `pre_schedule_event`, `pre_reschedule_event`, `pre_unschedule_event`, `pre_clear_scheduled_hook`, `pre_unschedule_hook`, `pre_get_scheduled_event` and `pre_next_scheduled`. Additionally, the post scheduling hooks `next_scheduled` and `get_schedule` to allow plugins to modify an event after retrieving it from WordPress. Props rmccue, DavidAnderson, ethitter, peterwilsoncc. Fixes #32656. git-svn-id: https://develop.svn.wordpress.org/trunk@43540 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
@@ -6,10 +6,22 @@
|
||||
* @group cron
|
||||
*/
|
||||
class Tests_Cron extends WP_UnitTestCase {
|
||||
/**
|
||||
* @var array Cron array for testing preflight filters.
|
||||
*/
|
||||
private $preflight_cron_array;
|
||||
|
||||
/**
|
||||
* @var int Timestamp of now() + 30 minutes;
|
||||
*/
|
||||
private $plus_thirty_minutes;
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
// make sure the schedule is clear
|
||||
_set_cron_array( array() );
|
||||
$this->preflight_cron_array = array();
|
||||
$this->plus_thirty_minutes = strtotime( '+30 minutes' );
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
@@ -306,4 +318,168 @@ class Tests_Cron extends WP_UnitTestCase {
|
||||
// following event should be there too
|
||||
$this->assertEquals( $ts2, wp_next_scheduled( $hook, $args ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the pre_scheduled_event filter prevents
|
||||
* modification of the cron_array_option.
|
||||
*
|
||||
* @ticket 32656
|
||||
*/
|
||||
function test_pre_schedule_event_filter() {
|
||||
$hook = __FUNCTION__;
|
||||
$args = array( 'arg1' );
|
||||
$ts1 = strtotime( '+30 minutes' );
|
||||
$ts2 = strtotime( '+3 minutes' );
|
||||
|
||||
$expected = _get_cron_array();
|
||||
|
||||
add_filter( 'pre_schedule_event', array( $this, '_filter_pre_schedule_event_filter' ), 10, 2 );
|
||||
|
||||
$this->assertTrue( wp_schedule_single_event( $ts1, $hook, $args ) );
|
||||
$this->assertTrue( wp_schedule_event( $ts2, 'hourly', $hook ) );
|
||||
|
||||
// Check cron option is unchanged.
|
||||
$this->assertSame( $expected, _get_cron_array() );
|
||||
|
||||
$expected_preflight[ $ts2 ][ $hook ][ md5( serialize( array() ) ) ] = array(
|
||||
'schedule' => 'hourly',
|
||||
'interval' => HOUR_IN_SECONDS,
|
||||
'args' => array(),
|
||||
);
|
||||
|
||||
$expected_preflight[ $ts1 ][ $hook ][ md5( serialize( $args ) ) ] = array(
|
||||
'schedule' => false,
|
||||
'interval' => 0,
|
||||
'args' => $args,
|
||||
);
|
||||
|
||||
$this->assertSame( $expected_preflight, $this->preflight_cron_array );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the scheduling of events to use the preflight array.
|
||||
*/
|
||||
function _filter_pre_schedule_event_filter( $null, $event ) {
|
||||
$key = md5( serialize( $event->args ) );
|
||||
|
||||
$this->preflight_cron_array[ $event->timestamp ][ $event->hook ][ $key ] = array(
|
||||
'schedule' => $event->schedule,
|
||||
'interval' => isset( $event->interval ) ? $event->interval : 0,
|
||||
'args' => $event->args,
|
||||
);
|
||||
uksort( $this->preflight_cron_array, 'strnatcasecmp' );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the pre_reschedule_event filter prevents
|
||||
* modification of the cron_array_option.
|
||||
*
|
||||
* @ticket 32656
|
||||
*/
|
||||
function test_pre_reschedule_event_filter() {
|
||||
$hook = __FUNCTION__;
|
||||
$ts1 = strtotime( '+30 minutes' );
|
||||
|
||||
// Add an event
|
||||
$this->assertTrue( wp_schedule_event( $ts1, 'hourly', $hook ) );
|
||||
$expected = _get_cron_array();
|
||||
|
||||
// Add preflight filter.
|
||||
add_filter( 'pre_reschedule_event', '__return_true' );
|
||||
|
||||
// Reschedule event with preflight filter in place.
|
||||
wp_reschedule_event( $ts1, 'daily', $hook );
|
||||
|
||||
// Check cron option is unchanged.
|
||||
$this->assertSame( $expected, _get_cron_array() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the pre_unschedule_event filter prevents
|
||||
* modification of the cron_array_option.
|
||||
*
|
||||
* @ticket 32656
|
||||
*/
|
||||
function test_pre_unschedule_event_filter() {
|
||||
$hook = __FUNCTION__;
|
||||
$ts1 = strtotime( '+30 minutes' );
|
||||
|
||||
// Add an event
|
||||
$this->assertTrue( wp_schedule_event( $ts1, 'hourly', $hook ) );
|
||||
$expected = _get_cron_array();
|
||||
|
||||
// Add preflight filter.
|
||||
add_filter( 'pre_unschedule_event', '__return_true' );
|
||||
|
||||
// Unschedule event with preflight filter in place.
|
||||
wp_unschedule_event( $ts1, $hook );
|
||||
|
||||
// Check cron option is unchanged.
|
||||
$this->assertSame( $expected, _get_cron_array() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the clearing scheduled hooks filter prevents
|
||||
* modification of the cron_array_option.
|
||||
*
|
||||
* @ticket 32656
|
||||
*/
|
||||
function test_pre_clear_scheduled_hook_filters() {
|
||||
$hook = __FUNCTION__;
|
||||
$ts1 = strtotime( '+30 minutes' );
|
||||
|
||||
// Add an event
|
||||
$this->assertTrue( wp_schedule_event( $ts1, 'hourly', $hook ) );
|
||||
$expected = _get_cron_array();
|
||||
|
||||
// Add preflight filters.
|
||||
add_filter( 'pre_clear_scheduled_hook', '__return_true' );
|
||||
add_filter( 'pre_unschedule_hook', '__return_zero' );
|
||||
|
||||
// Unschedule event with preflight filter in place.
|
||||
wp_clear_scheduled_hook( $hook );
|
||||
|
||||
// Check cron option is unchanged.
|
||||
$this->assertSame( $expected, _get_cron_array() );
|
||||
|
||||
// Unschedule all events with preflight filter in place.
|
||||
wp_unschedule_hook( $hook );
|
||||
|
||||
// Check cron option is unchanged.
|
||||
$this->assertSame( $expected, _get_cron_array() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the preflight hooks for scheduled events
|
||||
* return a filtered value as expected.
|
||||
*
|
||||
* @ticket 32656
|
||||
*/
|
||||
function test_pre_scheduled_event_hooks() {
|
||||
add_filter( 'pre_get_scheduled_event', array( $this, 'filter_pre_scheduled_event_hooks' ) );
|
||||
add_filter( 'pre_next_scheduled', array( $this, 'filter_pre_scheduled_event_hooks' ) );
|
||||
|
||||
$actual = wp_get_scheduled_event( 'preflight_event', array(), $this->plus_thirty_minutes );
|
||||
$actual2 = wp_next_scheduled( 'preflight_event', array() );
|
||||
|
||||
$expected = (object) array(
|
||||
'hook' => 'preflight_event',
|
||||
'timestamp' => $this->plus_thirty_minutes,
|
||||
'schedule' => false,
|
||||
'args' => array(),
|
||||
);
|
||||
|
||||
$this->assertEquals( $expected, $actual );
|
||||
$this->assertEquals( $expected, $actual2 );
|
||||
}
|
||||
|
||||
function filter_pre_scheduled_event_hooks() {
|
||||
return (object) array(
|
||||
'hook' => 'preflight_event',
|
||||
'timestamp' => $this->plus_thirty_minutes,
|
||||
'schedule' => false,
|
||||
'args' => array(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user