tasks
3 weeks ago
bootstrap.php
3 weeks ago
class-abstract-task.php
3 weeks ago
class-task-manager.php
3 weeks ago
handler.php
3 weeks ago
class-abstract-task.php
144 lines
| 1 | <?php |
| 2 | |
| 3 | // Namespace |
| 4 | namespace BMI\Plugin\CRON; |
| 5 | |
| 6 | // Exit on direct access |
| 7 | if (!defined('ABSPATH')) exit; |
| 8 | |
| 9 | /** |
| 10 | * AbstractTask |
| 11 | * |
| 12 | * Base contract for all background tasks in this plugin. |
| 13 | * |
| 14 | * Each concrete subclass represents exactly one WP-Cron scheduled event. |
| 15 | * Subclasses declare *what* to do (hook name, interval, and run() logic); |
| 16 | * the infrastructure (scheduling, unscheduling, hook registration) is fully |
| 17 | * handled here so subclasses never call wp_schedule_event() directly. |
| 18 | * |
| 19 | * Minimal implementation: |
| 20 | * |
| 21 | * class MyTask extends AbstractTask { |
| 22 | * public function get_hook() { return 'bmi_my_task'; } |
| 23 | * public function get_interval() { return 'daily'; } |
| 24 | * public function run() { // do work } |
| 25 | * } |
| 26 | * |
| 27 | * TaskManager::register(new MyTask()); |
| 28 | */ |
| 29 | abstract class AbstractTask { |
| 30 | |
| 31 | // ── Abstract interface ───────────────────────────────────────────────────── |
| 32 | |
| 33 | /** |
| 34 | * Unique WP action hook name that fires this task. |
| 35 | * Must not collide with any other hook in the WordPress installation. |
| 36 | * |
| 37 | * @return string |
| 38 | */ |
| 39 | abstract public function get_hook(); |
| 40 | |
| 41 | /** |
| 42 | * Recurrence interval slug passed to wp_schedule_event(). |
| 43 | * |
| 44 | * Built-in slugs (no extra setup needed): |
| 45 | * 'hourly', 'twicedaily', 'daily' |
| 46 | * |
| 47 | * Note: 'weekly' was added in WP 5.4; use a custom slug for broader |
| 48 | * compatibility (see get_custom_interval_args()). |
| 49 | * |
| 50 | * Custom slugs must be accompanied by a non-null return from |
| 51 | * get_custom_interval_args() so TaskManager can register them. |
| 52 | * |
| 53 | * @return string |
| 54 | */ |
| 55 | abstract public function get_interval(); |
| 56 | |
| 57 | /** |
| 58 | * The work to perform each time the event fires. |
| 59 | * |
| 60 | * @return void |
| 61 | */ |
| 62 | abstract public function run(); |
| 63 | |
| 64 | // ── Optional overrides ───────────────────────────────────────────────────── |
| 65 | |
| 66 | /** |
| 67 | * Arguments required to register a custom cron interval. |
| 68 | * |
| 69 | * Return null when the interval slug returned by get_interval() is one |
| 70 | * of WordPress's built-in intervals. |
| 71 | * |
| 72 | * Return an array for a custom interval: |
| 73 | * array('interval' => <seconds (int)>, 'display' => '<Human-readable label>') |
| 74 | * |
| 75 | * @return array|null |
| 76 | */ |
| 77 | public function get_custom_interval_args() { |
| 78 | return null; |
| 79 | } |
| 80 | |
| 81 | /** |
| 82 | * UTC timestamp for the first occurrence of this event. |
| 83 | * |
| 84 | * Defaults to one minute from the current time, giving WordPress a chance |
| 85 | * to finish its current request before the first execution. |
| 86 | * |
| 87 | * @return int Unix timestamp |
| 88 | */ |
| 89 | public function get_schedule_start() { |
| 90 | return time() + MINUTE_IN_SECONDS; |
| 91 | } |
| 92 | |
| 93 | // ── Final infrastructure methods ─────────────────────────────────────────── |
| 94 | |
| 95 | /** |
| 96 | * Bind this task's run() method to its WP action hook. |
| 97 | * Called once per request by TaskManager::boot(). |
| 98 | * |
| 99 | * @return void |
| 100 | */ |
| 101 | final public function register() { |
| 102 | add_action($this->get_hook(), array($this, 'run')); |
| 103 | } |
| 104 | |
| 105 | /** |
| 106 | * Schedule the recurring event unless it is already queued. |
| 107 | * Silently no-ops when the event is already scheduled. |
| 108 | * |
| 109 | * @return void |
| 110 | */ |
| 111 | final public function schedule() { |
| 112 | if (!$this->is_scheduled()) { |
| 113 | wp_schedule_event( |
| 114 | $this->get_schedule_start(), |
| 115 | $this->get_interval(), |
| 116 | $this->get_hook() |
| 117 | ); |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | /** |
| 122 | * Remove every pending occurrence of this event from the cron queue. |
| 123 | * |
| 124 | * @return void |
| 125 | */ |
| 126 | final public function unschedule() { |
| 127 | $timestamp = wp_next_scheduled($this->get_hook()); |
| 128 | if ($timestamp !== false) { |
| 129 | wp_unschedule_event($timestamp, $this->get_hook()); |
| 130 | } |
| 131 | wp_clear_scheduled_hook($this->get_hook()); |
| 132 | } |
| 133 | |
| 134 | /** |
| 135 | * Return true when at least one occurrence of this event is queued. |
| 136 | * |
| 137 | * @return bool |
| 138 | */ |
| 139 | final public function is_scheduled() { |
| 140 | return (bool) wp_next_scheduled($this->get_hook()); |
| 141 | } |
| 142 | |
| 143 | } |
| 144 |