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 / Tasks.php
wp-mail-smtp / src / Tasks Last commit date
Queue 5 days ago Reports 5 days ago DebugEventsCleanupTask.php 5 days ago Meta.php 5 days ago NotificationsUpdateTask.php 5 days ago Task.php 5 days ago Tasks.php 5 days ago
Tasks.php
322 lines
1 <?php
2
3 namespace WPMailSMTP\Tasks;
4
5 use ActionScheduler_Action;
6 use ActionScheduler_DataController;
7 use ActionScheduler_DBStore;
8 use WPMailSMTP\Tasks\Queue\CleanupQueueTask;
9 use WPMailSMTP\Tasks\Queue\ProcessQueueTask;
10 use WPMailSMTP\Tasks\Queue\SendEnqueuedEmailTask;
11 use WPMailSMTP\Tasks\Reports\SummaryEmailTask;
12
13 /**
14 * Class Tasks manages the tasks queue and provides API to work with it.
15 *
16 * @since 2.1.0
17 */
18 class Tasks {
19
20 /**
21 * Group that will be assigned to all actions.
22 *
23 * @since 2.1.0
24 */
25 const GROUP = 'wp_mail_smtp';
26
27 /**
28 * WP Mail SMTP pending or in-progress actions.
29 *
30 * @since 3.3.0
31 *
32 * @var array
33 */
34 private static $active_actions = null;
35
36 /**
37 * Perform certain things on class init.
38 *
39 * @since 2.1.0
40 */
41 public function init() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
42
43 // Hide the Action Scheduler admin menu item.
44 add_action( 'admin_menu', [ $this, 'admin_hide_as_menu' ], PHP_INT_MAX );
45
46 // Skip tasks registration if Action Scheduler is not usable yet.
47 if ( ! self::is_usable() ) {
48 return;
49 }
50
51 // Register tasks.
52 foreach ( $this->get_tasks() as $task ) {
53 if ( ! is_subclass_of( $task, '\WPMailSMTP\Tasks\Task' ) ) {
54 continue;
55 }
56
57 $new_task = new $task();
58
59 // Run the init method, if a task has one defined.
60 if ( method_exists( $new_task, 'init' ) ) {
61 $new_task->init();
62 }
63 }
64
65 // Remove scheduled action meta after action execution.
66 add_action( 'action_scheduler_after_execute', [ $this, 'clear_action_meta' ], PHP_INT_MAX, 2 );
67
68 // Cancel tasks on plugin deactivation.
69 register_deactivation_hook( WPMS_PLUGIN_FILE, [ $this, 'cancel_all' ] );
70 }
71
72 /**
73 * Get the list of default scheduled tasks.
74 * Tasks, that are fired under certain specific circumstances
75 * (like sending emails) are not listed here.
76 *
77 * @since 2.1.0
78 *
79 * @return Task[] List of tasks classes.
80 */
81 public function get_tasks() {
82
83 $tasks = [
84 SummaryEmailTask::class,
85 DebugEventsCleanupTask::class,
86 ProcessQueueTask::class,
87 CleanupQueueTask::class,
88 SendEnqueuedEmailTask::class,
89 NotificationsUpdateTask::class,
90 ];
91
92 /**
93 * Filters list of tasks classes.
94 *
95 * @since 2.1.2
96 *
97 * @param Task[] $tasks List of tasks classes.
98 */
99 return apply_filters( 'wp_mail_smtp_tasks_get_tasks', $tasks );
100 }
101
102 /**
103 * Hide Action Scheduler admin area when not in debug mode.
104 *
105 * @since 2.1.0
106 */
107 public function admin_hide_as_menu() {
108
109 $plugin_exceptions = [
110 'woocommerce/woocommerce.php',
111 'action-scheduler/action-scheduler.php',
112 ];
113
114 /**
115 * Filters the list of plugins for which
116 * the Action Scheduler Tools ->Scheduled Actions menu item
117 * should remain visible.
118 *
119 * @since 4.3.0
120 *
121 * @param array $plugin_exceptions List of plugins exceptions.
122 */
123 $plugin_exceptions = apply_filters( 'wp_mail_smtp_tasks_tasks_action_scheduler_tools_plugin_exceptions', $plugin_exceptions );
124 $hide_as_menu = empty( array_filter( $plugin_exceptions, 'is_plugin_active' ) );
125
126 // Filter to redefine that WP Mail SMTP hides Tools > Action Scheduler menu item.
127 if ( apply_filters( 'wp_mail_smtp_tasks_admin_hide_as_menu', $hide_as_menu ) ) {
128 remove_submenu_page( 'tools.php', 'action-scheduler' );
129 }
130 }
131
132 /**
133 * Create a new task.
134 * Used for "inline" tasks, that require additional information
135 * from the plugin runtime before they can be scheduled.
136 *
137 * Example:
138 * wp_mail_smtp()->get( 'tasks' )
139 * ->create( 'i_am_the_dude' )
140 * ->async()
141 * ->params( 'The Big Lebowski', 1998 )
142 * ->register();
143 *
144 * This `i_am_the_dude` action will be later processed as:
145 * add_action( 'i_am_the_dude', 'thats_what_you_call_me' );
146 *
147 * @since 2.1.0
148 *
149 * @param string $action Action that will be used as a hook.
150 *
151 * @return Task
152 */
153 public function create( $action ) {
154
155 return new Task( $action );
156 }
157
158 /**
159 * Cancel all the AS actions for a group.
160 *
161 * @since 2.1.0
162 *
163 * @param string $group Group to cancel all actions for.
164 */
165 public function cancel_all( $group = '' ) {
166
167 if ( empty( $group ) ) {
168 $group = self::GROUP;
169 } else {
170 $group = sanitize_key( $group );
171 }
172
173 if ( class_exists( 'ActionScheduler_DBStore' ) ) {
174 ActionScheduler_DBStore::instance()->cancel_actions_by_group( $group );
175 }
176 }
177
178 /**
179 * Remove all the AS actions for a group and remove group.
180 *
181 * @since 3.7.0
182 *
183 * @param string $group Group to remove all actions for.
184 */
185 public function remove_all( $group = '' ) {
186
187 global $wpdb;
188
189 if ( empty( $group ) ) {
190 $group = self::GROUP;
191 } else {
192 $group = sanitize_key( $group );
193 }
194
195 if (
196 class_exists( 'ActionScheduler_DBStore' ) &&
197 isset( $wpdb->actionscheduler_actions ) &&
198 isset( $wpdb->actionscheduler_groups )
199 ) {
200 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
201 $group_id = $wpdb->get_var(
202 $wpdb->prepare( "SELECT group_id FROM {$wpdb->actionscheduler_groups} WHERE slug=%s", $group )
203 );
204
205 if ( ! empty( $group_id ) ) {
206 // Delete actions.
207 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
208 $wpdb->delete( $wpdb->actionscheduler_actions, [ 'group_id' => (int) $group_id ], [ '%d' ] );
209
210 // Delete group.
211 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
212 $wpdb->delete( $wpdb->actionscheduler_groups, [ 'slug' => $group ], [ '%s' ] );
213 }
214 }
215 }
216
217 /**
218 * Clear the meta after action complete.
219 * Fired before an action is marked as completed.
220 *
221 * @since 3.5.0
222 *
223 * @param integer $action_id Action ID.
224 * @param ActionScheduler_Action $action Action name.
225 */
226 public function clear_action_meta( $action_id, $action ) {
227
228 $action_schedule = $action->get_schedule();
229
230 if (
231 $action_schedule === null ||
232 $action_schedule->is_recurring() ||
233 $action->get_group() !== self::GROUP
234 ) {
235 return;
236 }
237
238 $hook_args = $action->get_args();
239
240 if ( ! is_numeric( $hook_args[0] ) ) {
241 return;
242 }
243
244 $meta = new Meta();
245
246 $meta->delete( $hook_args[0] );
247 }
248
249 /**
250 * Whether ActionScheduler thinks that it has migrated or not.
251 *
252 * @since 2.1.0
253 *
254 * @return bool
255 */
256 public static function is_usable() {
257
258 // No tasks if ActionScheduler wasn't loaded.
259 if ( ! class_exists( 'ActionScheduler_DataController' ) ) {
260 return false;
261 }
262
263 return ActionScheduler_DataController::is_migration_complete();
264 }
265
266 /**
267 * Whether task has been scheduled and is pending.
268 *
269 * @since 2.1.0
270 *
271 * @param string $hook Hook to check for.
272 *
273 * @return bool|null
274 */
275 public static function is_scheduled( $hook ) {
276
277 // If ActionScheduler wasn't loaded, then no tasks are scheduled.
278 if ( ! function_exists( 'as_next_scheduled_action' ) ) {
279 return null;
280 }
281
282 if ( is_null( self::$active_actions ) ) {
283 self::$active_actions = self::get_active_actions();
284 }
285
286 if ( in_array( $hook, self::$active_actions, true ) ) {
287 return true;
288 }
289
290 // Action is not in the array, so it is not scheduled or belongs to another group.
291 if ( function_exists( 'as_has_scheduled_action' ) ) {
292 // This function more performant than `as_next_scheduled_action`, but it is available only since AS 3.3.0.
293 return as_has_scheduled_action( $hook );
294 } else {
295 return as_next_scheduled_action( $hook ) !== false;
296 }
297 }
298
299 /**
300 * Get all WP Mail SMTP pending or in-progress actions.
301 *
302 * @since 3.3.0
303 */
304 private static function get_active_actions() {
305
306 global $wpdb;
307
308 $group = self::GROUP;
309 $sql = "SELECT a.hook FROM {$wpdb->prefix}actionscheduler_actions a
310 JOIN {$wpdb->prefix}actionscheduler_groups g ON g.group_id = a.group_id
311 WHERE g.slug = '$group' AND a.status IN ('in-progress', 'pending')";
312
313 // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching
314 // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
315 $results = $wpdb->get_results( $sql, 'ARRAY_N' );
316 // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching
317 // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
318
319 return $results ? array_merge( ...$results ) : [];
320 }
321 }
322