WordPress как на ладони
Очень Удобный и Быстрый Хостинг для сайтов на WordPress. Пользуюсь сам и вам рекомендую!

Kama_Cron

Небольшой класс для удобного добавления крон событий (задач) в WordPress.

Класс позволяет быстро и удобно создавать cron задачи, чтобы не перепутать ничего, все настройки указываются в параметре при вызове класса, всю рутину по правильной регистрации крон задач и их интервалов класс берет на себя. Функции-обработчики задач нужно писать отдельно!

Код класса Kama_Cron

GitHub
<?php

namespace Kama\WP;

/**
 * Convenient way to add cron tasks in WordPress.
 *
 * Usage Example:
 *
 * ```
 * new \Kama\WP\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
 *     ],
 * ] );
 *
 * new \Kama\WP\Kama_Cron( [
 *     'single_job' => [
 *         'callback' => 'single_job_func',
 *         'start_time' => strtotime( '2021-06-05' ),
 *     ],
 * ] );
 *
 * new \Kama\WP\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 minutes',       // you can set already registered interval: hourly, twicedaily, daily
 *         ],
 *         // second task
 *         'wpkama_cron_func_2' => [
 *             'callback'      => 'wpkama_cron_func_2',
 *             'interval_name' => '2 hours',
 *             'start_time'    => time() + DAY_IN_SECONDS, // start in 1 day
 *         ],
 *         // 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 1.3
 */
class Kama_Cron {

	/**
	 * Allowed arguments for constructor.
	 *
	 * @see __construct
	 * @var array
	 */
	protected static $default_args = [
		'id' => '',
		'auto_activate' => true,
		'events' => [
			'hook_name' => [
				'callback'      => [ __CLASS__, 'default_callback' ],
				'args'          => [],
				'interval_name' => '',
				'interval_sec'  => 0,
				'interval_desc' => '',
				'start_time'    => 0,
			],
		],
	];

	/**
	 * Collects every cron options called with this class.
	 * It may be useful for any external cases.
	 *
	 * @var array
	 */
	public static $instances = [];

	/**
	 * Must be 0 on production.
	 * For debugging go to: http://site.com/wp-cron.php
	 */
	public const DEBUG = false;

	/**
	 * ID cron args. Internal - not uses for cron.
	 *
	 * @var string
	 */
	protected $id;

	/**
	 * Current instance args.
	 *
	 * @var array
	 */
	protected $args;

	/**
	 * Constructor.
	 *
	 * @param array     $args {
	 *     Args.
	 *
	 *     @type string $id             A unique identifier that can then be used to access the settings externally.
	 *                                  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 {@see self::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 cron task function.
	 *        @type mixed     $args           What parameters should be passed to the cron 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)s` — 10 minutes, 2 hours, 5 days, 2 months,
	 *                                        then the number will be taken to 'interval_sec' parameter.
	 *                                        You can specify an existing WP interval: hourly, twicedaily, daily.
	 *                                        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)s, 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:
	 *                                        N (min|hour|day|month)s, hourly, twicedaily, daily.
	 *        @type int       $start_time     UNIX timestamp. When to start the event. Default: time().
	 *     }
	 *
	 * }
	 */
	public function __construct( array $args ){

		// if passed simple array of events
		if( empty( $args['events'] ) ){
			$args = [ 'events' => $args ];
		}

		// complete passed args using defaults
		$args += [
			'id' => implode( '|', array_keys( $args['events'] ) ),
			'auto_activate' => true,
		];

		// complete each passed 'event' using defaults
		foreach( $args['events'] as $indx => $_event ){
			$args['events'][ $indx ] += self::$default_args['events']['hook_name'];
		}

		$this->args = $args;

		self::$instances[ $this->args['id'] ] = $this;

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

		// after 'cron_schedules'
		// activate only in: admin | WP_CLI | DOING_CRON
		if( $args['auto_activate'] && ( is_admin() || defined( 'WP_CLI' ) || defined( 'DOING_CRON' ) ) ){
			$this->activate();
		}

		// add cron hooks
		foreach( $args['events'] as $hook_name => $task_data ){
			add_action( $hook_name, $task_data['callback'], 10, count( $task_data['args'] ) );
		}

		self::debug_info();
	}

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

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

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

		foreach( $this->args['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
			elseif( ! $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'] );
			}

		}
	}

	public function _add_intervals( $schedules ){

		foreach( $this->args['events'] as $data ){

			$interval_name = $data['interval_name'];

			if(
				// it is a single event.
				! $interval_name
				// already exists
				|| isset( $schedules[ $interval_name ] )
				// internal WP intervals
				|| 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(?:ute)?|hour|day|month)s?/', $interval_name, $mm ) ){
					$min = $minute = 60;
					$hour = $min * 60;
					$day = $hour * 24;
					$month = $day * 30;

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

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

		return $schedules;
	}

	public static function default_callback(){

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

	private static function debug_info(): void {

		if( ! ( self::DEBUG && defined( 'DOING_CRON' ) ) ){
			return;
		}

		add_action( 'wp_loaded', function() {

			echo sprintf( "Current time: %s\n\n\nExisting Intervals:\n%s\n\n\n%s",
				time(), print_r( wp_get_schedules(), 1 ), print_r( _get_cron_array(), 1 )
			);
		} );
	}

}

Установка

Cкопируйте код класса и вставьте его в плагин или functions.php темы. Или используйте composer:

composer require doiftrue/wp-kama-cron

Если используете как пакет composer, то при вызове класса нужно добавить пространство имен

Примеры использования класса Kama_Cron

Вызывать new \Kama\WP\Kama_Cron() можно на самом раннем этапе загрузки WP, начиная с самого раннего события muplugins_loaded.

ВАЖНО! Код вызова new \Kama\WP\Kama_Cron() должен срабатывать (вызываться) при крон запросах, так как на нем регистрируются необходимые WP хуки, которые будут отрабатывать при крон запросах. Другими, словами нельзя зарегистрировать крон задачу с помощью этого кода и удалить его.

Пример 1: Простое использование без дополнительных параметров

В этом примере указанная задача Cron будет зарегистрирована автоматически при посещении админ-панели или при любому Cron запросе.

wpkama_cron_hook - это внутреннее имя хука WP, вам не нужно использовать его где-либо в своем коде - просто укажите понятное имя (можно указать название PHP функции).

Используем неизвестный для WP интервал:

new \Kama\WP\Kama_Cron( [
	'wpkama_cron_hook' => [
		'callback'      => 'wpkama_cron_func', // PHP function to run on job
		'interval_name' => '10 minutes',
	],
] );

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

В этом случае класс распарсит строку '10 minutes' и сам заполнит параметры interval_sec и interval_desc.

Используем известный WP интервал:

new \Kama\WP\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
}

Пример 2: Создадим 3 крон задачи

Создадим 3 крон задачи с разными интервалами. Задачи регистрируются автоматически при посещении админ-панели (это работает очень быстро). Код добавляем куда угодно, например в functions.php.

new \Kama\WP\Kama_Cron([
	'id'     => 'my_cron_jobs', // не обязательный параметр
	'events' => array(
		// первая задача
		'wpkama_cron_func' => array(
			'callback'      => 'wpkama_cron_func', // название функции крон-задачи
			'interval_name' => '10 min',           // можно указать уже имеющийся интервал: hourly, twicedaily, daily

		),
		// вторая задача
		'wpkama_cron_func_2' => array(
			'callback'      => 'wpkama_cron_func_2',
			'start_time'    => time() + DAY_IN_SECONDS, // начать через 1 день
			'interval_name' => '2 hours',
		),
		// третья задача
		'wpkama_cron_func_3' => array(
			'callback'      => 'wpkama_cron_func_3',
			'interval_name' => 'hourly', // это уже известный WP интервал
		),
	),
]);
//\Kama\WP\Kama_Cron::$DEBUG = 1;                 // для дебага
//\Kama\WP\Kama_Cron::deactivate('my_cron_jobs'); // для удаления

// Функция крона
function wpkama_cron_func(){
	file_put_contents( dirname(ABSPATH) .'/cron_check.txt', current_time('mysql') ."\n", FILE_APPEND );
}

// Функция крона
function wpkama_cron_func_2(){
	// операции
}

// Функция крона
function wpkama_cron_func_3(){
	// операции
}

Пример 3: Регистрация задач при активации плагина

Код ниже показывает, как активировать и деактивировать задачи при активации/деактивации плагина.

// Пример активации и деактивации, если не указан параметр auto_activate
register_activation_hook( __FILE__, function(){
	\Kama\WP\Kama_Cron::activate( 'my_cron_jobs_2' );
} );

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

new \Kama\WP\Kama_Cron([
	'id'     => 'my_cron_jobs_2',
	'auto_activate' => false, // false чтобы повесить активацию задач на register_activation_hook()
	'events' => array(
		// первая задача
		'wpkama_cron_func_4' => array(
			'callback'      => 'wpkama_cron_func_4', // название функции крон-задачи
			'interval_name' => 'twicedaily', // можно указать уже имеющийся интервал: hourly, twicedaily, daily
		),
		// вторая задача
		'wpkama_cron_func_5' => array(
			'callback'      => 'wpkama_cron_func_5',
			'interval_name' => 'two_hours',
			'interval_sec'  => HOUR_IN_SECONDS * 2,
			'interval_desc' => 'Каждые 2 часа',
		),
	),
]);

function wpkama_cron_func_4(){
	// операции
}

function wpkama_cron_func_5(){
	// операции
}

Параметры конструктора

$args(массив)

Args.

  • id(строка)
    A unique identifier that can then be used to access the settings externally.
    По умолчанию: keys of the $events parameter

  • auto_activate(true|false)
    true - automatically creates the specified event when visiting the admin panel. In this case, you do not need to call {@see self::activate} method separately.

  • 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:

    • callback(callable)
      The name of the cron task function.

    • args(разное)
      What parameters should be passed to the cron task function.

    • 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)s — 10 minutes, 2 hours, 5 days, 2 months, then the number will be taken to 'interval_sec' parameter. You can specify an existing WP interval: hourly, twicedaily, daily. Omite this parameter to register single cron job.

    • interval_sec(int)
      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)s, hourly, twicedaily, daily.

    • interval_desc(строка)
      Description of the interval, for example, 'Every half hour'. You don't need to specify this param when $interval_name one of: N (min|hour|day|month)s, hourly, twicedaily, daily.

    • start_time(int)
      UNIX timestamp. When to start the event.
      По умолчанию: time()
11 комментариев
    Войти