PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 3.11.0
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v3.11.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 / vendor / woocommerce / action-scheduler / classes / abstracts / ActionScheduler_Store.php
wp-mail-smtp / vendor / woocommerce / action-scheduler / classes / abstracts Last commit date
ActionScheduler.php 2 years ago ActionScheduler_Abstract_ListTable.php 2 years ago ActionScheduler_Abstract_QueueRunner.php 2 years ago ActionScheduler_Abstract_RecurringSchedule.php 2 years ago ActionScheduler_Abstract_Schedule.php 2 years ago ActionScheduler_Abstract_Schema.php 2 years ago ActionScheduler_Lock.php 2 years ago ActionScheduler_Logger.php 2 years ago ActionScheduler_Store.php 2 years ago ActionScheduler_TimezoneHelper.php 2 years ago
ActionScheduler_Store.php
451 lines
1 <?php
2
3 /**
4 * Class ActionScheduler_Store
5 * @codeCoverageIgnore
6 */
7 abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
8 const STATUS_COMPLETE = 'complete';
9 const STATUS_PENDING = 'pending';
10 const STATUS_RUNNING = 'in-progress';
11 const STATUS_FAILED = 'failed';
12 const STATUS_CANCELED = 'canceled';
13 const DEFAULT_CLASS = 'ActionScheduler_wpPostStore';
14
15 /** @var ActionScheduler_Store */
16 private static $store = NULL;
17
18 /** @var int */
19 protected static $max_args_length = 191;
20
21 /**
22 * @param ActionScheduler_Action $action
23 * @param DateTime $scheduled_date Optional Date of the first instance
24 * to store. Otherwise uses the first date of the action's
25 * schedule.
26 *
27 * @return int The action ID
28 */
29 abstract public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = NULL );
30
31 /**
32 * @param string $action_id
33 *
34 * @return ActionScheduler_Action
35 */
36 abstract public function fetch_action( $action_id );
37
38 /**
39 * Find an action.
40 *
41 * Note: the query ordering changes based on the passed 'status' value.
42 *
43 * @param string $hook Action hook.
44 * @param array $params Parameters of the action to find.
45 *
46 * @return string|null ID of the next action matching the criteria or NULL if not found.
47 */
48 public function find_action( $hook, $params = array() ) {
49 $params = wp_parse_args(
50 $params,
51 array(
52 'args' => null,
53 'status' => self::STATUS_PENDING,
54 'group' => '',
55 )
56 );
57
58 // These params are fixed for this method.
59 $params['hook'] = $hook;
60 $params['orderby'] = 'date';
61 $params['per_page'] = 1;
62
63 if ( ! empty( $params['status'] ) ) {
64 if ( self::STATUS_PENDING === $params['status'] ) {
65 $params['order'] = 'ASC'; // Find the next action that matches.
66 } else {
67 $params['order'] = 'DESC'; // Find the most recent action that matches.
68 }
69 }
70
71 $results = $this->query_actions( $params );
72
73 return empty( $results ) ? null : $results[0];
74 }
75
76 /**
77 * Query for action count or list of action IDs.
78 *
79 * @since 3.3.0 $query['status'] accepts array of statuses instead of a single status.
80 *
81 * @param array $query {
82 * Query filtering options.
83 *
84 * @type string $hook The name of the actions. Optional.
85 * @type string|array $status The status or statuses of the actions. Optional.
86 * @type array $args The args array of the actions. Optional.
87 * @type DateTime $date The scheduled date of the action. Used in UTC timezone. Optional.
88 * @type string $date_compare Operator for selecting by $date param. Accepted values are '!=', '>', '>=', '<', '<=', '='. Defaults to '<='.
89 * @type DateTime $modified The last modified date of the action. Used in UTC timezone. Optional.
90 * @type string $modified_compare Operator for comparing $modified param. Accepted values are '!=', '>', '>=', '<', '<=', '='. Defaults to '<='.
91 * @type string $group The group the action belongs to. Optional.
92 * @type bool|int $claimed TRUE to find claimed actions, FALSE to find unclaimed actions, an int to find a specific claim ID. Optional.
93 * @type int $per_page Number of results to return. Defaults to 5.
94 * @type int $offset The query pagination offset. Defaults to 0.
95 * @type int $orderby Accepted values are 'hook', 'group', 'modified', 'date' or 'none'. Defaults to 'date'.
96 * @type string $order Accepted values are 'ASC' or 'DESC'. Defaults to 'ASC'.
97 * }
98 * @param string $query_type Whether to select or count the results. Default, select.
99 *
100 * @return string|array|null The IDs of actions matching the query. Null on failure.
101 */
102 abstract public function query_actions( $query = array(), $query_type = 'select' );
103
104 /**
105 * Run query to get a single action ID.
106 *
107 * @since 3.3.0
108 *
109 * @see ActionScheduler_Store::query_actions for $query arg usage but 'per_page' and 'offset' can't be used.
110 *
111 * @param array $query Query parameters.
112 *
113 * @return int|null
114 */
115 public function query_action( $query ) {
116 $query['per_page'] = 1;
117 $query['offset'] = 0;
118 $results = $this->query_actions( $query );
119
120 if ( empty( $results ) ) {
121 return null;
122 } else {
123 return (int) $results[0];
124 }
125 }
126
127 /**
128 * Get a count of all actions in the store, grouped by status
129 *
130 * @return array
131 */
132 abstract public function action_counts();
133
134 /**
135 * Get additional action counts.
136 *
137 * - add past-due actions
138 *
139 * @return array
140 */
141 public function extra_action_counts() {
142 $extra_actions = array();
143
144 $pastdue_action_counts = ( int ) $this->query_actions( array(
145 'status' => self::STATUS_PENDING,
146 'date' => as_get_datetime_object(),
147 ), 'count' );
148
149 if ( $pastdue_action_counts ) {
150 $extra_actions['past-due'] = $pastdue_action_counts;
151 }
152
153 /**
154 * Allows 3rd party code to add extra action counts (used in filters in the list table).
155 *
156 * @since 3.5.0
157 * @param $extra_actions array Array with format action_count_identifier => action count.
158 */
159 return apply_filters( 'action_scheduler_extra_action_counts', $extra_actions );
160 }
161
162 /**
163 * @param string $action_id
164 */
165 abstract public function cancel_action( $action_id );
166
167 /**
168 * @param string $action_id
169 */
170 abstract public function delete_action( $action_id );
171
172 /**
173 * @param string $action_id
174 *
175 * @return DateTime The date the action is schedule to run, or the date that it ran.
176 */
177 abstract public function get_date( $action_id );
178
179
180 /**
181 * @param int $max_actions
182 * @param DateTime $before_date Claim only actions schedule before the given date. Defaults to now.
183 * @param array $hooks Claim only actions with a hook or hooks.
184 * @param string $group Claim only actions in the given group.
185 *
186 * @return ActionScheduler_ActionClaim
187 */
188 abstract public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' );
189
190 /**
191 * @return int
192 */
193 abstract public function get_claim_count();
194
195 /**
196 * @param ActionScheduler_ActionClaim $claim
197 */
198 abstract public function release_claim( ActionScheduler_ActionClaim $claim );
199
200 /**
201 * @param string $action_id
202 */
203 abstract public function unclaim_action( $action_id );
204
205 /**
206 * @param string $action_id
207 */
208 abstract public function mark_failure( $action_id );
209
210 /**
211 * @param string $action_id
212 */
213 abstract public function log_execution( $action_id );
214
215 /**
216 * @param string $action_id
217 */
218 abstract public function mark_complete( $action_id );
219
220 /**
221 * @param string $action_id
222 *
223 * @return string
224 */
225 abstract public function get_status( $action_id );
226
227 /**
228 * @param string $action_id
229 * @return mixed
230 */
231 abstract public function get_claim_id( $action_id );
232
233 /**
234 * @param string $claim_id
235 * @return array
236 */
237 abstract public function find_actions_by_claim_id( $claim_id );
238
239 /**
240 * @param string $comparison_operator
241 * @return string
242 */
243 protected function validate_sql_comparator( $comparison_operator ) {
244 if ( in_array( $comparison_operator, array('!=', '>', '>=', '<', '<=', '=') ) ) {
245 return $comparison_operator;
246 }
247 return '=';
248 }
249
250 /**
251 * Get the time MySQL formated date/time string for an action's (next) scheduled date.
252 *
253 * @param ActionScheduler_Action $action
254 * @param DateTime $scheduled_date (optional)
255 * @return string
256 */
257 protected function get_scheduled_date_string( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
258 $next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
259 if ( ! $next ) {
260 $next = date_create();
261 }
262 $next->setTimezone( new DateTimeZone( 'UTC' ) );
263
264 return $next->format( 'Y-m-d H:i:s' );
265 }
266
267 /**
268 * Get the time MySQL formated date/time string for an action's (next) scheduled date.
269 *
270 * @param ActionScheduler_Action $action
271 * @param DateTime $scheduled_date (optional)
272 * @return string
273 */
274 protected function get_scheduled_date_string_local( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
275 $next = null === $scheduled_date ? $action->get_schedule()->get_date() : $scheduled_date;
276 if ( ! $next ) {
277 $next = date_create();
278 }
279
280 ActionScheduler_TimezoneHelper::set_local_timezone( $next );
281 return $next->format( 'Y-m-d H:i:s' );
282 }
283
284 /**
285 * Validate that we could decode action arguments.
286 *
287 * @param mixed $args The decoded arguments.
288 * @param int $action_id The action ID.
289 *
290 * @throws ActionScheduler_InvalidActionException When the decoded arguments are invalid.
291 */
292 protected function validate_args( $args, $action_id ) {
293 // Ensure we have an array of args.
294 if ( ! is_array( $args ) ) {
295 throw ActionScheduler_InvalidActionException::from_decoding_args( $action_id );
296 }
297
298 // Validate JSON decoding if possible.
299 if ( function_exists( 'json_last_error' ) && JSON_ERROR_NONE !== json_last_error() ) {
300 throw ActionScheduler_InvalidActionException::from_decoding_args( $action_id, $args );
301 }
302 }
303
304 /**
305 * Validate a ActionScheduler_Schedule object.
306 *
307 * @param mixed $schedule The unserialized ActionScheduler_Schedule object.
308 * @param int $action_id The action ID.
309 *
310 * @throws ActionScheduler_InvalidActionException When the schedule is invalid.
311 */
312 protected function validate_schedule( $schedule, $action_id ) {
313 if ( empty( $schedule ) || ! is_a( $schedule, 'ActionScheduler_Schedule' ) ) {
314 throw ActionScheduler_InvalidActionException::from_schedule( $action_id, $schedule );
315 }
316 }
317
318 /**
319 * InnoDB indexes have a maximum size of 767 bytes by default, which is only 191 characters with utf8mb4.
320 *
321 * Previously, AS wasn't concerned about args length, as we used the (unindex) post_content column. However,
322 * with custom tables, we use an indexed VARCHAR column instead.
323 *
324 * @param ActionScheduler_Action $action Action to be validated.
325 * @throws InvalidArgumentException When json encoded args is too long.
326 */
327 protected function validate_action( ActionScheduler_Action $action ) {
328 if ( strlen( json_encode( $action->get_args() ) ) > static::$max_args_length ) {
329 throw new InvalidArgumentException( sprintf( __( 'ActionScheduler_Action::$args too long. To ensure the args column can be indexed, action args should not be more than %d characters when encoded as JSON.', 'action-scheduler' ), static::$max_args_length ) );
330 }
331 }
332
333 /**
334 * Cancel pending actions by hook.
335 *
336 * @since 3.0.0
337 *
338 * @param string $hook Hook name.
339 *
340 * @return void
341 */
342 public function cancel_actions_by_hook( $hook ) {
343 $action_ids = true;
344 while ( ! empty( $action_ids ) ) {
345 $action_ids = $this->query_actions(
346 array(
347 'hook' => $hook,
348 'status' => self::STATUS_PENDING,
349 'per_page' => 1000,
350 'orderby' => 'action_id',
351 )
352 );
353
354 $this->bulk_cancel_actions( $action_ids );
355 }
356 }
357
358 /**
359 * Cancel pending actions by group.
360 *
361 * @since 3.0.0
362 *
363 * @param string $group Group slug.
364 *
365 * @return void
366 */
367 public function cancel_actions_by_group( $group ) {
368 $action_ids = true;
369 while ( ! empty( $action_ids ) ) {
370 $action_ids = $this->query_actions(
371 array(
372 'group' => $group,
373 'status' => self::STATUS_PENDING,
374 'per_page' => 1000,
375 'orderby' => 'action_id',
376 )
377 );
378
379 $this->bulk_cancel_actions( $action_ids );
380 }
381 }
382
383 /**
384 * Cancel a set of action IDs.
385 *
386 * @since 3.0.0
387 *
388 * @param array $action_ids List of action IDs.
389 *
390 * @return void
391 */
392 private function bulk_cancel_actions( $action_ids ) {
393 foreach ( $action_ids as $action_id ) {
394 $this->cancel_action( $action_id );
395 }
396
397 do_action( 'action_scheduler_bulk_cancel_actions', $action_ids );
398 }
399
400 /**
401 * @return array
402 */
403 public function get_status_labels() {
404 return array(
405 self::STATUS_COMPLETE => __( 'Complete', 'action-scheduler' ),
406 self::STATUS_PENDING => __( 'Pending', 'action-scheduler' ),
407 self::STATUS_RUNNING => __( 'In-progress', 'action-scheduler' ),
408 self::STATUS_FAILED => __( 'Failed', 'action-scheduler' ),
409 self::STATUS_CANCELED => __( 'Canceled', 'action-scheduler' ),
410 );
411 }
412
413 /**
414 * Check if there are any pending scheduled actions due to run.
415 *
416 * @param ActionScheduler_Action $action
417 * @param DateTime $scheduled_date (optional)
418 * @return string
419 */
420 public function has_pending_actions_due() {
421 $pending_actions = $this->query_actions( array(
422 'date' => as_get_datetime_object(),
423 'status' => ActionScheduler_Store::STATUS_PENDING,
424 'orderby' => 'none',
425 ) );
426
427 return ! empty( $pending_actions );
428 }
429
430 /**
431 * Callable initialization function optionally overridden in derived classes.
432 */
433 public function init() {}
434
435 /**
436 * Callable function to mark an action as migrated optionally overridden in derived classes.
437 */
438 public function mark_migrated( $action_id ) {}
439
440 /**
441 * @return ActionScheduler_Store
442 */
443 public static function instance() {
444 if ( empty( self::$store ) ) {
445 $class = apply_filters( 'action_scheduler_store_class', self::DEFAULT_CLASS );
446 self::$store = new $class();
447 }
448 return self::$store;
449 }
450 }
451