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