PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 4.9.0
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v4.9.0
4.9.0 0.9.6 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.2 1.7.0 1.7.1 1.8.0 1.8.1 1.9.0 2.0.0 2.0.1 2.1.1 2.2.1 2.3.1 2.4.0 2.5.0 2.5.1 2.6.0 2.7.0 2.8.0 2.9.0 3.0.1 3.0.2 3.0.3 3.1.0 3.10.0 3.11.0 3.11.1 3.2.0 3.2.1 3.3.0 3.4.0 3.5.0 3.5.1 3.5.2 3.6.1 3.7.0 3.8.0 3.8.2 3.9.0 4.0.1 4.1.0 4.1.1 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.8.0 trunk 0.10.0 0.10.1 0.11.1 0.11.2 0.3.1 0.3.2 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.5.2 0.6 0.7 0.8 0.8.2 0.8.3 0.8.4 0.8.5 0.8.6 0.8.7 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5
wp-mail-smtp / src / Tasks / Task.php
wp-mail-smtp / src / Tasks Last commit date
Queue 6 days ago Reports 6 days ago DebugEventsCleanupTask.php 6 days ago Meta.php 6 days ago NotificationsUpdateTask.php 6 days ago Task.php 6 days ago Tasks.php 6 days ago
Task.php
450 lines
1 <?php
2
3 namespace WPMailSMTP\Tasks;
4
5 use ActionScheduler;
6
7 /**
8 * Class Task.
9 *
10 * @since 2.1.0
11 */
12 class Task {
13
14 /**
15 * This task is async (runs asap).
16 *
17 * @since 2.1.0
18 */
19 const TYPE_ASYNC = 'async';
20
21 /**
22 * This task is a recurring.
23 *
24 * @since 2.1.0
25 */
26 const TYPE_RECURRING = 'scheduled';
27
28 /**
29 * This task is run once.
30 *
31 * @since 2.1.0
32 */
33 const TYPE_ONCE = 'once';
34
35 /**
36 * Type of the task.
37 *
38 * @since 2.1.0
39 *
40 * @var string
41 */
42 private $type;
43
44 /**
45 * Action that will be used as a hook.
46 *
47 * @since 2.1.0
48 *
49 * @var string
50 */
51 private $action;
52
53 /**
54 * Task meta ID.
55 *
56 * @since 2.1.0
57 *
58 * @var int
59 */
60 private $meta_id;
61
62 /**
63 * All the params that should be passed to the hook.
64 *
65 * @since 2.1.0
66 *
67 * @var array
68 */
69 private $params;
70
71 /**
72 * When the first instance of the job will run.
73 * Used for ONCE ane RECURRING tasks.
74 *
75 * @since 2.1.0
76 *
77 * @var int
78 */
79 private $timestamp;
80
81 /**
82 * How long to wait between runs.
83 * Used for RECURRING tasks.
84 *
85 * @since 2.1.0
86 *
87 * @var int
88 */
89 private $interval;
90
91 /**
92 * Whether this task is unique.
93 *
94 * @since 4.0.0
95 *
96 * @var bool
97 */
98 private $unique = false;
99
100 /**
101 * Task constructor.
102 *
103 * @since 2.1.0
104 *
105 * @param string $action Action of the task.
106 *
107 * @throws \InvalidArgumentException When action is not a string.
108 * @throws \UnexpectedValueException When action is empty.
109 */
110 public function __construct( $action ) {
111
112 if ( ! is_string( $action ) ) {
113 throw new \InvalidArgumentException( 'Task action should be a string.' );
114 }
115
116 $this->action = sanitize_key( $action );
117
118 if ( empty( $this->action ) ) {
119 throw new \UnexpectedValueException( 'Task action cannot be empty.' );
120 }
121 }
122
123 /**
124 * Define the type of the task as async.
125 *
126 * @since 2.1.0
127 *
128 * @return Task
129 */
130 public function async() {
131
132 $this->type = self::TYPE_ASYNC;
133
134 return $this;
135 }
136
137 /**
138 * Define the type of the task as recurring.
139 *
140 * @since 2.1.0
141 *
142 * @param int $timestamp When the first instance of the job will run.
143 * @param int $interval How long to wait between runs.
144 *
145 * @return Task
146 */
147 public function recurring( $timestamp, $interval ) {
148
149 $this->type = self::TYPE_RECURRING;
150 $this->timestamp = (int) $timestamp;
151 $this->interval = (int) $interval;
152
153 return $this;
154 }
155
156 /**
157 * Define the type of the task as one-time.
158 *
159 * @since 2.1.0
160 *
161 * @param int $timestamp When the first instance of the job will run.
162 *
163 * @return Task
164 */
165 public function once( $timestamp ) {
166
167 $this->type = self::TYPE_ONCE;
168 $this->timestamp = (int) $timestamp;
169
170 return $this;
171 }
172
173 /**
174 * Set this task as unique.
175 *
176 * @since 4.0.0
177 *
178 * @return Task
179 */
180 public function unique() {
181
182 $this->unique = true;
183
184 return $this;
185 }
186
187 /**
188 * Pass any number of params that should be saved to Meta table.
189 *
190 * @since 2.1.0
191 *
192 * @return Task
193 */
194 public function params() {
195
196 $args = func_get_args();
197
198 if ( ! empty( $args ) ) {
199 $this->params = $args;
200 }
201
202 return $this;
203 }
204
205 /**
206 * Register the action.
207 * Should be the final call in a chain.
208 *
209 * @since 2.1.0
210 *
211 * @return null|string Action ID.
212 */
213 public function register() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
214
215 $action_id = null;
216
217 // No processing if ActionScheduler is not usable.
218 if ( ! Tasks::is_usable() ) {
219 return $action_id;
220 }
221
222 // Save data to tasks meta table.
223 if ( ! is_null( $this->params ) ) {
224 $task_meta = new Meta();
225
226 // No processing if meta table was not created.
227 if ( ! $task_meta->table_exists() ) {
228 return $action_id;
229 }
230
231 $this->meta_id = $task_meta->add(
232 [
233 'action' => $this->action,
234 'data' => isset( $this->params ) ? $this->params : [],
235 ]
236 );
237
238 if ( empty( $this->meta_id ) ) {
239 return $action_id;
240 }
241 }
242
243 // Prevent 500 errors when Action Scheduler tables don't exist.
244 try {
245 switch ( $this->type ) {
246 case self::TYPE_ASYNC:
247 $action_id = $this->register_async();
248 break;
249
250 case self::TYPE_RECURRING:
251 $action_id = $this->register_recurring();
252 break;
253
254 case self::TYPE_ONCE:
255 $action_id = $this->register_once();
256 break;
257 }
258 } catch ( \RuntimeException $exception ) {
259 $action_id = null;
260 }
261
262 return $action_id;
263 }
264
265 /**
266 * Register the async task.
267 *
268 * @since 2.1.0
269 *
270 * @return null|string Action ID.
271 */
272 protected function register_async() {
273
274 if ( ! function_exists( 'as_enqueue_async_action' ) ) {
275 return null;
276 }
277
278 return as_enqueue_async_action(
279 $this->action,
280 [ $this->meta_id ],
281 Tasks::GROUP,
282 $this->unique
283 );
284 }
285
286 /**
287 * Register the recurring task.
288 *
289 * @since 2.1.0
290 *
291 * @return null|string Action ID.
292 */
293 protected function register_recurring() {
294
295 if ( ! function_exists( 'as_schedule_recurring_action' ) ) {
296 return null;
297 }
298
299 return as_schedule_recurring_action(
300 $this->timestamp,
301 $this->interval,
302 $this->action,
303 [ $this->meta_id ],
304 Tasks::GROUP,
305 $this->unique
306 );
307 }
308
309 /**
310 * Register the one-time task.
311 *
312 * @since 2.1.0
313 *
314 * @return null|string Action ID.
315 */
316 protected function register_once() {
317
318 if ( ! function_exists( 'as_schedule_single_action' ) ) {
319 return null;
320 }
321
322 return as_schedule_single_action(
323 $this->timestamp,
324 $this->action,
325 [ $this->meta_id ],
326 Tasks::GROUP,
327 $this->unique
328 );
329 }
330
331 /**
332 * Cancel all occurrences of this task.
333 *
334 * @since 2.1.0
335 *
336 * @return null|bool|string Null if no matching action found,
337 * false if AS library is missing,
338 * string of the scheduled action ID if a scheduled action was found and unscheduled.
339 */
340 public function cancel() {
341
342 // Exit if AS function does not exist.
343 if ( ! function_exists( 'as_unschedule_all_actions' ) || ! Tasks::is_usable() ) {
344 return false;
345 }
346
347 as_unschedule_all_actions( $this->action );
348
349 return true;
350 }
351
352 /**
353 * Cancel all occurrences of this task,
354 * preventing it from re-registering itself.
355 *
356 * @since 4.0.0
357 */
358 public function cancel_force() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
359
360 add_action( 'shutdown', [ $this, 'cancel' ], PHP_INT_MAX );
361 }
362
363 /**
364 * Remove completed occurrences of this task.
365 *
366 * @since 4.1.0
367 *
368 * @param int $limit The amount of rows to remove.
369 */
370 protected function remove_completed( $limit = 0 ) {
371
372 // Make sure that all used functions, classes, and methods exist.
373 if (
374 ! function_exists( 'as_get_scheduled_actions' ) ||
375 ! class_exists( 'ActionScheduler' ) ||
376 ! method_exists( 'ActionScheduler', 'store' ) ||
377 ! class_exists( 'ActionScheduler_Store' ) ||
378 ! method_exists( 'ActionScheduler_Store', 'delete_action' )
379 ) {
380 return;
381 }
382
383 // Cap the query result to prevent performing a large number of individual delete actions at once.
384 $per_page = min( 10, max( 0, intval( $limit ) ) );
385
386 // Get completed occurrences of this task.
387 $action_ids = as_get_scheduled_actions(
388 [
389 'hook' => $this->action,
390 'status' => 'complete',
391 'per_page' => $per_page,
392 ],
393 'ids'
394 );
395
396 if ( empty( $action_ids ) ) {
397 return;
398 }
399
400 // Delete actions through the Action Scheduler API so that associated
401 // `actionscheduler_logs` rows are cleaned up via the
402 // `action_scheduler_deleted_action` hook.
403 foreach ( $action_ids as $action_id ) {
404 ActionScheduler::store()->delete_action( $action_id );
405 }
406 }
407
408 /**
409 * Remove pending occurrences of this task.
410 *
411 * @since 4.3.0
412 *
413 * @param int $limit The amount of rows to remove.
414 */
415 protected function remove_pending( $limit = 0 ) {
416
417 // Make sure that all used functions, classes, and methods exist.
418 if (
419 ! function_exists( 'as_get_scheduled_actions' ) ||
420 ! class_exists( 'ActionScheduler' ) ||
421 ! method_exists( 'ActionScheduler', 'store' ) ||
422 ! class_exists( 'ActionScheduler_Store' ) ||
423 ! method_exists( 'ActionScheduler_Store', 'delete_action' )
424 ) {
425 return;
426 }
427
428 $per_page = max( 0, intval( $limit ) );
429
430 // Get all pending license check actions.
431 $action_ids = as_get_scheduled_actions(
432 [
433 'hook' => $this->action,
434 'status' => 'pending',
435 'per_page' => $per_page,
436 ],
437 'ids'
438 );
439
440 if ( empty( $action_ids ) ) {
441 return;
442 }
443
444 // Delete all pending license check actions.
445 foreach ( $action_ids as $action_id ) {
446 ActionScheduler::store()->delete_action( $action_id );
447 }
448 }
449 }
450