Kama_Cron

Невеликий клас для зручного додавання крон подій (завдань) WordPress.

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

Код класу Kama_Cron

GitHub

<?php

namespace KamaWP;

/**
 * Convenient way to add cron tasks in WordPress.
 *
 * Usage Example:
 *
 * ````
 * new KamaWPKama_Cron([
 * 'wpkama_cron_func' => [
 * 'callback' => 'wpkama_cron_func', // PHP function to run on job
 * 'interval_name' => '10 min', // ви можете налагодити registered interval: hourly, twicedaily, daily
 * ],
 *]));
 *
 * new KamaWPKama_Cron([
 * 'single_job' => [
 * 'callback' => 'single_job_func',
 * 'start_time' => strtotime( '2021-06-05' ),
 * ],
 *]));
 *
 * new KamaWPKama_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', // Ви можете налагодити 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.
	 * Для debugging go to: http://site.com/wp-cron.php
	 */
	public const DEBUG = false;

	/**
	 * ID cron args. Internal - не використовується для cron.
	 *
	 * @var string
	 */
	protected $id;

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

	/**
	 * Constructor.
	 *
	 * @param array $args {
	 * Args.
	 *
	 * @type string $id Винятково identifier, що може бути використаний для підключення до settings externally.
	 * Default: keys the $events parameter.
	 * @type bool $auto_activate true - автоматично створюють конкретний пункт, коли використовується admin panel.
	 * У цьому випадку, ви не повинні call {@see self::activate} метод separately.
	 * @type array $events {
	 * На array of events to add to the crown. The element key will be used in the cron hook.
	 * The element value is array of event parameters that can contain the following keys:
	 *
	 * @type callable $callback Name of the cron task function.
	 * @type mixed $args What parameters повинні бути passed до функцію cron task.
	 * @type string $interval_name Назва часу, для прикладу: 'half_an_hover'.
	 * Ви можете визначити назву в наступному форматі:
	 * `N (min|hour|day|month)s` - 10 minutes, 2 hours, 5 days, 2 months,
	 * then the number will be taken to 'interval_sec' parameter.
	 * Ви можете сказати, що існує WP-час: години, двадцять днів, днів.
	 * Оміть цей параметр до registru single cron job.
	 * @type int $interval_sec Interval time, for example HOUR_IN_SECONDS /2.
	 * Ви не потрібні для особливості цього papameter при $interval_name один з:
	 * N (min|hour|day|month)s, hourly, twicedaily, daily.
	 * @type string $interval_desc Опис терміну, для прикладу, 'Every half hour'.
	 * Ви не хочете, щоб ця особливість є для того, щоб $interval_name один з:
	 * 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.
	 * може бути названий деякий час, для прикладу, коли 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 no 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.nnKama_Cron::$instance = " .
		     print_r( self::$instances, 1 ) . "nnnn_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: %snnnExisting Intervals:n%snnn%s",
				time(), print_r( wp_get_schedules(), 1 ), print_r( _get_cron_array(), 1 )
			);
		} );
	}

}

Встановлення

Скопіюйте код класу та вставте його у плагін або functions.php теми. Або використовуйте composer:

composer require doiftrue/wp-kama-cron

Якщо ви використовуєте як пакет composer, то при виклику класу потрібно додати простір імен

Приклади використання класу Kama_Cron

Викликати new KamaWPKama_Cron()можна на ранньому етапі завантаження WP, починаючи з ранньої події muplugins_loaded .

ВАЖЛИВО! Код виклику new KamaWPKama_Cron()повинен спрацьовувати (викликатися) при крон запитах, тому що на ньому реєструються необхідні WP хуки, які відпрацьовуватимуть при крон запитах. Іншими словами, не можна зареєструвати крон завдання за допомогою цього коду та видалити його.

Приклад 1: Просте використання без додаткових параметрів

У цьому прикладі зазначена задача Cron буде зареєстрована автоматично при відвідуванні адмін-панелі або за будь-якого Cron запиту.

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

Використовуємо невідомий для WP інтервал:

new KamaWPKama_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 KamaWPKama_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 KamaWPKama_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 інтервал
		),
	),
]);
//KamaWPKama_Cron::$DEBUG = 1; // для дебага
//KamaWPKama_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(){
	KamaWPKama_Cron::activate( 'my_cron_jobs_2' );
} );

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

new KamaWPKama_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, що може бути використаний для з’єднання externally.
    За замовчуванням: keys of the $events parameter

  • auto_activate (true|false)
    true – автоматично створюють конкретний пункт, коли використовується admin panel. У цьому випадку, ви не повинні call {@see self::activate} метод separately.

  • events (масив)
    An array of events to add to the crown. The element key will be used in the cron hook. Element value is array of event parameters that can contain the following keys:

    • callback (callable)
      Name of the cron task function.

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

    • interval_name (рядок)
      Назва часу, для прикладу: ‘half_an_hover’. Ви можете визначити назву в наступному форматі: N (min|hour|day|month)s – 10 minutes, 2 hours, 5 days, 2 months, then the number will be taken to ‘interval_sec’ parameter. Ви можете сказати, що існує WP-час: години, двадцять днів, днів. Оміть цей параметр до реєстру одного cron job.

    • interval_sec (int)
      Час часу, для прикладу HOUR_IN_SECONDS / 2. Ви не хочете, щоб цей papameter при $interval_name один з: N (min|hour|day|month)s, hourly, twicedaily, daily.

    • interval_desc (рядок)
      Опис терміну, для прикладу, ‘Every half hour’. Ви не хочете, щоб ця функція, коли $interval_name один з: N (min|hour|day|month)s, hourly, twicedaily, daily.

    • start_time (int)
      UNIX timestamp. When to start the event.
      Типово: time()

Залишити коментар

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *