WordPress at Your Fingertips

Kama_Cron

A small class for easily adding WP Cron tasks (jobs).

This Class allow you to create WordPress Cron tasks in a quick and simple way. In order not to confuse anything, all settings are specified in the first parameter when calling the class. The class takes care of the entire routine of correctly registering the Cron task and their intervals. The task handler (the function) need to be written separately in PHP!

Kama_Cron class code

GitHub
<?php


/**
 * Convenient way to add cron tasks in WordPress.
 *
 * Usage Example:
 *
 * ```
 * new Kama_Cron( [
 *     'wpkama_cron_func' => [
 *         'callback'      => 'wpkama_cron_func', // PHP function to run on job
 *         'interval_name' => '10_min',           // you can set already registered interval: hourly, twicedaily, daily
 *         'interval_desc' => 'Every 10 min',     // no need if already registered interval is set.
 *     ],
 * ] );
 *
 * new Kama_Cron( [
 *     'single_job' => [
 *         'callback' => 'single_job_func',
 *         'start_time' => strtotime( '2021-06-05' ),
 *     ],
 * ] );
 *
 * new Kama_Cron( [
 *     'id'     => 'my_cron_jobs', // not required param
 *     'events' => [
 *         // first task
 *         'wpkama_cron_func' => [
 *             'callback'      => 'wpkama_cron_func', // PHP function to run on job
 *             'interval_name' => '10_min',           // you can set already registered interval: hourly, twicedaily, daily
 *             'interval_desc' => 'Every 10 min',     // no need if already registered interval is set.
 *         ],
 *         // second task
 *         'wpkama_cron_func_2' => [
 *             'callback'      => 'wpkama_cron_func_2',
 *             'start_time'    => time() + DAY_IN_SECONDS, // start in 1 day
 *             'interval_name' => 'two_hours',
 *             'interval_sec'  => HOUR_IN_SECONDS * 2,
 *             'interval_desc' => 'Every 2 hours',
 *         ],
 *         // third task
 *         'wpkama_cron_func_3' => [
 *             'callback'      => 'wpkama_cron_func_3',
 *             'interval_name' => 'hourly', // this is already a known WP interval
 *         ],
 *     ],
 * ] );
 * ```
 *
 *
 * Changelog: https://github.com/doiftrue/Kama_Cron/blob/master/changelog.md
 *
 * @author Kama (wp-kama.com)
 *
 * @version 0.4.8
 */
class Kama_Cron {

	// must be 0 on production.
	// For debug go to: http://site.com/wp-cron.php
	static $DEBUG = false;

	// internal (Collects every cron options called with this class).
	static $opts;

	// internal id for opts (Not used for cron).
	protected $id;

	/**
	 * Constructor.
	 *
	 * @param array $args {
	 *     Args.
	 *
	 *     @type string $id             A unique identifier that can then be used to access the settings.
	 *                                  Default: keys of the $events parameter.
	 *     @type bool   $auto_activate  true - automatically creates the specified event when visiting the admin panel.
	 *                                  In this case, you do not need to call the activate() method separately.
	 *     @type array  $events         {
	 *        An array of events to add to the crown. The element key will be used in the cron hook.
	 *        The element value is an array of event parameters that can contain the following keys:
	 *
	 *        @type callable  $callback       The name of the crown task function.
	 *        @type mixed     $args           What parameters should be passed to the crown task function.
	 *        @type string    $interval_name  The name of the interval, for example: 'half_an_hover'.
	 *                                        You can specify the name in the following format:
	 *                                        `N_(min|hour|day|month)` — 10_min, 2_hours, 5_days, 2_month,
	 *                                        then the number will be taken as interval time.
	 *                                        You can specify an existing WP interval: hourly, twicedaily, daily,
	 *                                        then the interval time should not be set.
	 *                                        Omite this parameter to register single cron job.
	 *        @type int       $interval_sec   Interval time, for example HOUR_IN_SECONDS / 2.
	 *                                        You don't need to specify this papameter when $interval_name one of:
	 *                                        N_(min|hour|day|month), hourly, twicedaily, daily.
	 *        @type string    $interval_desc  Description of the interval, for example, 'Every half hour'.
	 *                                        You don't need to specify this param when $interval_name one of:
	 *                                        hourly, twicedaily, daily.
	 *        @type int       $start_time     UNIX timestamp. When to start the event. By default: time().
	 *     }
	 *
	 * }
	 */
	public function __construct( $args ){

		if( empty( $args['events'] ) ){
			$args = [ 'events' => $args ];
		}

		$args_def = [
			'id' => implode( '--', array_keys( $args['events'] ) ),

			'auto_activate' => true,

			'events' => [
				'hook_name' => [
					'callback'      => [ __CLASS__, 'default_callback' ],
					'args'          => [],
					'interval_name' => '',
					'interval_sec'  => 0,
					'interval_desc' => '',
					'start_time'    => 0,
				],
			],
		];

		$event_def = $args_def['events']['hook_name'];
		unset( $args_def['events'] );

		// complete parameters using defaults
		$args = array_merge( $args_def, $args );
		// complete `events` elements
		foreach( $args['events'] as & $events ){
			$events = array_merge( $event_def, $events );
		}
		unset( $events );

		$rg = (object) $args;

		$this->id = $rg->id;

		self::$opts[ $this->id ] = $rg;

		// after self::$opts
		add_filter( 'cron_schedules', [ $this, 'add_intervals' ] );

		// after 'cron_schedules'
		if( $rg->auto_activate && ( is_admin() || defined( 'WP_CLI' ) || defined( 'DOING_CRON' ) ) ){
			self::activate( $this->id );
		}

		foreach( $rg->events as $hook => $data ){
			add_action( $hook, $data['callback'] );
		}

		if( self::$DEBUG && defined( 'DOING_CRON' ) ){

			add_action( 'wp_loaded', function(){
				echo 'Current time: ' . time() . "\n\n\n" . 'Existing Intervals:' . "\n" .
				     print_r( wp_get_schedules(), 1 ) . "\n\n\n" . print_r( _get_cron_array(), 1 );
			} );
		}
	}

	public function add_intervals( $schedules ){

		foreach( self::$opts[ $this->id ]->events as $data ){

			// it is a single event.
			if( ! $interval_name = $data['interval_name'] )
				continue;

			if( isset( $schedules[ $interval_name ] ) || in_array( $interval_name, [ 'hourly', 'twicedaily', 'daily' ] ) ){
				continue;
			}

			// allow set only `interval_name` parameter like: 10_min, 2_hours, 5_days, 2_month
			if( ! $data['interval_sec'] ){

				if( preg_match( '/(\d+)[_-](min|hour|day|month)s?/', $interval_name, $mm ) ){
					$min = 60;
					$hour = $min * 60;
					$day = $hour * 24;
					$month = $day * 30;

					$data['interval_sec'] = $mm[1] * ${$mm[2]};
				}
				else {
					wp_die( 'ERROR: Kama_Cron required event parameter `interval_sec` not set. ' . print_r( debug_backtrace(), 1 ) );
				}
			}

			$schedules[ $interval_name ] = [
				'interval' => $data['interval_sec'],
				'display'  => $data['interval_desc'],
			];
		}

		return $schedules;
	}

	/**
	 * Add cron task.
	 * Should be called on plugin activation. Can be called somewhere else, for example, when updating the settings.
	 *
	 * @param string $id
	 */
	static function activate( $id = '' ){

		$opts = $id ? [ $id => self::$opts[ $id ] ] : self::$opts;

		foreach( $opts as $opt ){

			foreach( $opt->events as $hook => $data ){

				if( wp_next_scheduled( $hook, $data['args'] ) )
					continue;

				if( $data['interval_name'] ){
					wp_schedule_event( $data['start_time'] ?: time(), $data['interval_name'], $hook, $data['args'] );
				}
				// single event
				else {
					if( ! $data['start_time'] ){
						trigger_error( __CLASS__ . ' ERROR: Start time not specified for single event' );
					}
					elseif( $data['start_time'] > time() ){
						wp_schedule_single_event( $data['start_time'], $hook, $data['args'] );
					}
				}

			}
		}
	}

	/**
	 * Removes cron task.
	 * Should be called on plugin deactivation.
	 *
	 * @param string $id
	 */
	static function deactivate( $id = '' ){

		$opts = $id ? [ $id => self::$opts[ $id ] ] : self::$opts;

		foreach( $opts as $opt ){

			foreach( $opt->events as $hook => $data ){
				wp_clear_scheduled_hook( $hook, $data['args'] );
			}
		}
	}

	static function default_callback(){

		echo "ERROR: One of Kama_Cron callback function not set.\n\nKama_Cron::\$opts = " .
		     print_r( self::$opts, 1 ) . "\n\n\n\n_get_cron_array() =" .
		     print_r( _get_cron_array(), 1 );
	}

}

Examples of usage Kama_Cron

To get started, copy the class code and paste it into the plugin or theme functions.php file.

You can call new Kama_Cron() at the earliest stage of WP loading, starting from the earliest action muplugins_loaded.

IMPORTANT! The new Kama_Cron() must be triggered (called) on crown requests, since it registers the necessary WP hooks that do the staff on crown requests. In other words, you cannot register a cron task with this code and delete it.

Example 1: Simple usage without additional parameters

In this example specified Cron task will be registered automatically when you visit admin-panel or on any Cron Request.

wpkama_cron_hook - it's an internal name of WP hook you don't need to use it anywhere in your code - just specify understandable name (you may specify the name of the PHP function).

Use WP unknown interval:

new Kama_Cron( [
	'wpkama_cron_hook' => [
		'callback'      => 'wpkama_cron_func', // PHP function to run on job
		'interval_name' => '10_min',           // you can set already registered interval: hourly, twicedaily, daily
		'interval_desc' => 'Every 10 min',     // no need if already registered interval is set.
	],
] );

function wpkama_cron_func(){
	// your code to do the cron job
}

Use WP known interval:

new Kama_Cron( [
	'wpkama_core_data_check_update' => [
		'callback'      => 'wpkama_core_data_check_update',
		'interval_name' => 'hourly',
	]
] );

function wpkama_core_data_check_update(){
	// your code to do the cron job
}

Example 2: Let's create 3 cron jobs

Create 3 Cron tasks with different intervals. The tasks registered automatically when visiting admin-pane (it works very quick).

The code can be passed on any period of page load (php load) all necessary hooks will be added automatically. For example let's past ti in functions.php theme file.

new Kama_Cron( [
	'id' => 'my_cron_jobs', // optional parameter
	'events' => array(
		// first job
		'wpkama_cron_func' => array(
			'callback'      => 'wpkama_cron_func', // name of the crown task function
			'interval_name' => '10_min',           // you can specify an existing interval: hourly, twicedaily, daily
			'interval_desc' => 'Каждые 10 минут',  // not needed if an existing interval was set
		),
		// second job
		'wpkama_cron_func_2' => array(
			'callback'      => 'wpkama_cron_func_2',
			'start_time'    => time() + DAY_IN_SECONDS, // start in 1 day
			'interval_name' => 'two_hours',
			'interval_sec'  => HOUR_IN_SECONDS * 2,
			'interval_desc' => 'Every 2 hours',
		),
		// third job
		'wpkama_cron_func_3' => array(
			'callback'      => 'wpkama_cron_func_3',
			'interval_name' => 'hourly', // this is the already known WP interval
		),
	),
] );

//Kama_Cron::$DEBUG = 1;                 // for debag
//Kama_Cron::deactivate('my_cron_jobs'); // to delete

// Cron function
function wpkama_cron_func(){
	file_put_contents( dirname(ABSPATH) .'/cron_check.txt', current_time('mysql') ."\n", FILE_APPEND );
}

// Cron function
function wpkama_cron_func_2(){
	// operations
}

// Cron function
function wpkama_cron_func_3(){
	// operations
}

Example 3: Registering single taks

new Kama_Cron( [
	// single task
	'wpkama_cron_func_3' => [
		'callback'      => 'wpkama_cron_func_4',
	],
] );

Example 4: Registering tasks when activate a plugin

The code below shows how to activate and deactivate tasks on plugin activation / deactivation.

// Example of activation and deactivation, if the `auto_activate` parameter is not specified
register_activation_hook( __FILE__, function(){
	Kama_Cron::activate( 'my_cron_jobs_2' );
} );

register_deactivation_hook( __FILE__, function(){
	Kama_Cron::deactivate( 'my_cron_jobs_2' );
} );

new Kama_Cron( [
	'id' => 'my_cron_jobs_2',
	'auto_activate' => false, // to call task activation on register_activation_hook()
	'events' => [
		// first task
		'wpkama_cron_func_4' => [
			'callback'      => 'wpkama_cron_func_4', // name of the cron-task function
			'interval_name' => 'twicedaily', // you can specify an existing interval: hourly, twicedaily, daily
		],
		// second task
		'wpkama_cron_func_5' => [
			'callback'      => 'wpkama_cron_func_5',
			'interval_name' => 'two_hours',
			'interval_sec'  => HOUR_IN_SECONDS * 2,
			'interval_desc' => 'Каждые 2 часа',
		],
	],
] );

function wpkama_cron_func_4(){
	// operations
}

function wpkama_cron_func_5(){
	// operations
}
No comments
    Log In