<?php
/**
* This file contains Sensei_Scheduler class.
*
* @package sensei
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Fetch the correct scheduler.
*
* @since 3.0.0
*/
class Sensei_Scheduler {
/**
* Instance of the current handler.
*
* @var Sensei_Scheduler_Interface
*/
private static $instance;
/**
* Get the instance of the Scheduler to use.
*
* @return Sensei_Scheduler_Interface
*/
public static function instance() {
if ( ! isset( self::$instance ) ) {
$class_name = self::get_class();
self::$instance = new $class_name();
}
return self::$instance;
}
/**
* Initialize actions.
*/
public static function init() {
add_action( Sensei_Background_Job_Stateful::NAME, [ __CLASS__, 'run_stateful_job' ] );
}
/**
* Run a stateful job.
*
* @param array $args The job arguments.
*
* @return bool
*/
public static function run_stateful_job( $args ) : bool {
if (
empty( $args['id'] )
|| empty( $args['class'] )
|| ! class_exists( (string) $args['class'] )
|| ! is_subclass_of( (string) $args['class'], Sensei_Background_Job_Stateful::class )
) {
return false;
}
$id = (string) $args['id'];
$class_name = (string) $args['class'];
unset( $args['id'], $args['class'] );
$job = new $class_name( $args, $id );
self::instance()->run(
$job,
function() use ( $job ) {
$job->cleanup();
}
);
$job->persist();
return true;
}
/**
* Get the class for the scheduler.
*
* @return string
*/
private static function get_class() {
if ( 0 === did_action( 'plugins_loaded' ) ) {
_doing_it_wrong( __METHOD__, 'Scheduler should not be used until after the plugins are loaded.', '3.0.0' );
}
$default_class_name = Sensei_Scheduler_WP_Cron::class;
if ( self::is_action_scheduler_available() ) {
$default_class_name = Sensei_Scheduler_Action_Scheduler::class;
}
/**
* Override the default class that implements `Sensei_Scheduler_Interface`.
*
* @since 3.0.0
*
* @hook sensei_scheduler_class
*
* @param {string} $class_name Class for the scheduler that should be used by Sensei.
* @return {string} Filtered class name.
*/
$class_name = apply_filters( 'sensei_scheduler_class', $default_class_name );
if ( ! is_subclass_of( $class_name, Sensei_Scheduler_Interface::class, true ) ) {
_doing_it_wrong( __METHOD__, 'The filter "sensei_scheduler_class" returned an invalid scheduler.', '3.0.0' );
$class_name = $default_class_name;
}
return $class_name;
}
/**
* Check to see if Action Scheduler is available.
*
* @return bool
*/
private static function is_action_scheduler_available() {
return class_exists( 'ActionScheduler_Versions' )
&& function_exists( 'as_unschedule_all_actions' )
&& function_exists( 'as_next_scheduled_action' )
&& function_exists( 'as_schedule_single_action' );
}
}