Skip to content

Instantly share code, notes, and snippets.

@peterwilsoncc
Last active March 1, 2020 23:38
Show Gist options
  • Select an option

  • Save peterwilsoncc/b83a23abb0c75a4cdf9301da12f245a6 to your computer and use it in GitHub Desktop.

Select an option

Save peterwilsoncc/b83a23abb0c75a4cdf9301da12f245a6 to your computer and use it in GitHub Desktop.
<?php
namespace PWCC\NightlyCronSchedule;
use DateTime;
use DateTimeZone;
use HM\Cavalcade\Plugin\Job;
/**
* Register hooks for WordPress.
*/
function bootstrap() {
if ( ! class_exists( 'HM\Cavalcade\Plugin\Job' ) ) {
return;
}
add_filter( 'pre_get_scheduled_event', __NAMESPACE__ . '\\pre_get_scheduled_event', 5, 4 );
add_filter( 'schedule_event', __NAMESPACE__ . '\\schedule_event' );
}
function enforced_daily_schedules() {
/**
* Daily cron events to be enforced to run at a
* particular hour.
*
* @param array $daily_events Events scheduled to run daily at particular times.
* The key is the hook name, the value the hour of day.
*/
return apply_filters(
'pwcc.nightly-cron-scheduled.enforced-daily-schedules',
[
'wp_scheduled_delete' => 02,
'wp_scheduled_auto_draft_delete' => 03,
'delete_expired_transients' => 04,
]
);
}
/**
* When getting Core daily tasks, ensure they are scheduled for night time.
*
* Ensure the following core hooks are scheduled to run within a ten minute window
* of the specified time.
* - wp_scheduled_delete: 2am
* - wp_scheduled_auto_draft_delete: 3am
* - delete_expired_transients: 4am
*
* @param null|bool $pre Value to return instead. Default null to continue adding the event.
* @param stdClass $event {
* An object containing an event's data.
*
* @type string $hook Action hook to execute when the event is run.
* @type int $timestamp Unix timestamp (UTC) for when to next run the event.
* @type string|false $schedule How often the event should subsequently recur.
* @type array $args Array containing each separate argument to pass to the hook's callback function.
* @type int $interval The interval time in seconds for the schedule. Only present for recurring events.
* }
* @return null|bool True if event successfully scheduled. False for failure.
*/
function pre_get_scheduled_event( $pre, $hook, $args, $timestamp ) {
$core_schedules = enforced_daily_schedules();
if ( ! in_array( $hook, array_keys( $core_schedules ), true ) ) {
return $pre;
}
$jobs = Job::get_jobs_by_query( [
'hook' => $hook,
'timestamp' => $timestamp,
'args' => $args,
] );
if ( is_wp_error( $jobs ) || empty( $jobs ) ) {
return false;
}
$job = $jobs[0];
$date = new DateTime();
$date->setTimestamp( $job->nextrun );
$date->setTimezone( new DateTimeZone( get_option('timezone_string') ) );
$date->modify( '-15 minutes' );
$start = (int) $date->format( 'Hi' );
$date->modify( '+30 minutes' );
$end = (int) $date->format( 'Hi' );
if (
( $core_schedules[ $hook ] * 100 ) < $start ||
( $core_schedules[ $hook ] * 100 ) > $end
) {
// Outside window, delete event and return false.
wp_clear_scheduled_hook( $hook );
return false;
}
/*
* Return $pre and allow Cavalcade to deal with object creation and
* dealing with any compatibility changes required for core.
*/
return $pre;
}
/**
* Ensure core daily tasks are scheduled for night time.
*
* Ensure the following core hooks are scheduled to run at the specified time.
* - wp_scheduled_delete: 2am
* - wp_scheduled_auto_draft_delete: 3am
* - delete_expired_transients: 4am
*
* @param stdClass $event {
* An object containing an event's data.
*
* @type string $hook Action hook to execute when the event is run.
* @type int $timestamp Unix timestamp (UTC) for when to next run the event.
* @type string|false $schedule How often the event should subsequently recur.
* @type array $args Array containing each separate argument to pass to the hook's callback function.
* @type int $interval The interval time in seconds for the schedule. Only present for recurring events.
* }
*/
function schedule_event( $event ) {
$core_schedules = enforced_daily_schedules();
if ( ! in_array( $event->hook, array_keys( $core_schedules ), true ) ) {
return $event;
}
$date = new DateTime();
$date->setTimestamp( $event->timestamp );
$date->setTimezone( new DateTimeZone( get_option('timezone_string') ));
$date->modify( sprintf( 'tomorrow %d hours', $core_schedules[ $event->hook ] ) );
$date->setTime( $core_schedules[ $event->hook ], 0 );
$event->timestamp = $date->getTimestamp();
return $event;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment