Completed
Push — develop ( 36a199...920e68 )
by David
01:14
created
action-scheduler/classes/data-stores/ActionScheduler_wpPostStore.php 2 patches
Indentation   +1059 added lines, -1059 removed lines patch added patch discarded remove patch
@@ -4,1072 +4,1072 @@
 block discarded – undo
4 4
  * Class ActionScheduler_wpPostStore
5 5
  */
6 6
 class ActionScheduler_wpPostStore extends ActionScheduler_Store {
7
-	const POST_TYPE         = 'scheduled-action';
8
-	const GROUP_TAXONOMY    = 'action-group';
9
-	const SCHEDULE_META_KEY = '_action_manager_schedule';
10
-	const DEPENDENCIES_MET  = 'as-post-store-dependencies-met';
11
-
12
-	/**
13
-	 * Used to share information about the before_date property of claims internally.
14
-	 *
15
-	 * This is used in preference to passing the same information as a method param
16
-	 * for backwards-compatibility reasons.
17
-	 *
18
-	 * @var DateTime|null
19
-	 */
20
-	private $claim_before_date = null;
21
-
22
-	/**
23
-	 * Local Timezone.
24
-	 *
25
-	 * @var DateTimeZone
26
-	 */
27
-	protected $local_timezone = null;
28
-
29
-	/**
30
-	 * Save action.
31
-	 *
32
-	 * @param ActionScheduler_Action $action Scheduled Action.
33
-	 * @param DateTime               $scheduled_date Scheduled Date.
34
-	 *
35
-	 * @throws RuntimeException Throws an exception if the action could not be saved.
36
-	 * @return int
37
-	 */
38
-	public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = null ) {
39
-		try {
40
-			$this->validate_action( $action );
41
-			$post_array = $this->create_post_array( $action, $scheduled_date );
42
-			$post_id    = $this->save_post_array( $post_array );
43
-			$this->save_post_schedule( $post_id, $action->get_schedule() );
44
-			$this->save_action_group( $post_id, $action->get_group() );
45
-			do_action( 'action_scheduler_stored_action', $post_id );
46
-			return $post_id;
47
-		} catch ( Exception $e ) {
48
-			/* translators: %s: action error message */
49
-			throw new RuntimeException( sprintf( __( 'Error saving action: %s', 'action-scheduler' ), $e->getMessage() ), 0 );
50
-		}
51
-	}
52
-
53
-	/**
54
-	 * Create post array.
55
-	 *
56
-	 * @param ActionScheduler_Action $action Scheduled Action.
57
-	 * @param DateTime               $scheduled_date Scheduled Date.
58
-	 *
59
-	 * @return array Returns an array of post data.
60
-	 */
61
-	protected function create_post_array( ActionScheduler_Action $action, DateTime $scheduled_date = null ) {
62
-		$post = array(
63
-			'post_type'     => self::POST_TYPE,
64
-			'post_title'    => $action->get_hook(),
65
-			'post_content'  => wp_json_encode( $action->get_args() ),
66
-			'post_status'   => ( $action->is_finished() ? 'publish' : 'pending' ),
67
-			'post_date_gmt' => $this->get_scheduled_date_string( $action, $scheduled_date ),
68
-			'post_date'     => $this->get_scheduled_date_string_local( $action, $scheduled_date ),
69
-		);
70
-		return $post;
71
-	}
72
-
73
-	/**
74
-	 * Save post array.
75
-	 *
76
-	 * @param array $post_array Post array.
77
-	 * @return int Returns the post ID.
78
-	 * @throws RuntimeException Throws an exception if the action could not be saved.
79
-	 */
80
-	protected function save_post_array( $post_array ) {
81
-		add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 );
82
-		add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
83
-
84
-		$has_kses = false !== has_filter( 'content_save_pre', 'wp_filter_post_kses' );
85
-
86
-		if ( $has_kses ) {
87
-			// Prevent KSES from corrupting JSON in post_content.
88
-			kses_remove_filters();
89
-		}
90
-
91
-		$post_id = wp_insert_post( $post_array );
92
-
93
-		if ( $has_kses ) {
94
-			kses_init_filters();
95
-		}
96
-
97
-		remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
98
-		remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
99
-
100
-		if ( is_wp_error( $post_id ) || empty( $post_id ) ) {
101
-			throw new RuntimeException( __( 'Unable to save action.', 'action-scheduler' ) );
102
-		}
103
-		return $post_id;
104
-	}
105
-
106
-	/**
107
-	 * Filter insert post data.
108
-	 *
109
-	 * @param array $postdata Post data to filter.
110
-	 *
111
-	 * @return array
112
-	 */
113
-	public function filter_insert_post_data( $postdata ) {
114
-		if ( self::POST_TYPE === $postdata['post_type'] ) {
115
-			$postdata['post_author'] = 0;
116
-			if ( 'future' === $postdata['post_status'] ) {
117
-				$postdata['post_status'] = 'publish';
118
-			}
119
-		}
120
-		return $postdata;
121
-	}
122
-
123
-	/**
124
-	 * Create a (probably unique) post name for scheduled actions in a more performant manner than wp_unique_post_slug().
125
-	 *
126
-	 * When an action's post status is transitioned to something other than 'draft', 'pending' or 'auto-draft, like 'publish'
127
-	 * or 'failed' or 'trash', WordPress will find a unique slug (stored in post_name column) using the wp_unique_post_slug()
128
-	 * function. This is done to ensure URL uniqueness. The approach taken by wp_unique_post_slug() is to iterate over existing
129
-	 * post_name values that match, and append a number 1 greater than the largest. This makes sense when manually creating a
130
-	 * post from the Edit Post screen. It becomes a bottleneck when automatically processing thousands of actions, with a
131
-	 * database containing thousands of related post_name values.
132
-	 *
133
-	 * WordPress 5.1 introduces the 'pre_wp_unique_post_slug' filter for plugins to address this issue.
134
-	 *
135
-	 * We can short-circuit WordPress's wp_unique_post_slug() approach using the 'pre_wp_unique_post_slug' filter. This
136
-	 * method is available to be used as a callback on that filter. It provides a more scalable approach to generating a
137
-	 * post_name/slug that is probably unique. Because Action Scheduler never actually uses the post_name field, or an
138
-	 * action's slug, being probably unique is good enough.
139
-	 *
140
-	 * For more backstory on this issue, see:
141
-	 * - https://github.com/woocommerce/action-scheduler/issues/44 and
142
-	 * - https://core.trac.wordpress.org/ticket/21112
143
-	 *
144
-	 * @param string $override_slug Short-circuit return value.
145
-	 * @param string $slug          The desired slug (post_name).
146
-	 * @param int    $post_ID       Post ID.
147
-	 * @param string $post_status   The post status.
148
-	 * @param string $post_type     Post type.
149
-	 * @return string
150
-	 */
151
-	public function set_unique_post_slug( $override_slug, $slug, $post_ID, $post_status, $post_type ) {
152
-		if ( self::POST_TYPE === $post_type ) {
153
-			$override_slug = uniqid( self::POST_TYPE . '-', true ) . '-' . wp_generate_password( 32, false );
154
-		}
155
-		return $override_slug;
156
-	}
157
-
158
-	/**
159
-	 * Save post schedule.
160
-	 *
161
-	 * @param int    $post_id  Post ID of the scheduled action.
162
-	 * @param string $schedule Schedule to save.
163
-	 *
164
-	 * @return void
165
-	 */
166
-	protected function save_post_schedule( $post_id, $schedule ) {
167
-		update_post_meta( $post_id, self::SCHEDULE_META_KEY, $schedule );
168
-	}
169
-
170
-	/**
171
-	 * Save action group.
172
-	 *
173
-	 * @param int    $post_id Post ID.
174
-	 * @param string $group   Group to save.
175
-	 * @return void
176
-	 */
177
-	protected function save_action_group( $post_id, $group ) {
178
-		if ( empty( $group ) ) {
179
-			wp_set_object_terms( $post_id, array(), self::GROUP_TAXONOMY, false );
180
-		} else {
181
-			wp_set_object_terms( $post_id, array( $group ), self::GROUP_TAXONOMY, false );
182
-		}
183
-	}
184
-
185
-	/**
186
-	 * Fetch actions.
187
-	 *
188
-	 * @param int $action_id Action ID.
189
-	 * @return object
190
-	 */
191
-	public function fetch_action( $action_id ) {
192
-		$post = $this->get_post( $action_id );
193
-		if ( empty( $post ) || self::POST_TYPE !== $post->post_type ) {
194
-			return $this->get_null_action();
195
-		}
196
-
197
-		try {
198
-			$action = $this->make_action_from_post( $post );
199
-		} catch ( ActionScheduler_InvalidActionException $exception ) {
200
-			do_action( 'action_scheduler_failed_fetch_action', $post->ID, $exception );
201
-			return $this->get_null_action();
202
-		}
203
-
204
-		return $action;
205
-	}
206
-
207
-	/**
208
-	 * Get post.
209
-	 *
210
-	 * @param string $action_id - Action ID.
211
-	 * @return WP_Post|null
212
-	 */
213
-	protected function get_post( $action_id ) {
214
-		if ( empty( $action_id ) ) {
215
-			return null;
216
-		}
217
-		return get_post( $action_id );
218
-	}
219
-
220
-	/**
221
-	 * Get NULL action.
222
-	 *
223
-	 * @return ActionScheduler_NullAction
224
-	 */
225
-	protected function get_null_action() {
226
-		return new ActionScheduler_NullAction();
227
-	}
228
-
229
-	/**
230
-	 * Make action from post.
231
-	 *
232
-	 * @param WP_Post $post Post object.
233
-	 * @return WP_Post
234
-	 */
235
-	protected function make_action_from_post( $post ) {
236
-		$hook = $post->post_title;
237
-
238
-		$args = json_decode( $post->post_content, true );
239
-		$this->validate_args( $args, $post->ID );
240
-
241
-		$schedule = get_post_meta( $post->ID, self::SCHEDULE_META_KEY, true );
242
-		$this->validate_schedule( $schedule, $post->ID );
243
-
244
-		$group = wp_get_object_terms( $post->ID, self::GROUP_TAXONOMY, array( 'fields' => 'names' ) );
245
-		$group = empty( $group ) ? '' : reset( $group );
246
-
247
-		return ActionScheduler::factory()->get_stored_action( $this->get_action_status_by_post_status( $post->post_status ), $hook, $args, $schedule, $group );
248
-	}
249
-
250
-	/**
251
-	 * Get action status by post status.
252
-	 *
253
-	 * @param string $post_status Post status.
254
-	 *
255
-	 * @throws InvalidArgumentException Throw InvalidArgumentException if $post_status not in known status fields returned by $this->get_status_labels().
256
-	 * @return string
257
-	 */
258
-	protected function get_action_status_by_post_status( $post_status ) {
259
-
260
-		switch ( $post_status ) {
261
-			case 'publish':
262
-				$action_status = self::STATUS_COMPLETE;
263
-				break;
264
-			case 'trash':
265
-				$action_status = self::STATUS_CANCELED;
266
-				break;
267
-			default:
268
-				if ( ! array_key_exists( $post_status, $this->get_status_labels() ) ) {
269
-					throw new InvalidArgumentException( sprintf( 'Invalid post status: "%s". No matching action status available.', $post_status ) );
270
-				}
271
-				$action_status = $post_status;
272
-				break;
273
-		}
274
-
275
-		return $action_status;
276
-	}
277
-
278
-	/**
279
-	 * Get post status by action status.
280
-	 *
281
-	 * @param string $action_status Action status.
282
-	 *
283
-	 * @throws InvalidArgumentException Throws InvalidArgumentException if $post_status not in known status fields returned by $this->get_status_labels().
284
-	 * @return string
285
-	 */
286
-	protected function get_post_status_by_action_status( $action_status ) {
287
-
288
-		switch ( $action_status ) {
289
-			case self::STATUS_COMPLETE:
290
-				$post_status = 'publish';
291
-				break;
292
-			case self::STATUS_CANCELED:
293
-				$post_status = 'trash';
294
-				break;
295
-			default:
296
-				if ( ! array_key_exists( $action_status, $this->get_status_labels() ) ) {
297
-					throw new InvalidArgumentException( sprintf( 'Invalid action status: "%s".', $action_status ) );
298
-				}
299
-				$post_status = $action_status;
300
-				break;
301
-		}
302
-
303
-		return $post_status;
304
-	}
305
-
306
-	/**
307
-	 * Returns the SQL statement to query (or count) actions.
308
-	 *
309
-	 * @param array  $query            - Filtering options.
310
-	 * @param string $select_or_count  - Whether the SQL should select and return the IDs or just the row count.
311
-	 *
312
-	 * @throws InvalidArgumentException - Throw InvalidArgumentException if $select_or_count not count or select.
313
-	 * @return string SQL statement. The returned SQL is already properly escaped.
314
-	 */
315
-	protected function get_query_actions_sql( array $query, $select_or_count = 'select' ) {
316
-
317
-		if ( ! in_array( $select_or_count, array( 'select', 'count' ), true ) ) {
318
-			throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'action-scheduler' ) );
319
-		}
320
-
321
-		$query = wp_parse_args(
322
-			$query,
323
-			array(
324
-				'hook'             => '',
325
-				'args'             => null,
326
-				'date'             => null,
327
-				'date_compare'     => '<=',
328
-				'modified'         => null,
329
-				'modified_compare' => '<=',
330
-				'group'            => '',
331
-				'status'           => '',
332
-				'claimed'          => null,
333
-				'per_page'         => 5,
334
-				'offset'           => 0,
335
-				'orderby'          => 'date',
336
-				'order'            => 'ASC',
337
-				'search'           => '',
338
-			)
339
-		);
340
-
341
-		/**
342
-		 * Global wpdb object.
343
-		 *
344
-		 * @var wpdb $wpdb
345
-		 */
346
-		global $wpdb;
347
-		$sql        = ( 'count' === $select_or_count ) ? 'SELECT count(p.ID)' : 'SELECT p.ID ';
348
-		$sql       .= "FROM {$wpdb->posts} p";
349
-		$sql_params = array();
350
-		if ( empty( $query['group'] ) && 'group' === $query['orderby'] ) {
351
-			$sql .= " LEFT JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
352
-			$sql .= " LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
353
-			$sql .= " LEFT JOIN {$wpdb->terms} t ON tt.term_id=t.term_id";
354
-		} elseif ( ! empty( $query['group'] ) ) {
355
-			$sql         .= " INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
356
-			$sql         .= " INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
357
-			$sql         .= " INNER JOIN {$wpdb->terms} t ON tt.term_id=t.term_id";
358
-			$sql         .= ' AND t.slug=%s';
359
-			$sql_params[] = $query['group'];
360
-		}
361
-		$sql         .= ' WHERE post_type=%s';
362
-		$sql_params[] = self::POST_TYPE;
363
-		if ( $query['hook'] ) {
364
-			$sql         .= ' AND p.post_title=%s';
365
-			$sql_params[] = $query['hook'];
366
-		}
367
-		if ( $query['args'] !== null ) {
368
-			$sql         .= ' AND p.post_content=%s';
369
-			$sql_params[] = wp_json_encode( $query['args'] );
370
-		}
371
-
372
-		if ( $query['status'] ) {
373
-			$post_statuses = array_map( array( $this, 'get_post_status_by_action_status' ), (array) $query['status'] );
374
-			$placeholders  = array_fill( 0, count( $post_statuses ), '%s' );
375
-			$sql          .= ' AND p.post_status IN (' . join( ', ', $placeholders ) . ')';
376
-			$sql_params    = array_merge( $sql_params, array_values( $post_statuses ) );
377
-		}
378
-
379
-		if ( $query['date'] instanceof DateTime ) {
380
-			$date = clone $query['date'];
381
-			$date->setTimezone( new DateTimeZone( 'UTC' ) );
382
-			$date_string  = $date->format( 'Y-m-d H:i:s' );
383
-			$comparator   = $this->validate_sql_comparator( $query['date_compare'] );
384
-			$sql         .= " AND p.post_date_gmt $comparator %s";
385
-			$sql_params[] = $date_string;
386
-		}
387
-
388
-		if ( $query['modified'] instanceof DateTime ) {
389
-			$modified = clone $query['modified'];
390
-			$modified->setTimezone( new DateTimeZone( 'UTC' ) );
391
-			$date_string  = $modified->format( 'Y-m-d H:i:s' );
392
-			$comparator   = $this->validate_sql_comparator( $query['modified_compare'] );
393
-			$sql         .= " AND p.post_modified_gmt $comparator %s";
394
-			$sql_params[] = $date_string;
395
-		}
396
-
397
-		if ( true === $query['claimed'] ) {
398
-			$sql .= " AND p.post_password != ''";
399
-		} elseif ( false === $query['claimed'] ) {
400
-			$sql .= " AND p.post_password = ''";
401
-		} elseif ( $query['claimed'] !== null ) {
402
-			$sql         .= ' AND p.post_password = %s';
403
-			$sql_params[] = $query['claimed'];
404
-		}
405
-
406
-		if ( ! empty( $query['search'] ) ) {
407
-			$sql .= ' AND (p.post_title LIKE %s OR p.post_content LIKE %s OR p.post_password LIKE %s)';
408
-			for ( $i = 0; $i < 3; $i++ ) {
409
-				$sql_params[] = sprintf( '%%%s%%', $query['search'] );
410
-			}
411
-		}
412
-
413
-		if ( 'select' === $select_or_count ) {
414
-			switch ( $query['orderby'] ) {
415
-				case 'hook':
416
-					$orderby = 'p.post_title';
417
-					break;
418
-				case 'group':
419
-					$orderby = 't.name';
420
-					break;
421
-				case 'status':
422
-					$orderby = 'p.post_status';
423
-					break;
424
-				case 'modified':
425
-					$orderby = 'p.post_modified';
426
-					break;
427
-				case 'claim_id':
428
-					$orderby = 'p.post_password';
429
-					break;
430
-				case 'schedule':
431
-				case 'date':
432
-				default:
433
-					$orderby = 'p.post_date_gmt';
434
-					break;
435
-			}
436
-			if ( 'ASC' === strtoupper( $query['order'] ) ) {
437
-				$order = 'ASC';
438
-			} else {
439
-				$order = 'DESC';
440
-			}
441
-			$sql .= " ORDER BY $orderby $order";
442
-			if ( $query['per_page'] > 0 ) {
443
-				$sql         .= ' LIMIT %d, %d';
444
-				$sql_params[] = $query['offset'];
445
-				$sql_params[] = $query['per_page'];
446
-			}
447
-		}
448
-
449
-		return $wpdb->prepare( $sql, $sql_params ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
450
-	}
451
-
452
-	/**
453
-	 * Query for action count or list of action IDs.
454
-	 *
455
-	 * @since 3.3.0 $query['status'] accepts array of statuses instead of a single status.
456
-	 *
457
-	 * @see ActionScheduler_Store::query_actions for $query arg usage.
458
-	 *
459
-	 * @param array  $query      Query filtering options.
460
-	 * @param string $query_type Whether to select or count the results. Defaults to select.
461
-	 *
462
-	 * @return string|array|null The IDs of actions matching the query. Null on failure.
463
-	 */
464
-	public function query_actions( $query = array(), $query_type = 'select' ) {
465
-		/**
466
-		 * Global $wpdb object.
467
-		 *
468
-		 * @var wpdb $wpdb
469
-		 */
470
-		global $wpdb;
471
-
472
-		$sql = $this->get_query_actions_sql( $query, $query_type );
473
-
474
-		return ( 'count' === $query_type ) ? $wpdb->get_var( $sql ) : $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared
475
-	}
476
-
477
-	/**
478
-	 * Get a count of all actions in the store, grouped by status
479
-	 *
480
-	 * @return array
481
-	 */
482
-	public function action_counts() {
483
-
484
-		$action_counts_by_status = array();
485
-		$action_stati_and_labels = $this->get_status_labels();
486
-		$posts_count_by_status   = (array) wp_count_posts( self::POST_TYPE, 'readable' );
487
-
488
-		foreach ( $posts_count_by_status as $post_status_name => $count ) {
489
-
490
-			try {
491
-				$action_status_name = $this->get_action_status_by_post_status( $post_status_name );
492
-			} catch ( Exception $e ) {
493
-				// Ignore any post statuses that aren't for actions.
494
-				continue;
495
-			}
496
-			if ( array_key_exists( $action_status_name, $action_stati_and_labels ) ) {
497
-				$action_counts_by_status[ $action_status_name ] = $count;
498
-			}
499
-		}
500
-
501
-		return $action_counts_by_status;
502
-	}
503
-
504
-	/**
505
-	 * Cancel action.
506
-	 *
507
-	 * @param int $action_id Action ID.
508
-	 *
509
-	 * @throws InvalidArgumentException If $action_id is not identified.
510
-	 */
511
-	public function cancel_action( $action_id ) {
512
-		$post = get_post( $action_id );
513
-		if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
514
-			/* translators: %s is the action ID */
515
-			throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
516
-		}
517
-		do_action( 'action_scheduler_canceled_action', $action_id );
518
-		add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
519
-		wp_trash_post( $action_id );
520
-		remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
521
-	}
522
-
523
-	/**
524
-	 * Delete action.
525
-	 *
526
-	 * @param int $action_id Action ID.
527
-	 * @return void
528
-	 * @throws InvalidArgumentException If action is not identified.
529
-	 */
530
-	public function delete_action( $action_id ) {
531
-		$post = get_post( $action_id );
532
-		if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
533
-			/* translators: %s is the action ID */
534
-			throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
535
-		}
536
-		do_action( 'action_scheduler_deleted_action', $action_id );
537
-
538
-		wp_delete_post( $action_id, true );
539
-	}
540
-
541
-	/**
542
-	 * Get date for claim id.
543
-	 *
544
-	 * @param int $action_id Action ID.
545
-	 * @return ActionScheduler_DateTime The date the action is schedule to run, or the date that it ran.
546
-	 */
547
-	public function get_date( $action_id ) {
548
-		$next = $this->get_date_gmt( $action_id );
549
-		return ActionScheduler_TimezoneHelper::set_local_timezone( $next );
550
-	}
551
-
552
-	/**
553
-	 * Get Date GMT.
554
-	 *
555
-	 * @param int $action_id Action ID.
556
-	 *
557
-	 * @throws InvalidArgumentException If $action_id is not identified.
558
-	 * @return ActionScheduler_DateTime The date the action is schedule to run, or the date that it ran.
559
-	 */
560
-	public function get_date_gmt( $action_id ) {
561
-		$post = get_post( $action_id );
562
-		if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
563
-			/* translators: %s is the action ID */
564
-			throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
565
-		}
566
-		if ( 'publish' === $post->post_status ) {
567
-			return as_get_datetime_object( $post->post_modified_gmt );
568
-		} else {
569
-			return as_get_datetime_object( $post->post_date_gmt );
570
-		}
571
-	}
572
-
573
-	/**
574
-	 * Stake claim.
575
-	 *
576
-	 * @param int      $max_actions Maximum number of actions.
577
-	 * @param DateTime $before_date Jobs must be schedule before this date. Defaults to now.
578
-	 * @param array    $hooks       Claim only actions with a hook or hooks.
579
-	 * @param string   $group       Claim only actions in the given group.
580
-	 *
581
-	 * @return ActionScheduler_ActionClaim
582
-	 * @throws RuntimeException When there is an error staking a claim.
583
-	 * @throws InvalidArgumentException When the given group is not valid.
584
-	 */
585
-	public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' ) {
586
-		$this->claim_before_date = $before_date;
587
-		$claim_id                = $this->generate_claim_id();
588
-		$this->claim_actions( $claim_id, $max_actions, $before_date, $hooks, $group );
589
-		$action_ids              = $this->find_actions_by_claim_id( $claim_id );
590
-		$this->claim_before_date = null;
591
-
592
-		return new ActionScheduler_ActionClaim( $claim_id, $action_ids );
593
-	}
594
-
595
-	/**
596
-	 * Get claim count.
597
-	 *
598
-	 * @return int
599
-	 */
600
-	public function get_claim_count() {
601
-		global $wpdb;
602
-
603
-		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
604
-		return $wpdb->get_var(
605
-			$wpdb->prepare(
606
-				"SELECT COUNT(DISTINCT post_password) FROM {$wpdb->posts} WHERE post_password != '' AND post_type = %s AND post_status IN ('in-progress','pending')",
607
-				array( self::POST_TYPE )
608
-			)
609
-		);
610
-	}
611
-
612
-	/**
613
-	 * Generate claim id.
614
-	 *
615
-	 * @return string
616
-	 */
617
-	protected function generate_claim_id() {
618
-		$claim_id = md5( microtime( true ) . wp_rand( 0, 1000 ) );
619
-		return substr( $claim_id, 0, 20 ); // to fit in db field with 20 char limit.
620
-	}
621
-
622
-	/**
623
-	 * Claim actions.
624
-	 *
625
-	 * @param string   $claim_id    Claim ID.
626
-	 * @param int      $limit       Limit.
627
-	 * @param DateTime $before_date Should use UTC timezone.
628
-	 * @param array    $hooks       Claim only actions with a hook or hooks.
629
-	 * @param string   $group       Claim only actions in the given group.
630
-	 *
631
-	 * @return int The number of actions that were claimed.
632
-	 * @throws RuntimeException  When there is a database error.
633
-	 */
634
-	protected function claim_actions( $claim_id, $limit, DateTime $before_date = null, $hooks = array(), $group = '' ) {
635
-		// Set up initial variables.
636
-		$date      = null === $before_date ? as_get_datetime_object() : clone $before_date;
637
-		$limit_ids = ! empty( $group );
638
-		$ids       = $limit_ids ? $this->get_actions_by_group( $group, $limit, $date ) : array();
639
-
640
-		// If limiting by IDs and no posts found, then return early since we have nothing to update.
641
-		if ( $limit_ids && 0 === count( $ids ) ) {
642
-			return 0;
643
-		}
644
-
645
-		/**
646
-		 * Global wpdb object.
647
-		 *
648
-		 * @var wpdb $wpdb
649
-		 */
650
-		global $wpdb;
651
-
652
-		/*
7
+    const POST_TYPE         = 'scheduled-action';
8
+    const GROUP_TAXONOMY    = 'action-group';
9
+    const SCHEDULE_META_KEY = '_action_manager_schedule';
10
+    const DEPENDENCIES_MET  = 'as-post-store-dependencies-met';
11
+
12
+    /**
13
+     * Used to share information about the before_date property of claims internally.
14
+     *
15
+     * This is used in preference to passing the same information as a method param
16
+     * for backwards-compatibility reasons.
17
+     *
18
+     * @var DateTime|null
19
+     */
20
+    private $claim_before_date = null;
21
+
22
+    /**
23
+     * Local Timezone.
24
+     *
25
+     * @var DateTimeZone
26
+     */
27
+    protected $local_timezone = null;
28
+
29
+    /**
30
+     * Save action.
31
+     *
32
+     * @param ActionScheduler_Action $action Scheduled Action.
33
+     * @param DateTime               $scheduled_date Scheduled Date.
34
+     *
35
+     * @throws RuntimeException Throws an exception if the action could not be saved.
36
+     * @return int
37
+     */
38
+    public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = null ) {
39
+        try {
40
+            $this->validate_action( $action );
41
+            $post_array = $this->create_post_array( $action, $scheduled_date );
42
+            $post_id    = $this->save_post_array( $post_array );
43
+            $this->save_post_schedule( $post_id, $action->get_schedule() );
44
+            $this->save_action_group( $post_id, $action->get_group() );
45
+            do_action( 'action_scheduler_stored_action', $post_id );
46
+            return $post_id;
47
+        } catch ( Exception $e ) {
48
+            /* translators: %s: action error message */
49
+            throw new RuntimeException( sprintf( __( 'Error saving action: %s', 'action-scheduler' ), $e->getMessage() ), 0 );
50
+        }
51
+    }
52
+
53
+    /**
54
+     * Create post array.
55
+     *
56
+     * @param ActionScheduler_Action $action Scheduled Action.
57
+     * @param DateTime               $scheduled_date Scheduled Date.
58
+     *
59
+     * @return array Returns an array of post data.
60
+     */
61
+    protected function create_post_array( ActionScheduler_Action $action, DateTime $scheduled_date = null ) {
62
+        $post = array(
63
+            'post_type'     => self::POST_TYPE,
64
+            'post_title'    => $action->get_hook(),
65
+            'post_content'  => wp_json_encode( $action->get_args() ),
66
+            'post_status'   => ( $action->is_finished() ? 'publish' : 'pending' ),
67
+            'post_date_gmt' => $this->get_scheduled_date_string( $action, $scheduled_date ),
68
+            'post_date'     => $this->get_scheduled_date_string_local( $action, $scheduled_date ),
69
+        );
70
+        return $post;
71
+    }
72
+
73
+    /**
74
+     * Save post array.
75
+     *
76
+     * @param array $post_array Post array.
77
+     * @return int Returns the post ID.
78
+     * @throws RuntimeException Throws an exception if the action could not be saved.
79
+     */
80
+    protected function save_post_array( $post_array ) {
81
+        add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 );
82
+        add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
83
+
84
+        $has_kses = false !== has_filter( 'content_save_pre', 'wp_filter_post_kses' );
85
+
86
+        if ( $has_kses ) {
87
+            // Prevent KSES from corrupting JSON in post_content.
88
+            kses_remove_filters();
89
+        }
90
+
91
+        $post_id = wp_insert_post( $post_array );
92
+
93
+        if ( $has_kses ) {
94
+            kses_init_filters();
95
+        }
96
+
97
+        remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
98
+        remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
99
+
100
+        if ( is_wp_error( $post_id ) || empty( $post_id ) ) {
101
+            throw new RuntimeException( __( 'Unable to save action.', 'action-scheduler' ) );
102
+        }
103
+        return $post_id;
104
+    }
105
+
106
+    /**
107
+     * Filter insert post data.
108
+     *
109
+     * @param array $postdata Post data to filter.
110
+     *
111
+     * @return array
112
+     */
113
+    public function filter_insert_post_data( $postdata ) {
114
+        if ( self::POST_TYPE === $postdata['post_type'] ) {
115
+            $postdata['post_author'] = 0;
116
+            if ( 'future' === $postdata['post_status'] ) {
117
+                $postdata['post_status'] = 'publish';
118
+            }
119
+        }
120
+        return $postdata;
121
+    }
122
+
123
+    /**
124
+     * Create a (probably unique) post name for scheduled actions in a more performant manner than wp_unique_post_slug().
125
+     *
126
+     * When an action's post status is transitioned to something other than 'draft', 'pending' or 'auto-draft, like 'publish'
127
+     * or 'failed' or 'trash', WordPress will find a unique slug (stored in post_name column) using the wp_unique_post_slug()
128
+     * function. This is done to ensure URL uniqueness. The approach taken by wp_unique_post_slug() is to iterate over existing
129
+     * post_name values that match, and append a number 1 greater than the largest. This makes sense when manually creating a
130
+     * post from the Edit Post screen. It becomes a bottleneck when automatically processing thousands of actions, with a
131
+     * database containing thousands of related post_name values.
132
+     *
133
+     * WordPress 5.1 introduces the 'pre_wp_unique_post_slug' filter for plugins to address this issue.
134
+     *
135
+     * We can short-circuit WordPress's wp_unique_post_slug() approach using the 'pre_wp_unique_post_slug' filter. This
136
+     * method is available to be used as a callback on that filter. It provides a more scalable approach to generating a
137
+     * post_name/slug that is probably unique. Because Action Scheduler never actually uses the post_name field, or an
138
+     * action's slug, being probably unique is good enough.
139
+     *
140
+     * For more backstory on this issue, see:
141
+     * - https://github.com/woocommerce/action-scheduler/issues/44 and
142
+     * - https://core.trac.wordpress.org/ticket/21112
143
+     *
144
+     * @param string $override_slug Short-circuit return value.
145
+     * @param string $slug          The desired slug (post_name).
146
+     * @param int    $post_ID       Post ID.
147
+     * @param string $post_status   The post status.
148
+     * @param string $post_type     Post type.
149
+     * @return string
150
+     */
151
+    public function set_unique_post_slug( $override_slug, $slug, $post_ID, $post_status, $post_type ) {
152
+        if ( self::POST_TYPE === $post_type ) {
153
+            $override_slug = uniqid( self::POST_TYPE . '-', true ) . '-' . wp_generate_password( 32, false );
154
+        }
155
+        return $override_slug;
156
+    }
157
+
158
+    /**
159
+     * Save post schedule.
160
+     *
161
+     * @param int    $post_id  Post ID of the scheduled action.
162
+     * @param string $schedule Schedule to save.
163
+     *
164
+     * @return void
165
+     */
166
+    protected function save_post_schedule( $post_id, $schedule ) {
167
+        update_post_meta( $post_id, self::SCHEDULE_META_KEY, $schedule );
168
+    }
169
+
170
+    /**
171
+     * Save action group.
172
+     *
173
+     * @param int    $post_id Post ID.
174
+     * @param string $group   Group to save.
175
+     * @return void
176
+     */
177
+    protected function save_action_group( $post_id, $group ) {
178
+        if ( empty( $group ) ) {
179
+            wp_set_object_terms( $post_id, array(), self::GROUP_TAXONOMY, false );
180
+        } else {
181
+            wp_set_object_terms( $post_id, array( $group ), self::GROUP_TAXONOMY, false );
182
+        }
183
+    }
184
+
185
+    /**
186
+     * Fetch actions.
187
+     *
188
+     * @param int $action_id Action ID.
189
+     * @return object
190
+     */
191
+    public function fetch_action( $action_id ) {
192
+        $post = $this->get_post( $action_id );
193
+        if ( empty( $post ) || self::POST_TYPE !== $post->post_type ) {
194
+            return $this->get_null_action();
195
+        }
196
+
197
+        try {
198
+            $action = $this->make_action_from_post( $post );
199
+        } catch ( ActionScheduler_InvalidActionException $exception ) {
200
+            do_action( 'action_scheduler_failed_fetch_action', $post->ID, $exception );
201
+            return $this->get_null_action();
202
+        }
203
+
204
+        return $action;
205
+    }
206
+
207
+    /**
208
+     * Get post.
209
+     *
210
+     * @param string $action_id - Action ID.
211
+     * @return WP_Post|null
212
+     */
213
+    protected function get_post( $action_id ) {
214
+        if ( empty( $action_id ) ) {
215
+            return null;
216
+        }
217
+        return get_post( $action_id );
218
+    }
219
+
220
+    /**
221
+     * Get NULL action.
222
+     *
223
+     * @return ActionScheduler_NullAction
224
+     */
225
+    protected function get_null_action() {
226
+        return new ActionScheduler_NullAction();
227
+    }
228
+
229
+    /**
230
+     * Make action from post.
231
+     *
232
+     * @param WP_Post $post Post object.
233
+     * @return WP_Post
234
+     */
235
+    protected function make_action_from_post( $post ) {
236
+        $hook = $post->post_title;
237
+
238
+        $args = json_decode( $post->post_content, true );
239
+        $this->validate_args( $args, $post->ID );
240
+
241
+        $schedule = get_post_meta( $post->ID, self::SCHEDULE_META_KEY, true );
242
+        $this->validate_schedule( $schedule, $post->ID );
243
+
244
+        $group = wp_get_object_terms( $post->ID, self::GROUP_TAXONOMY, array( 'fields' => 'names' ) );
245
+        $group = empty( $group ) ? '' : reset( $group );
246
+
247
+        return ActionScheduler::factory()->get_stored_action( $this->get_action_status_by_post_status( $post->post_status ), $hook, $args, $schedule, $group );
248
+    }
249
+
250
+    /**
251
+     * Get action status by post status.
252
+     *
253
+     * @param string $post_status Post status.
254
+     *
255
+     * @throws InvalidArgumentException Throw InvalidArgumentException if $post_status not in known status fields returned by $this->get_status_labels().
256
+     * @return string
257
+     */
258
+    protected function get_action_status_by_post_status( $post_status ) {
259
+
260
+        switch ( $post_status ) {
261
+            case 'publish':
262
+                $action_status = self::STATUS_COMPLETE;
263
+                break;
264
+            case 'trash':
265
+                $action_status = self::STATUS_CANCELED;
266
+                break;
267
+            default:
268
+                if ( ! array_key_exists( $post_status, $this->get_status_labels() ) ) {
269
+                    throw new InvalidArgumentException( sprintf( 'Invalid post status: "%s". No matching action status available.', $post_status ) );
270
+                }
271
+                $action_status = $post_status;
272
+                break;
273
+        }
274
+
275
+        return $action_status;
276
+    }
277
+
278
+    /**
279
+     * Get post status by action status.
280
+     *
281
+     * @param string $action_status Action status.
282
+     *
283
+     * @throws InvalidArgumentException Throws InvalidArgumentException if $post_status not in known status fields returned by $this->get_status_labels().
284
+     * @return string
285
+     */
286
+    protected function get_post_status_by_action_status( $action_status ) {
287
+
288
+        switch ( $action_status ) {
289
+            case self::STATUS_COMPLETE:
290
+                $post_status = 'publish';
291
+                break;
292
+            case self::STATUS_CANCELED:
293
+                $post_status = 'trash';
294
+                break;
295
+            default:
296
+                if ( ! array_key_exists( $action_status, $this->get_status_labels() ) ) {
297
+                    throw new InvalidArgumentException( sprintf( 'Invalid action status: "%s".', $action_status ) );
298
+                }
299
+                $post_status = $action_status;
300
+                break;
301
+        }
302
+
303
+        return $post_status;
304
+    }
305
+
306
+    /**
307
+     * Returns the SQL statement to query (or count) actions.
308
+     *
309
+     * @param array  $query            - Filtering options.
310
+     * @param string $select_or_count  - Whether the SQL should select and return the IDs or just the row count.
311
+     *
312
+     * @throws InvalidArgumentException - Throw InvalidArgumentException if $select_or_count not count or select.
313
+     * @return string SQL statement. The returned SQL is already properly escaped.
314
+     */
315
+    protected function get_query_actions_sql( array $query, $select_or_count = 'select' ) {
316
+
317
+        if ( ! in_array( $select_or_count, array( 'select', 'count' ), true ) ) {
318
+            throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'action-scheduler' ) );
319
+        }
320
+
321
+        $query = wp_parse_args(
322
+            $query,
323
+            array(
324
+                'hook'             => '',
325
+                'args'             => null,
326
+                'date'             => null,
327
+                'date_compare'     => '<=',
328
+                'modified'         => null,
329
+                'modified_compare' => '<=',
330
+                'group'            => '',
331
+                'status'           => '',
332
+                'claimed'          => null,
333
+                'per_page'         => 5,
334
+                'offset'           => 0,
335
+                'orderby'          => 'date',
336
+                'order'            => 'ASC',
337
+                'search'           => '',
338
+            )
339
+        );
340
+
341
+        /**
342
+         * Global wpdb object.
343
+         *
344
+         * @var wpdb $wpdb
345
+         */
346
+        global $wpdb;
347
+        $sql        = ( 'count' === $select_or_count ) ? 'SELECT count(p.ID)' : 'SELECT p.ID ';
348
+        $sql       .= "FROM {$wpdb->posts} p";
349
+        $sql_params = array();
350
+        if ( empty( $query['group'] ) && 'group' === $query['orderby'] ) {
351
+            $sql .= " LEFT JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
352
+            $sql .= " LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
353
+            $sql .= " LEFT JOIN {$wpdb->terms} t ON tt.term_id=t.term_id";
354
+        } elseif ( ! empty( $query['group'] ) ) {
355
+            $sql         .= " INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
356
+            $sql         .= " INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
357
+            $sql         .= " INNER JOIN {$wpdb->terms} t ON tt.term_id=t.term_id";
358
+            $sql         .= ' AND t.slug=%s';
359
+            $sql_params[] = $query['group'];
360
+        }
361
+        $sql         .= ' WHERE post_type=%s';
362
+        $sql_params[] = self::POST_TYPE;
363
+        if ( $query['hook'] ) {
364
+            $sql         .= ' AND p.post_title=%s';
365
+            $sql_params[] = $query['hook'];
366
+        }
367
+        if ( $query['args'] !== null ) {
368
+            $sql         .= ' AND p.post_content=%s';
369
+            $sql_params[] = wp_json_encode( $query['args'] );
370
+        }
371
+
372
+        if ( $query['status'] ) {
373
+            $post_statuses = array_map( array( $this, 'get_post_status_by_action_status' ), (array) $query['status'] );
374
+            $placeholders  = array_fill( 0, count( $post_statuses ), '%s' );
375
+            $sql          .= ' AND p.post_status IN (' . join( ', ', $placeholders ) . ')';
376
+            $sql_params    = array_merge( $sql_params, array_values( $post_statuses ) );
377
+        }
378
+
379
+        if ( $query['date'] instanceof DateTime ) {
380
+            $date = clone $query['date'];
381
+            $date->setTimezone( new DateTimeZone( 'UTC' ) );
382
+            $date_string  = $date->format( 'Y-m-d H:i:s' );
383
+            $comparator   = $this->validate_sql_comparator( $query['date_compare'] );
384
+            $sql         .= " AND p.post_date_gmt $comparator %s";
385
+            $sql_params[] = $date_string;
386
+        }
387
+
388
+        if ( $query['modified'] instanceof DateTime ) {
389
+            $modified = clone $query['modified'];
390
+            $modified->setTimezone( new DateTimeZone( 'UTC' ) );
391
+            $date_string  = $modified->format( 'Y-m-d H:i:s' );
392
+            $comparator   = $this->validate_sql_comparator( $query['modified_compare'] );
393
+            $sql         .= " AND p.post_modified_gmt $comparator %s";
394
+            $sql_params[] = $date_string;
395
+        }
396
+
397
+        if ( true === $query['claimed'] ) {
398
+            $sql .= " AND p.post_password != ''";
399
+        } elseif ( false === $query['claimed'] ) {
400
+            $sql .= " AND p.post_password = ''";
401
+        } elseif ( $query['claimed'] !== null ) {
402
+            $sql         .= ' AND p.post_password = %s';
403
+            $sql_params[] = $query['claimed'];
404
+        }
405
+
406
+        if ( ! empty( $query['search'] ) ) {
407
+            $sql .= ' AND (p.post_title LIKE %s OR p.post_content LIKE %s OR p.post_password LIKE %s)';
408
+            for ( $i = 0; $i < 3; $i++ ) {
409
+                $sql_params[] = sprintf( '%%%s%%', $query['search'] );
410
+            }
411
+        }
412
+
413
+        if ( 'select' === $select_or_count ) {
414
+            switch ( $query['orderby'] ) {
415
+                case 'hook':
416
+                    $orderby = 'p.post_title';
417
+                    break;
418
+                case 'group':
419
+                    $orderby = 't.name';
420
+                    break;
421
+                case 'status':
422
+                    $orderby = 'p.post_status';
423
+                    break;
424
+                case 'modified':
425
+                    $orderby = 'p.post_modified';
426
+                    break;
427
+                case 'claim_id':
428
+                    $orderby = 'p.post_password';
429
+                    break;
430
+                case 'schedule':
431
+                case 'date':
432
+                default:
433
+                    $orderby = 'p.post_date_gmt';
434
+                    break;
435
+            }
436
+            if ( 'ASC' === strtoupper( $query['order'] ) ) {
437
+                $order = 'ASC';
438
+            } else {
439
+                $order = 'DESC';
440
+            }
441
+            $sql .= " ORDER BY $orderby $order";
442
+            if ( $query['per_page'] > 0 ) {
443
+                $sql         .= ' LIMIT %d, %d';
444
+                $sql_params[] = $query['offset'];
445
+                $sql_params[] = $query['per_page'];
446
+            }
447
+        }
448
+
449
+        return $wpdb->prepare( $sql, $sql_params ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
450
+    }
451
+
452
+    /**
453
+     * Query for action count or list of action IDs.
454
+     *
455
+     * @since 3.3.0 $query['status'] accepts array of statuses instead of a single status.
456
+     *
457
+     * @see ActionScheduler_Store::query_actions for $query arg usage.
458
+     *
459
+     * @param array  $query      Query filtering options.
460
+     * @param string $query_type Whether to select or count the results. Defaults to select.
461
+     *
462
+     * @return string|array|null The IDs of actions matching the query. Null on failure.
463
+     */
464
+    public function query_actions( $query = array(), $query_type = 'select' ) {
465
+        /**
466
+         * Global $wpdb object.
467
+         *
468
+         * @var wpdb $wpdb
469
+         */
470
+        global $wpdb;
471
+
472
+        $sql = $this->get_query_actions_sql( $query, $query_type );
473
+
474
+        return ( 'count' === $query_type ) ? $wpdb->get_var( $sql ) : $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared
475
+    }
476
+
477
+    /**
478
+     * Get a count of all actions in the store, grouped by status
479
+     *
480
+     * @return array
481
+     */
482
+    public function action_counts() {
483
+
484
+        $action_counts_by_status = array();
485
+        $action_stati_and_labels = $this->get_status_labels();
486
+        $posts_count_by_status   = (array) wp_count_posts( self::POST_TYPE, 'readable' );
487
+
488
+        foreach ( $posts_count_by_status as $post_status_name => $count ) {
489
+
490
+            try {
491
+                $action_status_name = $this->get_action_status_by_post_status( $post_status_name );
492
+            } catch ( Exception $e ) {
493
+                // Ignore any post statuses that aren't for actions.
494
+                continue;
495
+            }
496
+            if ( array_key_exists( $action_status_name, $action_stati_and_labels ) ) {
497
+                $action_counts_by_status[ $action_status_name ] = $count;
498
+            }
499
+        }
500
+
501
+        return $action_counts_by_status;
502
+    }
503
+
504
+    /**
505
+     * Cancel action.
506
+     *
507
+     * @param int $action_id Action ID.
508
+     *
509
+     * @throws InvalidArgumentException If $action_id is not identified.
510
+     */
511
+    public function cancel_action( $action_id ) {
512
+        $post = get_post( $action_id );
513
+        if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
514
+            /* translators: %s is the action ID */
515
+            throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
516
+        }
517
+        do_action( 'action_scheduler_canceled_action', $action_id );
518
+        add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
519
+        wp_trash_post( $action_id );
520
+        remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
521
+    }
522
+
523
+    /**
524
+     * Delete action.
525
+     *
526
+     * @param int $action_id Action ID.
527
+     * @return void
528
+     * @throws InvalidArgumentException If action is not identified.
529
+     */
530
+    public function delete_action( $action_id ) {
531
+        $post = get_post( $action_id );
532
+        if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
533
+            /* translators: %s is the action ID */
534
+            throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
535
+        }
536
+        do_action( 'action_scheduler_deleted_action', $action_id );
537
+
538
+        wp_delete_post( $action_id, true );
539
+    }
540
+
541
+    /**
542
+     * Get date for claim id.
543
+     *
544
+     * @param int $action_id Action ID.
545
+     * @return ActionScheduler_DateTime The date the action is schedule to run, or the date that it ran.
546
+     */
547
+    public function get_date( $action_id ) {
548
+        $next = $this->get_date_gmt( $action_id );
549
+        return ActionScheduler_TimezoneHelper::set_local_timezone( $next );
550
+    }
551
+
552
+    /**
553
+     * Get Date GMT.
554
+     *
555
+     * @param int $action_id Action ID.
556
+     *
557
+     * @throws InvalidArgumentException If $action_id is not identified.
558
+     * @return ActionScheduler_DateTime The date the action is schedule to run, or the date that it ran.
559
+     */
560
+    public function get_date_gmt( $action_id ) {
561
+        $post = get_post( $action_id );
562
+        if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
563
+            /* translators: %s is the action ID */
564
+            throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
565
+        }
566
+        if ( 'publish' === $post->post_status ) {
567
+            return as_get_datetime_object( $post->post_modified_gmt );
568
+        } else {
569
+            return as_get_datetime_object( $post->post_date_gmt );
570
+        }
571
+    }
572
+
573
+    /**
574
+     * Stake claim.
575
+     *
576
+     * @param int      $max_actions Maximum number of actions.
577
+     * @param DateTime $before_date Jobs must be schedule before this date. Defaults to now.
578
+     * @param array    $hooks       Claim only actions with a hook or hooks.
579
+     * @param string   $group       Claim only actions in the given group.
580
+     *
581
+     * @return ActionScheduler_ActionClaim
582
+     * @throws RuntimeException When there is an error staking a claim.
583
+     * @throws InvalidArgumentException When the given group is not valid.
584
+     */
585
+    public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' ) {
586
+        $this->claim_before_date = $before_date;
587
+        $claim_id                = $this->generate_claim_id();
588
+        $this->claim_actions( $claim_id, $max_actions, $before_date, $hooks, $group );
589
+        $action_ids              = $this->find_actions_by_claim_id( $claim_id );
590
+        $this->claim_before_date = null;
591
+
592
+        return new ActionScheduler_ActionClaim( $claim_id, $action_ids );
593
+    }
594
+
595
+    /**
596
+     * Get claim count.
597
+     *
598
+     * @return int
599
+     */
600
+    public function get_claim_count() {
601
+        global $wpdb;
602
+
603
+        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
604
+        return $wpdb->get_var(
605
+            $wpdb->prepare(
606
+                "SELECT COUNT(DISTINCT post_password) FROM {$wpdb->posts} WHERE post_password != '' AND post_type = %s AND post_status IN ('in-progress','pending')",
607
+                array( self::POST_TYPE )
608
+            )
609
+        );
610
+    }
611
+
612
+    /**
613
+     * Generate claim id.
614
+     *
615
+     * @return string
616
+     */
617
+    protected function generate_claim_id() {
618
+        $claim_id = md5( microtime( true ) . wp_rand( 0, 1000 ) );
619
+        return substr( $claim_id, 0, 20 ); // to fit in db field with 20 char limit.
620
+    }
621
+
622
+    /**
623
+     * Claim actions.
624
+     *
625
+     * @param string   $claim_id    Claim ID.
626
+     * @param int      $limit       Limit.
627
+     * @param DateTime $before_date Should use UTC timezone.
628
+     * @param array    $hooks       Claim only actions with a hook or hooks.
629
+     * @param string   $group       Claim only actions in the given group.
630
+     *
631
+     * @return int The number of actions that were claimed.
632
+     * @throws RuntimeException  When there is a database error.
633
+     */
634
+    protected function claim_actions( $claim_id, $limit, DateTime $before_date = null, $hooks = array(), $group = '' ) {
635
+        // Set up initial variables.
636
+        $date      = null === $before_date ? as_get_datetime_object() : clone $before_date;
637
+        $limit_ids = ! empty( $group );
638
+        $ids       = $limit_ids ? $this->get_actions_by_group( $group, $limit, $date ) : array();
639
+
640
+        // If limiting by IDs and no posts found, then return early since we have nothing to update.
641
+        if ( $limit_ids && 0 === count( $ids ) ) {
642
+            return 0;
643
+        }
644
+
645
+        /**
646
+         * Global wpdb object.
647
+         *
648
+         * @var wpdb $wpdb
649
+         */
650
+        global $wpdb;
651
+
652
+        /*
653 653
 		 * Build up custom query to update the affected posts. Parameters are built as a separate array
654 654
 		 * to make it easier to identify where they are in the query.
655 655
 		 *
656 656
 		 * We can't use $wpdb->update() here because of the "ID IN ..." clause.
657 657
 		 */
658
-		$update = "UPDATE {$wpdb->posts} SET post_password = %s, post_modified_gmt = %s, post_modified = %s";
659
-		$params = array(
660
-			$claim_id,
661
-			current_time( 'mysql', true ),
662
-			current_time( 'mysql' ),
663
-		);
664
-
665
-		// Build initial WHERE clause.
666
-		$where    = "WHERE post_type = %s AND post_status = %s AND post_password = ''";
667
-		$params[] = self::POST_TYPE;
668
-		$params[] = ActionScheduler_Store::STATUS_PENDING;
669
-
670
-		if ( ! empty( $hooks ) ) {
671
-			$placeholders = array_fill( 0, count( $hooks ), '%s' );
672
-			$where       .= ' AND post_title IN (' . join( ', ', $placeholders ) . ')';
673
-			$params       = array_merge( $params, array_values( $hooks ) );
674
-		}
675
-
676
-		/*
658
+        $update = "UPDATE {$wpdb->posts} SET post_password = %s, post_modified_gmt = %s, post_modified = %s";
659
+        $params = array(
660
+            $claim_id,
661
+            current_time( 'mysql', true ),
662
+            current_time( 'mysql' ),
663
+        );
664
+
665
+        // Build initial WHERE clause.
666
+        $where    = "WHERE post_type = %s AND post_status = %s AND post_password = ''";
667
+        $params[] = self::POST_TYPE;
668
+        $params[] = ActionScheduler_Store::STATUS_PENDING;
669
+
670
+        if ( ! empty( $hooks ) ) {
671
+            $placeholders = array_fill( 0, count( $hooks ), '%s' );
672
+            $where       .= ' AND post_title IN (' . join( ', ', $placeholders ) . ')';
673
+            $params       = array_merge( $params, array_values( $hooks ) );
674
+        }
675
+
676
+        /*
677 677
 		 * Add the IDs to the WHERE clause. IDs not escaped because they came directly from a prior DB query.
678 678
 		 *
679 679
 		 * If we're not limiting by IDs, then include the post_date_gmt clause.
680 680
 		 */
681
-		if ( $limit_ids ) {
682
-			$where .= ' AND ID IN (' . join( ',', $ids ) . ')';
683
-		} else {
684
-			$where   .= ' AND post_date_gmt <= %s';
685
-			$params[] = $date->format( 'Y-m-d H:i:s' );
686
-		}
687
-
688
-		// Add the ORDER BY clause and,ms limit.
689
-		$order    = 'ORDER BY menu_order ASC, post_date_gmt ASC, ID ASC LIMIT %d';
690
-		$params[] = $limit;
691
-
692
-		// Run the query and gather results.
693
-		$rows_affected = $wpdb->query( $wpdb->prepare( "{$update} {$where} {$order}", $params ) ); // phpcs:ignore // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
694
-
695
-		if ( false === $rows_affected ) {
696
-			throw new RuntimeException( __( 'Unable to claim actions. Database error.', 'action-scheduler' ) );
697
-		}
698
-
699
-		return (int) $rows_affected;
700
-	}
701
-
702
-	/**
703
-	 * Get IDs of actions within a certain group and up to a certain date/time.
704
-	 *
705
-	 * @param string   $group The group to use in finding actions.
706
-	 * @param int      $limit The number of actions to retrieve.
707
-	 * @param DateTime $date  DateTime object representing cutoff time for actions. Actions retrieved will be
708
-	 *                        up to and including this DateTime.
709
-	 *
710
-	 * @return array IDs of actions in the appropriate group and before the appropriate time.
711
-	 * @throws InvalidArgumentException When the group does not exist.
712
-	 */
713
-	protected function get_actions_by_group( $group, $limit, DateTime $date ) {
714
-		// Ensure the group exists before continuing.
715
-		if ( ! term_exists( $group, self::GROUP_TAXONOMY ) ) {
716
-			/* translators: %s is the group name */
717
-			throw new InvalidArgumentException( sprintf( __( 'The group "%s" does not exist.', 'action-scheduler' ), $group ) );
718
-		}
719
-
720
-		// Set up a query for post IDs to use later.
721
-		$query      = new WP_Query();
722
-		$query_args = array(
723
-			'fields'           => 'ids',
724
-			'post_type'        => self::POST_TYPE,
725
-			'post_status'      => ActionScheduler_Store::STATUS_PENDING,
726
-			'has_password'     => false,
727
-			'posts_per_page'   => $limit * 3,
728
-			'suppress_filters' => true,
729
-			'no_found_rows'    => true,
730
-			'orderby'          => array(
731
-				'menu_order' => 'ASC',
732
-				'date'       => 'ASC',
733
-				'ID'         => 'ASC',
734
-			),
735
-			'date_query'       => array(
736
-				'column'    => 'post_date_gmt',
737
-				'before'    => $date->format( 'Y-m-d H:i' ),
738
-				'inclusive' => true,
739
-			),
740
-			'tax_query'        => array( // phpcs:ignore WordPress.DB.SlowDBQuery
741
-				array(
742
-					'taxonomy'         => self::GROUP_TAXONOMY,
743
-					'field'            => 'slug',
744
-					'terms'            => $group,
745
-					'include_children' => false,
746
-				),
747
-			),
748
-		);
749
-
750
-		return $query->query( $query_args );
751
-	}
752
-
753
-	/**
754
-	 * Find actions by claim ID.
755
-	 *
756
-	 * @param string $claim_id Claim ID.
757
-	 * @return array
758
-	 */
759
-	public function find_actions_by_claim_id( $claim_id ) {
760
-		/**
761
-		 * Global wpdb object.
762
-		 *
763
-		 * @var wpdb $wpdb
764
-		 */
765
-		global $wpdb;
766
-
767
-		$action_ids  = array();
768
-		$before_date = isset( $this->claim_before_date ) ? $this->claim_before_date : as_get_datetime_object();
769
-		$cut_off     = $before_date->format( 'Y-m-d H:i:s' );
770
-
771
-		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
772
-		$results = $wpdb->get_results(
773
-			$wpdb->prepare(
774
-				"SELECT ID, post_date_gmt FROM {$wpdb->posts} WHERE post_type = %s AND post_password = %s",
775
-				array(
776
-					self::POST_TYPE,
777
-					$claim_id,
778
-				)
779
-			)
780
-		);
781
-
782
-		// Verify that the scheduled date for each action is within the expected bounds (in some unusual
783
-		// cases, we cannot depend on MySQL to honor all of the WHERE conditions we specify).
784
-		foreach ( $results as $claimed_action ) {
785
-			if ( $claimed_action->post_date_gmt <= $cut_off ) {
786
-				$action_ids[] = absint( $claimed_action->ID );
787
-			}
788
-		}
789
-
790
-		return $action_ids;
791
-	}
792
-
793
-	/**
794
-	 * Release claim.
795
-	 *
796
-	 * @param ActionScheduler_ActionClaim $claim Claim object to release.
797
-	 * @return void
798
-	 * @throws RuntimeException When the claim is not unlocked.
799
-	 */
800
-	public function release_claim( ActionScheduler_ActionClaim $claim ) {
801
-		$action_ids = $this->find_actions_by_claim_id( $claim->get_id() );
802
-		if ( empty( $action_ids ) ) {
803
-			return; // nothing to do.
804
-		}
805
-		$action_id_string = implode( ',', array_map( 'intval', $action_ids ) );
806
-		/**
807
-		 * Global wpdb object.
808
-		 *
809
-		 * @var wpdb $wpdb
810
-		 */
811
-		global $wpdb;
812
-
813
-		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
814
-		$result = $wpdb->query(
815
-			$wpdb->prepare(
816
-				"UPDATE {$wpdb->posts} SET post_password = '' WHERE ID IN ($action_id_string) AND post_password = %s", //phpcs:ignore
817
-				array(
818
-					$claim->get_id(),
819
-				)
820
-			)
821
-		);
822
-		if ( false === $result ) {
823
-			/* translators: %s: claim ID */
824
-			throw new RuntimeException( sprintf( __( 'Unable to unlock claim %s. Database error.', 'action-scheduler' ), $claim->get_id() ) );
825
-		}
826
-	}
827
-
828
-	/**
829
-	 * Unclaim action.
830
-	 *
831
-	 * @param string $action_id Action ID.
832
-	 * @throws RuntimeException When unable to unlock claim on action ID.
833
-	 */
834
-	public function unclaim_action( $action_id ) {
835
-		/**
836
-		 * Global wpdb object.
837
-		 *
838
-		 * @var wpdb $wpdb
839
-		 */
840
-		global $wpdb;
841
-
842
-		//phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
843
-		$result = $wpdb->query(
844
-			$wpdb->prepare(
845
-				"UPDATE {$wpdb->posts} SET post_password = '' WHERE ID = %d AND post_type = %s",
846
-				$action_id,
847
-				self::POST_TYPE
848
-			)
849
-		);
850
-		if ( false === $result ) {
851
-			/* translators: %s: action ID */
852
-			throw new RuntimeException( sprintf( __( 'Unable to unlock claim on action %s. Database error.', 'action-scheduler' ), $action_id ) );
853
-		}
854
-	}
855
-
856
-	/**
857
-	 * Mark failure on action.
858
-	 *
859
-	 * @param int $action_id Action ID.
860
-	 *
861
-	 * @return void
862
-	 * @throws RuntimeException When unable to mark failure on action ID.
863
-	 */
864
-	public function mark_failure( $action_id ) {
865
-		/**
866
-		 * Global wpdb object.
867
-		 *
868
-		 * @var wpdb $wpdb
869
-		 */
870
-		global $wpdb;
871
-
872
-		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
873
-		$result = $wpdb->query(
874
-			$wpdb->prepare( "UPDATE {$wpdb->posts} SET post_status = %s WHERE ID = %d AND post_type = %s", self::STATUS_FAILED, $action_id, self::POST_TYPE )
875
-		);
876
-		if ( false === $result ) {
877
-			/* translators: %s: action ID */
878
-			throw new RuntimeException( sprintf( __( 'Unable to mark failure on action %s. Database error.', 'action-scheduler' ), $action_id ) );
879
-		}
880
-	}
881
-
882
-	/**
883
-	 * Return an action's claim ID, as stored in the post password column
884
-	 *
885
-	 * @param int $action_id Action ID.
886
-	 * @return mixed
887
-	 */
888
-	public function get_claim_id( $action_id ) {
889
-		return $this->get_post_column( $action_id, 'post_password' );
890
-	}
891
-
892
-	/**
893
-	 * Return an action's status, as stored in the post status column
894
-	 *
895
-	 * @param int $action_id Action ID.
896
-	 *
897
-	 * @return mixed
898
-	 * @throws InvalidArgumentException When the action ID is invalid.
899
-	 */
900
-	public function get_status( $action_id ) {
901
-		$status = $this->get_post_column( $action_id, 'post_status' );
902
-
903
-		if ( null === $status ) {
904
-			throw new InvalidArgumentException( __( 'Invalid action ID. No status found.', 'action-scheduler' ) );
905
-		}
906
-
907
-		return $this->get_action_status_by_post_status( $status );
908
-	}
909
-
910
-	/**
911
-	 * Get post column
912
-	 *
913
-	 * @param string $action_id Action ID.
914
-	 * @param string $column_name Column Name.
915
-	 *
916
-	 * @return string|null
917
-	 */
918
-	private function get_post_column( $action_id, $column_name ) {
919
-		/**
920
-		 * Global wpdb object.
921
-		 *
922
-		 * @var wpdb $wpdb
923
-		 */
924
-		global $wpdb;
925
-
926
-		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
927
-		return $wpdb->get_var(
928
-			$wpdb->prepare(
929
-				"SELECT {$column_name} FROM {$wpdb->posts} WHERE ID=%d AND post_type=%s", // phpcs:ignore
930
-				$action_id,
931
-				self::POST_TYPE
932
-			)
933
-		);
934
-	}
935
-
936
-	/**
937
-	 * Log Execution.
938
-	 *
939
-	 * @param string $action_id Action ID.
940
-	 */
941
-	public function log_execution( $action_id ) {
942
-		/**
943
-		 * Global wpdb object.
944
-		 *
945
-		 * @var wpdb $wpdb
946
-		 */
947
-		global $wpdb;
948
-
949
-		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
950
-		$wpdb->query(
951
-			$wpdb->prepare(
952
-				"UPDATE {$wpdb->posts} SET menu_order = menu_order+1, post_status=%s, post_modified_gmt = %s, post_modified = %s WHERE ID = %d AND post_type = %s",
953
-				self::STATUS_RUNNING,
954
-				current_time( 'mysql', true ),
955
-				current_time( 'mysql' ),
956
-				$action_id,
957
-				self::POST_TYPE
958
-			)
959
-		);
960
-	}
961
-
962
-	/**
963
-	 * Record that an action was completed.
964
-	 *
965
-	 * @param string $action_id ID of the completed action.
966
-	 *
967
-	 * @throws InvalidArgumentException When the action ID is invalid.
968
-	 * @throws RuntimeException         When there was an error executing the action.
969
-	 */
970
-	public function mark_complete( $action_id ) {
971
-		$post = get_post( $action_id );
972
-		if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
973
-			/* translators: %s is the action ID */
974
-			throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
975
-		}
976
-		add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 );
977
-		add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
978
-		$result = wp_update_post(
979
-			array(
980
-				'ID'          => $action_id,
981
-				'post_status' => 'publish',
982
-			),
983
-			true
984
-		);
985
-		remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
986
-		remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
987
-		if ( is_wp_error( $result ) ) {
988
-			throw new RuntimeException( $result->get_error_message() );
989
-		}
990
-
991
-		/**
992
-		 * Fires after a scheduled action has been completed.
993
-		 *
994
-		 * @since 3.4.2
995
-		 *
996
-		 * @param int $action_id Action ID.
997
-		 */
998
-		do_action( 'action_scheduler_completed_action', $action_id );
999
-	}
1000
-
1001
-	/**
1002
-	 * Mark action as migrated when there is an error deleting the action.
1003
-	 *
1004
-	 * @param int $action_id Action ID.
1005
-	 */
1006
-	public function mark_migrated( $action_id ) {
1007
-		wp_update_post(
1008
-			array(
1009
-				'ID'          => $action_id,
1010
-				'post_status' => 'migrated',
1011
-			)
1012
-		);
1013
-	}
1014
-
1015
-	/**
1016
-	 * Determine whether the post store can be migrated.
1017
-	 *
1018
-	 * @param [type] $setting - Setting value.
1019
-	 * @return bool
1020
-	 */
1021
-	public function migration_dependencies_met( $setting ) {
1022
-		global $wpdb;
1023
-
1024
-		$dependencies_met = get_transient( self::DEPENDENCIES_MET );
1025
-		if ( empty( $dependencies_met ) ) {
1026
-			$maximum_args_length = apply_filters( 'action_scheduler_maximum_args_length', 191 );
1027
-			$found_action        = $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1028
-				$wpdb->prepare(
1029
-					"SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND CHAR_LENGTH(post_content) > %d LIMIT 1",
1030
-					$maximum_args_length,
1031
-					self::POST_TYPE
1032
-				)
1033
-			);
1034
-			$dependencies_met    = $found_action ? 'no' : 'yes';
1035
-			set_transient( self::DEPENDENCIES_MET, $dependencies_met, DAY_IN_SECONDS );
1036
-		}
1037
-
1038
-		return 'yes' === $dependencies_met ? $setting : false;
1039
-	}
1040
-
1041
-	/**
1042
-	 * InnoDB indexes have a maximum size of 767 bytes by default, which is only 191 characters with utf8mb4.
1043
-	 *
1044
-	 * Previously, AS wasn't concerned about args length, as we used the (unindex) post_content column. However,
1045
-	 * as we prepare to move to custom tables, and can use an indexed VARCHAR column instead, we want to warn
1046
-	 * developers of this impending requirement.
1047
-	 *
1048
-	 * @param ActionScheduler_Action $action Action object.
1049
-	 */
1050
-	protected function validate_action( ActionScheduler_Action $action ) {
1051
-		try {
1052
-			parent::validate_action( $action );
1053
-		} catch ( Exception $e ) {
1054
-			/* translators: %s is the error message */
1055
-			$message = sprintf( __( '%s Support for strings longer than this will be removed in a future version.', 'action-scheduler' ), $e->getMessage() );
1056
-			_doing_it_wrong( 'ActionScheduler_Action::$args', esc_html( $message ), '2.1.0' );
1057
-		}
1058
-	}
1059
-
1060
-	/**
1061
-	 * (@codeCoverageIgnore)
1062
-	 */
1063
-	public function init() {
1064
-		add_filter( 'action_scheduler_migration_dependencies_met', array( $this, 'migration_dependencies_met' ) );
1065
-
1066
-		$post_type_registrar = new ActionScheduler_wpPostStore_PostTypeRegistrar();
1067
-		$post_type_registrar->register();
1068
-
1069
-		$post_status_registrar = new ActionScheduler_wpPostStore_PostStatusRegistrar();
1070
-		$post_status_registrar->register();
1071
-
1072
-		$taxonomy_registrar = new ActionScheduler_wpPostStore_TaxonomyRegistrar();
1073
-		$taxonomy_registrar->register();
1074
-	}
681
+        if ( $limit_ids ) {
682
+            $where .= ' AND ID IN (' . join( ',', $ids ) . ')';
683
+        } else {
684
+            $where   .= ' AND post_date_gmt <= %s';
685
+            $params[] = $date->format( 'Y-m-d H:i:s' );
686
+        }
687
+
688
+        // Add the ORDER BY clause and,ms limit.
689
+        $order    = 'ORDER BY menu_order ASC, post_date_gmt ASC, ID ASC LIMIT %d';
690
+        $params[] = $limit;
691
+
692
+        // Run the query and gather results.
693
+        $rows_affected = $wpdb->query( $wpdb->prepare( "{$update} {$where} {$order}", $params ) ); // phpcs:ignore // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
694
+
695
+        if ( false === $rows_affected ) {
696
+            throw new RuntimeException( __( 'Unable to claim actions. Database error.', 'action-scheduler' ) );
697
+        }
698
+
699
+        return (int) $rows_affected;
700
+    }
701
+
702
+    /**
703
+     * Get IDs of actions within a certain group and up to a certain date/time.
704
+     *
705
+     * @param string   $group The group to use in finding actions.
706
+     * @param int      $limit The number of actions to retrieve.
707
+     * @param DateTime $date  DateTime object representing cutoff time for actions. Actions retrieved will be
708
+     *                        up to and including this DateTime.
709
+     *
710
+     * @return array IDs of actions in the appropriate group and before the appropriate time.
711
+     * @throws InvalidArgumentException When the group does not exist.
712
+     */
713
+    protected function get_actions_by_group( $group, $limit, DateTime $date ) {
714
+        // Ensure the group exists before continuing.
715
+        if ( ! term_exists( $group, self::GROUP_TAXONOMY ) ) {
716
+            /* translators: %s is the group name */
717
+            throw new InvalidArgumentException( sprintf( __( 'The group "%s" does not exist.', 'action-scheduler' ), $group ) );
718
+        }
719
+
720
+        // Set up a query for post IDs to use later.
721
+        $query      = new WP_Query();
722
+        $query_args = array(
723
+            'fields'           => 'ids',
724
+            'post_type'        => self::POST_TYPE,
725
+            'post_status'      => ActionScheduler_Store::STATUS_PENDING,
726
+            'has_password'     => false,
727
+            'posts_per_page'   => $limit * 3,
728
+            'suppress_filters' => true,
729
+            'no_found_rows'    => true,
730
+            'orderby'          => array(
731
+                'menu_order' => 'ASC',
732
+                'date'       => 'ASC',
733
+                'ID'         => 'ASC',
734
+            ),
735
+            'date_query'       => array(
736
+                'column'    => 'post_date_gmt',
737
+                'before'    => $date->format( 'Y-m-d H:i' ),
738
+                'inclusive' => true,
739
+            ),
740
+            'tax_query'        => array( // phpcs:ignore WordPress.DB.SlowDBQuery
741
+                array(
742
+                    'taxonomy'         => self::GROUP_TAXONOMY,
743
+                    'field'            => 'slug',
744
+                    'terms'            => $group,
745
+                    'include_children' => false,
746
+                ),
747
+            ),
748
+        );
749
+
750
+        return $query->query( $query_args );
751
+    }
752
+
753
+    /**
754
+     * Find actions by claim ID.
755
+     *
756
+     * @param string $claim_id Claim ID.
757
+     * @return array
758
+     */
759
+    public function find_actions_by_claim_id( $claim_id ) {
760
+        /**
761
+         * Global wpdb object.
762
+         *
763
+         * @var wpdb $wpdb
764
+         */
765
+        global $wpdb;
766
+
767
+        $action_ids  = array();
768
+        $before_date = isset( $this->claim_before_date ) ? $this->claim_before_date : as_get_datetime_object();
769
+        $cut_off     = $before_date->format( 'Y-m-d H:i:s' );
770
+
771
+        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
772
+        $results = $wpdb->get_results(
773
+            $wpdb->prepare(
774
+                "SELECT ID, post_date_gmt FROM {$wpdb->posts} WHERE post_type = %s AND post_password = %s",
775
+                array(
776
+                    self::POST_TYPE,
777
+                    $claim_id,
778
+                )
779
+            )
780
+        );
781
+
782
+        // Verify that the scheduled date for each action is within the expected bounds (in some unusual
783
+        // cases, we cannot depend on MySQL to honor all of the WHERE conditions we specify).
784
+        foreach ( $results as $claimed_action ) {
785
+            if ( $claimed_action->post_date_gmt <= $cut_off ) {
786
+                $action_ids[] = absint( $claimed_action->ID );
787
+            }
788
+        }
789
+
790
+        return $action_ids;
791
+    }
792
+
793
+    /**
794
+     * Release claim.
795
+     *
796
+     * @param ActionScheduler_ActionClaim $claim Claim object to release.
797
+     * @return void
798
+     * @throws RuntimeException When the claim is not unlocked.
799
+     */
800
+    public function release_claim( ActionScheduler_ActionClaim $claim ) {
801
+        $action_ids = $this->find_actions_by_claim_id( $claim->get_id() );
802
+        if ( empty( $action_ids ) ) {
803
+            return; // nothing to do.
804
+        }
805
+        $action_id_string = implode( ',', array_map( 'intval', $action_ids ) );
806
+        /**
807
+         * Global wpdb object.
808
+         *
809
+         * @var wpdb $wpdb
810
+         */
811
+        global $wpdb;
812
+
813
+        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
814
+        $result = $wpdb->query(
815
+            $wpdb->prepare(
816
+                "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID IN ($action_id_string) AND post_password = %s", //phpcs:ignore
817
+                array(
818
+                    $claim->get_id(),
819
+                )
820
+            )
821
+        );
822
+        if ( false === $result ) {
823
+            /* translators: %s: claim ID */
824
+            throw new RuntimeException( sprintf( __( 'Unable to unlock claim %s. Database error.', 'action-scheduler' ), $claim->get_id() ) );
825
+        }
826
+    }
827
+
828
+    /**
829
+     * Unclaim action.
830
+     *
831
+     * @param string $action_id Action ID.
832
+     * @throws RuntimeException When unable to unlock claim on action ID.
833
+     */
834
+    public function unclaim_action( $action_id ) {
835
+        /**
836
+         * Global wpdb object.
837
+         *
838
+         * @var wpdb $wpdb
839
+         */
840
+        global $wpdb;
841
+
842
+        //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
843
+        $result = $wpdb->query(
844
+            $wpdb->prepare(
845
+                "UPDATE {$wpdb->posts} SET post_password = '' WHERE ID = %d AND post_type = %s",
846
+                $action_id,
847
+                self::POST_TYPE
848
+            )
849
+        );
850
+        if ( false === $result ) {
851
+            /* translators: %s: action ID */
852
+            throw new RuntimeException( sprintf( __( 'Unable to unlock claim on action %s. Database error.', 'action-scheduler' ), $action_id ) );
853
+        }
854
+    }
855
+
856
+    /**
857
+     * Mark failure on action.
858
+     *
859
+     * @param int $action_id Action ID.
860
+     *
861
+     * @return void
862
+     * @throws RuntimeException When unable to mark failure on action ID.
863
+     */
864
+    public function mark_failure( $action_id ) {
865
+        /**
866
+         * Global wpdb object.
867
+         *
868
+         * @var wpdb $wpdb
869
+         */
870
+        global $wpdb;
871
+
872
+        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
873
+        $result = $wpdb->query(
874
+            $wpdb->prepare( "UPDATE {$wpdb->posts} SET post_status = %s WHERE ID = %d AND post_type = %s", self::STATUS_FAILED, $action_id, self::POST_TYPE )
875
+        );
876
+        if ( false === $result ) {
877
+            /* translators: %s: action ID */
878
+            throw new RuntimeException( sprintf( __( 'Unable to mark failure on action %s. Database error.', 'action-scheduler' ), $action_id ) );
879
+        }
880
+    }
881
+
882
+    /**
883
+     * Return an action's claim ID, as stored in the post password column
884
+     *
885
+     * @param int $action_id Action ID.
886
+     * @return mixed
887
+     */
888
+    public function get_claim_id( $action_id ) {
889
+        return $this->get_post_column( $action_id, 'post_password' );
890
+    }
891
+
892
+    /**
893
+     * Return an action's status, as stored in the post status column
894
+     *
895
+     * @param int $action_id Action ID.
896
+     *
897
+     * @return mixed
898
+     * @throws InvalidArgumentException When the action ID is invalid.
899
+     */
900
+    public function get_status( $action_id ) {
901
+        $status = $this->get_post_column( $action_id, 'post_status' );
902
+
903
+        if ( null === $status ) {
904
+            throw new InvalidArgumentException( __( 'Invalid action ID. No status found.', 'action-scheduler' ) );
905
+        }
906
+
907
+        return $this->get_action_status_by_post_status( $status );
908
+    }
909
+
910
+    /**
911
+     * Get post column
912
+     *
913
+     * @param string $action_id Action ID.
914
+     * @param string $column_name Column Name.
915
+     *
916
+     * @return string|null
917
+     */
918
+    private function get_post_column( $action_id, $column_name ) {
919
+        /**
920
+         * Global wpdb object.
921
+         *
922
+         * @var wpdb $wpdb
923
+         */
924
+        global $wpdb;
925
+
926
+        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
927
+        return $wpdb->get_var(
928
+            $wpdb->prepare(
929
+                "SELECT {$column_name} FROM {$wpdb->posts} WHERE ID=%d AND post_type=%s", // phpcs:ignore
930
+                $action_id,
931
+                self::POST_TYPE
932
+            )
933
+        );
934
+    }
935
+
936
+    /**
937
+     * Log Execution.
938
+     *
939
+     * @param string $action_id Action ID.
940
+     */
941
+    public function log_execution( $action_id ) {
942
+        /**
943
+         * Global wpdb object.
944
+         *
945
+         * @var wpdb $wpdb
946
+         */
947
+        global $wpdb;
948
+
949
+        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
950
+        $wpdb->query(
951
+            $wpdb->prepare(
952
+                "UPDATE {$wpdb->posts} SET menu_order = menu_order+1, post_status=%s, post_modified_gmt = %s, post_modified = %s WHERE ID = %d AND post_type = %s",
953
+                self::STATUS_RUNNING,
954
+                current_time( 'mysql', true ),
955
+                current_time( 'mysql' ),
956
+                $action_id,
957
+                self::POST_TYPE
958
+            )
959
+        );
960
+    }
961
+
962
+    /**
963
+     * Record that an action was completed.
964
+     *
965
+     * @param string $action_id ID of the completed action.
966
+     *
967
+     * @throws InvalidArgumentException When the action ID is invalid.
968
+     * @throws RuntimeException         When there was an error executing the action.
969
+     */
970
+    public function mark_complete( $action_id ) {
971
+        $post = get_post( $action_id );
972
+        if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
973
+            /* translators: %s is the action ID */
974
+            throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
975
+        }
976
+        add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 );
977
+        add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
978
+        $result = wp_update_post(
979
+            array(
980
+                'ID'          => $action_id,
981
+                'post_status' => 'publish',
982
+            ),
983
+            true
984
+        );
985
+        remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
986
+        remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
987
+        if ( is_wp_error( $result ) ) {
988
+            throw new RuntimeException( $result->get_error_message() );
989
+        }
990
+
991
+        /**
992
+         * Fires after a scheduled action has been completed.
993
+         *
994
+         * @since 3.4.2
995
+         *
996
+         * @param int $action_id Action ID.
997
+         */
998
+        do_action( 'action_scheduler_completed_action', $action_id );
999
+    }
1000
+
1001
+    /**
1002
+     * Mark action as migrated when there is an error deleting the action.
1003
+     *
1004
+     * @param int $action_id Action ID.
1005
+     */
1006
+    public function mark_migrated( $action_id ) {
1007
+        wp_update_post(
1008
+            array(
1009
+                'ID'          => $action_id,
1010
+                'post_status' => 'migrated',
1011
+            )
1012
+        );
1013
+    }
1014
+
1015
+    /**
1016
+     * Determine whether the post store can be migrated.
1017
+     *
1018
+     * @param [type] $setting - Setting value.
1019
+     * @return bool
1020
+     */
1021
+    public function migration_dependencies_met( $setting ) {
1022
+        global $wpdb;
1023
+
1024
+        $dependencies_met = get_transient( self::DEPENDENCIES_MET );
1025
+        if ( empty( $dependencies_met ) ) {
1026
+            $maximum_args_length = apply_filters( 'action_scheduler_maximum_args_length', 191 );
1027
+            $found_action        = $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1028
+                $wpdb->prepare(
1029
+                    "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND CHAR_LENGTH(post_content) > %d LIMIT 1",
1030
+                    $maximum_args_length,
1031
+                    self::POST_TYPE
1032
+                )
1033
+            );
1034
+            $dependencies_met    = $found_action ? 'no' : 'yes';
1035
+            set_transient( self::DEPENDENCIES_MET, $dependencies_met, DAY_IN_SECONDS );
1036
+        }
1037
+
1038
+        return 'yes' === $dependencies_met ? $setting : false;
1039
+    }
1040
+
1041
+    /**
1042
+     * InnoDB indexes have a maximum size of 767 bytes by default, which is only 191 characters with utf8mb4.
1043
+     *
1044
+     * Previously, AS wasn't concerned about args length, as we used the (unindex) post_content column. However,
1045
+     * as we prepare to move to custom tables, and can use an indexed VARCHAR column instead, we want to warn
1046
+     * developers of this impending requirement.
1047
+     *
1048
+     * @param ActionScheduler_Action $action Action object.
1049
+     */
1050
+    protected function validate_action( ActionScheduler_Action $action ) {
1051
+        try {
1052
+            parent::validate_action( $action );
1053
+        } catch ( Exception $e ) {
1054
+            /* translators: %s is the error message */
1055
+            $message = sprintf( __( '%s Support for strings longer than this will be removed in a future version.', 'action-scheduler' ), $e->getMessage() );
1056
+            _doing_it_wrong( 'ActionScheduler_Action::$args', esc_html( $message ), '2.1.0' );
1057
+        }
1058
+    }
1059
+
1060
+    /**
1061
+     * (@codeCoverageIgnore)
1062
+     */
1063
+    public function init() {
1064
+        add_filter( 'action_scheduler_migration_dependencies_met', array( $this, 'migration_dependencies_met' ) );
1065
+
1066
+        $post_type_registrar = new ActionScheduler_wpPostStore_PostTypeRegistrar();
1067
+        $post_type_registrar->register();
1068
+
1069
+        $post_status_registrar = new ActionScheduler_wpPostStore_PostStatusRegistrar();
1070
+        $post_status_registrar->register();
1071
+
1072
+        $taxonomy_registrar = new ActionScheduler_wpPostStore_TaxonomyRegistrar();
1073
+        $taxonomy_registrar->register();
1074
+    }
1075 1075
 }
Please login to merge, or discard this patch.
Spacing   +210 added lines, -210 removed lines patch added patch discarded remove patch
@@ -35,18 +35,18 @@  discard block
 block discarded – undo
35 35
 	 * @throws RuntimeException Throws an exception if the action could not be saved.
36 36
 	 * @return int
37 37
 	 */
38
-	public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = null ) {
38
+	public function save_action(ActionScheduler_Action $action, DateTime $scheduled_date = null) {
39 39
 		try {
40
-			$this->validate_action( $action );
41
-			$post_array = $this->create_post_array( $action, $scheduled_date );
42
-			$post_id    = $this->save_post_array( $post_array );
43
-			$this->save_post_schedule( $post_id, $action->get_schedule() );
44
-			$this->save_action_group( $post_id, $action->get_group() );
45
-			do_action( 'action_scheduler_stored_action', $post_id );
40
+			$this->validate_action($action);
41
+			$post_array = $this->create_post_array($action, $scheduled_date);
42
+			$post_id    = $this->save_post_array($post_array);
43
+			$this->save_post_schedule($post_id, $action->get_schedule());
44
+			$this->save_action_group($post_id, $action->get_group());
45
+			do_action('action_scheduler_stored_action', $post_id);
46 46
 			return $post_id;
47
-		} catch ( Exception $e ) {
47
+		} catch (Exception $e) {
48 48
 			/* translators: %s: action error message */
49
-			throw new RuntimeException( sprintf( __( 'Error saving action: %s', 'action-scheduler' ), $e->getMessage() ), 0 );
49
+			throw new RuntimeException(sprintf(__('Error saving action: %s', 'action-scheduler'), $e->getMessage()), 0);
50 50
 		}
51 51
 	}
52 52
 
@@ -58,14 +58,14 @@  discard block
 block discarded – undo
58 58
 	 *
59 59
 	 * @return array Returns an array of post data.
60 60
 	 */
61
-	protected function create_post_array( ActionScheduler_Action $action, DateTime $scheduled_date = null ) {
61
+	protected function create_post_array(ActionScheduler_Action $action, DateTime $scheduled_date = null) {
62 62
 		$post = array(
63 63
 			'post_type'     => self::POST_TYPE,
64 64
 			'post_title'    => $action->get_hook(),
65
-			'post_content'  => wp_json_encode( $action->get_args() ),
66
-			'post_status'   => ( $action->is_finished() ? 'publish' : 'pending' ),
67
-			'post_date_gmt' => $this->get_scheduled_date_string( $action, $scheduled_date ),
68
-			'post_date'     => $this->get_scheduled_date_string_local( $action, $scheduled_date ),
65
+			'post_content'  => wp_json_encode($action->get_args()),
66
+			'post_status'   => ($action->is_finished() ? 'publish' : 'pending'),
67
+			'post_date_gmt' => $this->get_scheduled_date_string($action, $scheduled_date),
68
+			'post_date'     => $this->get_scheduled_date_string_local($action, $scheduled_date),
69 69
 		);
70 70
 		return $post;
71 71
 	}
@@ -77,28 +77,28 @@  discard block
 block discarded – undo
77 77
 	 * @return int Returns the post ID.
78 78
 	 * @throws RuntimeException Throws an exception if the action could not be saved.
79 79
 	 */
80
-	protected function save_post_array( $post_array ) {
81
-		add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 );
82
-		add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
80
+	protected function save_post_array($post_array) {
81
+		add_filter('wp_insert_post_data', array($this, 'filter_insert_post_data'), 10, 1);
82
+		add_filter('pre_wp_unique_post_slug', array($this, 'set_unique_post_slug'), 10, 5);
83 83
 
84
-		$has_kses = false !== has_filter( 'content_save_pre', 'wp_filter_post_kses' );
84
+		$has_kses = false !== has_filter('content_save_pre', 'wp_filter_post_kses');
85 85
 
86
-		if ( $has_kses ) {
86
+		if ($has_kses) {
87 87
 			// Prevent KSES from corrupting JSON in post_content.
88 88
 			kses_remove_filters();
89 89
 		}
90 90
 
91
-		$post_id = wp_insert_post( $post_array );
91
+		$post_id = wp_insert_post($post_array);
92 92
 
93
-		if ( $has_kses ) {
93
+		if ($has_kses) {
94 94
 			kses_init_filters();
95 95
 		}
96 96
 
97
-		remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
98
-		remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
97
+		remove_filter('wp_insert_post_data', array($this, 'filter_insert_post_data'), 10);
98
+		remove_filter('pre_wp_unique_post_slug', array($this, 'set_unique_post_slug'), 10);
99 99
 
100
-		if ( is_wp_error( $post_id ) || empty( $post_id ) ) {
101
-			throw new RuntimeException( __( 'Unable to save action.', 'action-scheduler' ) );
100
+		if (is_wp_error($post_id) || empty($post_id)) {
101
+			throw new RuntimeException(__('Unable to save action.', 'action-scheduler'));
102 102
 		}
103 103
 		return $post_id;
104 104
 	}
@@ -110,10 +110,10 @@  discard block
 block discarded – undo
110 110
 	 *
111 111
 	 * @return array
112 112
 	 */
113
-	public function filter_insert_post_data( $postdata ) {
114
-		if ( self::POST_TYPE === $postdata['post_type'] ) {
113
+	public function filter_insert_post_data($postdata) {
114
+		if (self::POST_TYPE === $postdata['post_type']) {
115 115
 			$postdata['post_author'] = 0;
116
-			if ( 'future' === $postdata['post_status'] ) {
116
+			if ('future' === $postdata['post_status']) {
117 117
 				$postdata['post_status'] = 'publish';
118 118
 			}
119 119
 		}
@@ -148,9 +148,9 @@  discard block
 block discarded – undo
148 148
 	 * @param string $post_type     Post type.
149 149
 	 * @return string
150 150
 	 */
151
-	public function set_unique_post_slug( $override_slug, $slug, $post_ID, $post_status, $post_type ) {
152
-		if ( self::POST_TYPE === $post_type ) {
153
-			$override_slug = uniqid( self::POST_TYPE . '-', true ) . '-' . wp_generate_password( 32, false );
151
+	public function set_unique_post_slug($override_slug, $slug, $post_ID, $post_status, $post_type) {
152
+		if (self::POST_TYPE === $post_type) {
153
+			$override_slug = uniqid(self::POST_TYPE.'-', true).'-'.wp_generate_password(32, false);
154 154
 		}
155 155
 		return $override_slug;
156 156
 	}
@@ -163,8 +163,8 @@  discard block
 block discarded – undo
163 163
 	 *
164 164
 	 * @return void
165 165
 	 */
166
-	protected function save_post_schedule( $post_id, $schedule ) {
167
-		update_post_meta( $post_id, self::SCHEDULE_META_KEY, $schedule );
166
+	protected function save_post_schedule($post_id, $schedule) {
167
+		update_post_meta($post_id, self::SCHEDULE_META_KEY, $schedule);
168 168
 	}
169 169
 
170 170
 	/**
@@ -174,11 +174,11 @@  discard block
 block discarded – undo
174 174
 	 * @param string $group   Group to save.
175 175
 	 * @return void
176 176
 	 */
177
-	protected function save_action_group( $post_id, $group ) {
178
-		if ( empty( $group ) ) {
179
-			wp_set_object_terms( $post_id, array(), self::GROUP_TAXONOMY, false );
177
+	protected function save_action_group($post_id, $group) {
178
+		if (empty($group)) {
179
+			wp_set_object_terms($post_id, array(), self::GROUP_TAXONOMY, false);
180 180
 		} else {
181
-			wp_set_object_terms( $post_id, array( $group ), self::GROUP_TAXONOMY, false );
181
+			wp_set_object_terms($post_id, array($group), self::GROUP_TAXONOMY, false);
182 182
 		}
183 183
 	}
184 184
 
@@ -188,16 +188,16 @@  discard block
 block discarded – undo
188 188
 	 * @param int $action_id Action ID.
189 189
 	 * @return object
190 190
 	 */
191
-	public function fetch_action( $action_id ) {
192
-		$post = $this->get_post( $action_id );
193
-		if ( empty( $post ) || self::POST_TYPE !== $post->post_type ) {
191
+	public function fetch_action($action_id) {
192
+		$post = $this->get_post($action_id);
193
+		if (empty($post) || self::POST_TYPE !== $post->post_type) {
194 194
 			return $this->get_null_action();
195 195
 		}
196 196
 
197 197
 		try {
198
-			$action = $this->make_action_from_post( $post );
199
-		} catch ( ActionScheduler_InvalidActionException $exception ) {
200
-			do_action( 'action_scheduler_failed_fetch_action', $post->ID, $exception );
198
+			$action = $this->make_action_from_post($post);
199
+		} catch (ActionScheduler_InvalidActionException $exception) {
200
+			do_action('action_scheduler_failed_fetch_action', $post->ID, $exception);
201 201
 			return $this->get_null_action();
202 202
 		}
203 203
 
@@ -210,11 +210,11 @@  discard block
 block discarded – undo
210 210
 	 * @param string $action_id - Action ID.
211 211
 	 * @return WP_Post|null
212 212
 	 */
213
-	protected function get_post( $action_id ) {
214
-		if ( empty( $action_id ) ) {
213
+	protected function get_post($action_id) {
214
+		if (empty($action_id)) {
215 215
 			return null;
216 216
 		}
217
-		return get_post( $action_id );
217
+		return get_post($action_id);
218 218
 	}
219 219
 
220 220
 	/**
@@ -232,19 +232,19 @@  discard block
 block discarded – undo
232 232
 	 * @param WP_Post $post Post object.
233 233
 	 * @return WP_Post
234 234
 	 */
235
-	protected function make_action_from_post( $post ) {
235
+	protected function make_action_from_post($post) {
236 236
 		$hook = $post->post_title;
237 237
 
238
-		$args = json_decode( $post->post_content, true );
239
-		$this->validate_args( $args, $post->ID );
238
+		$args = json_decode($post->post_content, true);
239
+		$this->validate_args($args, $post->ID);
240 240
 
241
-		$schedule = get_post_meta( $post->ID, self::SCHEDULE_META_KEY, true );
242
-		$this->validate_schedule( $schedule, $post->ID );
241
+		$schedule = get_post_meta($post->ID, self::SCHEDULE_META_KEY, true);
242
+		$this->validate_schedule($schedule, $post->ID);
243 243
 
244
-		$group = wp_get_object_terms( $post->ID, self::GROUP_TAXONOMY, array( 'fields' => 'names' ) );
245
-		$group = empty( $group ) ? '' : reset( $group );
244
+		$group = wp_get_object_terms($post->ID, self::GROUP_TAXONOMY, array('fields' => 'names'));
245
+		$group = empty($group) ? '' : reset($group);
246 246
 
247
-		return ActionScheduler::factory()->get_stored_action( $this->get_action_status_by_post_status( $post->post_status ), $hook, $args, $schedule, $group );
247
+		return ActionScheduler::factory()->get_stored_action($this->get_action_status_by_post_status($post->post_status), $hook, $args, $schedule, $group);
248 248
 	}
249 249
 
250 250
 	/**
@@ -255,9 +255,9 @@  discard block
 block discarded – undo
255 255
 	 * @throws InvalidArgumentException Throw InvalidArgumentException if $post_status not in known status fields returned by $this->get_status_labels().
256 256
 	 * @return string
257 257
 	 */
258
-	protected function get_action_status_by_post_status( $post_status ) {
258
+	protected function get_action_status_by_post_status($post_status) {
259 259
 
260
-		switch ( $post_status ) {
260
+		switch ($post_status) {
261 261
 			case 'publish':
262 262
 				$action_status = self::STATUS_COMPLETE;
263 263
 				break;
@@ -265,8 +265,8 @@  discard block
 block discarded – undo
265 265
 				$action_status = self::STATUS_CANCELED;
266 266
 				break;
267 267
 			default:
268
-				if ( ! array_key_exists( $post_status, $this->get_status_labels() ) ) {
269
-					throw new InvalidArgumentException( sprintf( 'Invalid post status: "%s". No matching action status available.', $post_status ) );
268
+				if ( ! array_key_exists($post_status, $this->get_status_labels())) {
269
+					throw new InvalidArgumentException(sprintf('Invalid post status: "%s". No matching action status available.', $post_status));
270 270
 				}
271 271
 				$action_status = $post_status;
272 272
 				break;
@@ -283,9 +283,9 @@  discard block
 block discarded – undo
283 283
 	 * @throws InvalidArgumentException Throws InvalidArgumentException if $post_status not in known status fields returned by $this->get_status_labels().
284 284
 	 * @return string
285 285
 	 */
286
-	protected function get_post_status_by_action_status( $action_status ) {
286
+	protected function get_post_status_by_action_status($action_status) {
287 287
 
288
-		switch ( $action_status ) {
288
+		switch ($action_status) {
289 289
 			case self::STATUS_COMPLETE:
290 290
 				$post_status = 'publish';
291 291
 				break;
@@ -293,8 +293,8 @@  discard block
 block discarded – undo
293 293
 				$post_status = 'trash';
294 294
 				break;
295 295
 			default:
296
-				if ( ! array_key_exists( $action_status, $this->get_status_labels() ) ) {
297
-					throw new InvalidArgumentException( sprintf( 'Invalid action status: "%s".', $action_status ) );
296
+				if ( ! array_key_exists($action_status, $this->get_status_labels())) {
297
+					throw new InvalidArgumentException(sprintf('Invalid action status: "%s".', $action_status));
298 298
 				}
299 299
 				$post_status = $action_status;
300 300
 				break;
@@ -312,10 +312,10 @@  discard block
 block discarded – undo
312 312
 	 * @throws InvalidArgumentException - Throw InvalidArgumentException if $select_or_count not count or select.
313 313
 	 * @return string SQL statement. The returned SQL is already properly escaped.
314 314
 	 */
315
-	protected function get_query_actions_sql( array $query, $select_or_count = 'select' ) {
315
+	protected function get_query_actions_sql(array $query, $select_or_count = 'select') {
316 316
 
317
-		if ( ! in_array( $select_or_count, array( 'select', 'count' ), true ) ) {
318
-			throw new InvalidArgumentException( __( 'Invalid schedule. Cannot save action.', 'action-scheduler' ) );
317
+		if ( ! in_array($select_or_count, array('select', 'count'), true)) {
318
+			throw new InvalidArgumentException(__('Invalid schedule. Cannot save action.', 'action-scheduler'));
319 319
 		}
320 320
 
321 321
 		$query = wp_parse_args(
@@ -344,14 +344,14 @@  discard block
 block discarded – undo
344 344
 		 * @var wpdb $wpdb
345 345
 		 */
346 346
 		global $wpdb;
347
-		$sql        = ( 'count' === $select_or_count ) ? 'SELECT count(p.ID)' : 'SELECT p.ID ';
347
+		$sql        = ('count' === $select_or_count) ? 'SELECT count(p.ID)' : 'SELECT p.ID ';
348 348
 		$sql       .= "FROM {$wpdb->posts} p";
349 349
 		$sql_params = array();
350
-		if ( empty( $query['group'] ) && 'group' === $query['orderby'] ) {
350
+		if (empty($query['group']) && 'group' === $query['orderby']) {
351 351
 			$sql .= " LEFT JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
352 352
 			$sql .= " LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
353 353
 			$sql .= " LEFT JOIN {$wpdb->terms} t ON tt.term_id=t.term_id";
354
-		} elseif ( ! empty( $query['group'] ) ) {
354
+		} elseif ( ! empty($query['group'])) {
355 355
 			$sql         .= " INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id=p.ID";
356 356
 			$sql         .= " INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id=tt.term_taxonomy_id";
357 357
 			$sql         .= " INNER JOIN {$wpdb->terms} t ON tt.term_id=t.term_id";
@@ -360,58 +360,58 @@  discard block
 block discarded – undo
360 360
 		}
361 361
 		$sql         .= ' WHERE post_type=%s';
362 362
 		$sql_params[] = self::POST_TYPE;
363
-		if ( $query['hook'] ) {
363
+		if ($query['hook']) {
364 364
 			$sql         .= ' AND p.post_title=%s';
365 365
 			$sql_params[] = $query['hook'];
366 366
 		}
367
-		if ( $query['args'] !== null ) {
367
+		if ($query['args'] !== null) {
368 368
 			$sql         .= ' AND p.post_content=%s';
369
-			$sql_params[] = wp_json_encode( $query['args'] );
369
+			$sql_params[] = wp_json_encode($query['args']);
370 370
 		}
371 371
 
372
-		if ( $query['status'] ) {
373
-			$post_statuses = array_map( array( $this, 'get_post_status_by_action_status' ), (array) $query['status'] );
374
-			$placeholders  = array_fill( 0, count( $post_statuses ), '%s' );
375
-			$sql          .= ' AND p.post_status IN (' . join( ', ', $placeholders ) . ')';
376
-			$sql_params    = array_merge( $sql_params, array_values( $post_statuses ) );
372
+		if ($query['status']) {
373
+			$post_statuses = array_map(array($this, 'get_post_status_by_action_status'), (array) $query['status']);
374
+			$placeholders  = array_fill(0, count($post_statuses), '%s');
375
+			$sql          .= ' AND p.post_status IN ('.join(', ', $placeholders).')';
376
+			$sql_params    = array_merge($sql_params, array_values($post_statuses));
377 377
 		}
378 378
 
379
-		if ( $query['date'] instanceof DateTime ) {
379
+		if ($query['date'] instanceof DateTime) {
380 380
 			$date = clone $query['date'];
381
-			$date->setTimezone( new DateTimeZone( 'UTC' ) );
382
-			$date_string  = $date->format( 'Y-m-d H:i:s' );
383
-			$comparator   = $this->validate_sql_comparator( $query['date_compare'] );
381
+			$date->setTimezone(new DateTimeZone('UTC'));
382
+			$date_string  = $date->format('Y-m-d H:i:s');
383
+			$comparator   = $this->validate_sql_comparator($query['date_compare']);
384 384
 			$sql         .= " AND p.post_date_gmt $comparator %s";
385 385
 			$sql_params[] = $date_string;
386 386
 		}
387 387
 
388
-		if ( $query['modified'] instanceof DateTime ) {
388
+		if ($query['modified'] instanceof DateTime) {
389 389
 			$modified = clone $query['modified'];
390
-			$modified->setTimezone( new DateTimeZone( 'UTC' ) );
391
-			$date_string  = $modified->format( 'Y-m-d H:i:s' );
392
-			$comparator   = $this->validate_sql_comparator( $query['modified_compare'] );
390
+			$modified->setTimezone(new DateTimeZone('UTC'));
391
+			$date_string  = $modified->format('Y-m-d H:i:s');
392
+			$comparator   = $this->validate_sql_comparator($query['modified_compare']);
393 393
 			$sql         .= " AND p.post_modified_gmt $comparator %s";
394 394
 			$sql_params[] = $date_string;
395 395
 		}
396 396
 
397
-		if ( true === $query['claimed'] ) {
397
+		if (true === $query['claimed']) {
398 398
 			$sql .= " AND p.post_password != ''";
399
-		} elseif ( false === $query['claimed'] ) {
399
+		} elseif (false === $query['claimed']) {
400 400
 			$sql .= " AND p.post_password = ''";
401
-		} elseif ( $query['claimed'] !== null ) {
401
+		} elseif ($query['claimed'] !== null) {
402 402
 			$sql         .= ' AND p.post_password = %s';
403 403
 			$sql_params[] = $query['claimed'];
404 404
 		}
405 405
 
406
-		if ( ! empty( $query['search'] ) ) {
406
+		if ( ! empty($query['search'])) {
407 407
 			$sql .= ' AND (p.post_title LIKE %s OR p.post_content LIKE %s OR p.post_password LIKE %s)';
408
-			for ( $i = 0; $i < 3; $i++ ) {
409
-				$sql_params[] = sprintf( '%%%s%%', $query['search'] );
408
+			for ($i = 0; $i < 3; $i++) {
409
+				$sql_params[] = sprintf('%%%s%%', $query['search']);
410 410
 			}
411 411
 		}
412 412
 
413
-		if ( 'select' === $select_or_count ) {
414
-			switch ( $query['orderby'] ) {
413
+		if ('select' === $select_or_count) {
414
+			switch ($query['orderby']) {
415 415
 				case 'hook':
416 416
 					$orderby = 'p.post_title';
417 417
 					break;
@@ -433,20 +433,20 @@  discard block
 block discarded – undo
433 433
 					$orderby = 'p.post_date_gmt';
434 434
 					break;
435 435
 			}
436
-			if ( 'ASC' === strtoupper( $query['order'] ) ) {
436
+			if ('ASC' === strtoupper($query['order'])) {
437 437
 				$order = 'ASC';
438 438
 			} else {
439 439
 				$order = 'DESC';
440 440
 			}
441 441
 			$sql .= " ORDER BY $orderby $order";
442
-			if ( $query['per_page'] > 0 ) {
442
+			if ($query['per_page'] > 0) {
443 443
 				$sql         .= ' LIMIT %d, %d';
444 444
 				$sql_params[] = $query['offset'];
445 445
 				$sql_params[] = $query['per_page'];
446 446
 			}
447 447
 		}
448 448
 
449
-		return $wpdb->prepare( $sql, $sql_params ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
449
+		return $wpdb->prepare($sql, $sql_params); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
450 450
 	}
451 451
 
452 452
 	/**
@@ -461,7 +461,7 @@  discard block
 block discarded – undo
461 461
 	 *
462 462
 	 * @return string|array|null The IDs of actions matching the query. Null on failure.
463 463
 	 */
464
-	public function query_actions( $query = array(), $query_type = 'select' ) {
464
+	public function query_actions($query = array(), $query_type = 'select') {
465 465
 		/**
466 466
 		 * Global $wpdb object.
467 467
 		 *
@@ -469,9 +469,9 @@  discard block
 block discarded – undo
469 469
 		 */
470 470
 		global $wpdb;
471 471
 
472
-		$sql = $this->get_query_actions_sql( $query, $query_type );
472
+		$sql = $this->get_query_actions_sql($query, $query_type);
473 473
 
474
-		return ( 'count' === $query_type ) ? $wpdb->get_var( $sql ) : $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared
474
+		return ('count' === $query_type) ? $wpdb->get_var($sql) : $wpdb->get_col($sql); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared
475 475
 	}
476 476
 
477 477
 	/**
@@ -483,18 +483,18 @@  discard block
 block discarded – undo
483 483
 
484 484
 		$action_counts_by_status = array();
485 485
 		$action_stati_and_labels = $this->get_status_labels();
486
-		$posts_count_by_status   = (array) wp_count_posts( self::POST_TYPE, 'readable' );
486
+		$posts_count_by_status   = (array) wp_count_posts(self::POST_TYPE, 'readable');
487 487
 
488
-		foreach ( $posts_count_by_status as $post_status_name => $count ) {
488
+		foreach ($posts_count_by_status as $post_status_name => $count) {
489 489
 
490 490
 			try {
491
-				$action_status_name = $this->get_action_status_by_post_status( $post_status_name );
492
-			} catch ( Exception $e ) {
491
+				$action_status_name = $this->get_action_status_by_post_status($post_status_name);
492
+			} catch (Exception $e) {
493 493
 				// Ignore any post statuses that aren't for actions.
494 494
 				continue;
495 495
 			}
496
-			if ( array_key_exists( $action_status_name, $action_stati_and_labels ) ) {
497
-				$action_counts_by_status[ $action_status_name ] = $count;
496
+			if (array_key_exists($action_status_name, $action_stati_and_labels)) {
497
+				$action_counts_by_status[$action_status_name] = $count;
498 498
 			}
499 499
 		}
500 500
 
@@ -508,16 +508,16 @@  discard block
 block discarded – undo
508 508
 	 *
509 509
 	 * @throws InvalidArgumentException If $action_id is not identified.
510 510
 	 */
511
-	public function cancel_action( $action_id ) {
512
-		$post = get_post( $action_id );
513
-		if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
511
+	public function cancel_action($action_id) {
512
+		$post = get_post($action_id);
513
+		if (empty($post) || (self::POST_TYPE !== $post->post_type)) {
514 514
 			/* translators: %s is the action ID */
515
-			throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
515
+			throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
516 516
 		}
517
-		do_action( 'action_scheduler_canceled_action', $action_id );
518
-		add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
519
-		wp_trash_post( $action_id );
520
-		remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
517
+		do_action('action_scheduler_canceled_action', $action_id);
518
+		add_filter('pre_wp_unique_post_slug', array($this, 'set_unique_post_slug'), 10, 5);
519
+		wp_trash_post($action_id);
520
+		remove_filter('pre_wp_unique_post_slug', array($this, 'set_unique_post_slug'), 10);
521 521
 	}
522 522
 
523 523
 	/**
@@ -527,15 +527,15 @@  discard block
 block discarded – undo
527 527
 	 * @return void
528 528
 	 * @throws InvalidArgumentException If action is not identified.
529 529
 	 */
530
-	public function delete_action( $action_id ) {
531
-		$post = get_post( $action_id );
532
-		if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
530
+	public function delete_action($action_id) {
531
+		$post = get_post($action_id);
532
+		if (empty($post) || (self::POST_TYPE !== $post->post_type)) {
533 533
 			/* translators: %s is the action ID */
534
-			throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
534
+			throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
535 535
 		}
536
-		do_action( 'action_scheduler_deleted_action', $action_id );
536
+		do_action('action_scheduler_deleted_action', $action_id);
537 537
 
538
-		wp_delete_post( $action_id, true );
538
+		wp_delete_post($action_id, true);
539 539
 	}
540 540
 
541 541
 	/**
@@ -544,9 +544,9 @@  discard block
 block discarded – undo
544 544
 	 * @param int $action_id Action ID.
545 545
 	 * @return ActionScheduler_DateTime The date the action is schedule to run, or the date that it ran.
546 546
 	 */
547
-	public function get_date( $action_id ) {
548
-		$next = $this->get_date_gmt( $action_id );
549
-		return ActionScheduler_TimezoneHelper::set_local_timezone( $next );
547
+	public function get_date($action_id) {
548
+		$next = $this->get_date_gmt($action_id);
549
+		return ActionScheduler_TimezoneHelper::set_local_timezone($next);
550 550
 	}
551 551
 
552 552
 	/**
@@ -557,16 +557,16 @@  discard block
 block discarded – undo
557 557
 	 * @throws InvalidArgumentException If $action_id is not identified.
558 558
 	 * @return ActionScheduler_DateTime The date the action is schedule to run, or the date that it ran.
559 559
 	 */
560
-	public function get_date_gmt( $action_id ) {
561
-		$post = get_post( $action_id );
562
-		if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
560
+	public function get_date_gmt($action_id) {
561
+		$post = get_post($action_id);
562
+		if (empty($post) || (self::POST_TYPE !== $post->post_type)) {
563 563
 			/* translators: %s is the action ID */
564
-			throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
564
+			throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
565 565
 		}
566
-		if ( 'publish' === $post->post_status ) {
567
-			return as_get_datetime_object( $post->post_modified_gmt );
566
+		if ('publish' === $post->post_status) {
567
+			return as_get_datetime_object($post->post_modified_gmt);
568 568
 		} else {
569
-			return as_get_datetime_object( $post->post_date_gmt );
569
+			return as_get_datetime_object($post->post_date_gmt);
570 570
 		}
571 571
 	}
572 572
 
@@ -582,14 +582,14 @@  discard block
 block discarded – undo
582 582
 	 * @throws RuntimeException When there is an error staking a claim.
583 583
 	 * @throws InvalidArgumentException When the given group is not valid.
584 584
 	 */
585
-	public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' ) {
585
+	public function stake_claim($max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '') {
586 586
 		$this->claim_before_date = $before_date;
587 587
 		$claim_id                = $this->generate_claim_id();
588
-		$this->claim_actions( $claim_id, $max_actions, $before_date, $hooks, $group );
589
-		$action_ids              = $this->find_actions_by_claim_id( $claim_id );
588
+		$this->claim_actions($claim_id, $max_actions, $before_date, $hooks, $group);
589
+		$action_ids              = $this->find_actions_by_claim_id($claim_id);
590 590
 		$this->claim_before_date = null;
591 591
 
592
-		return new ActionScheduler_ActionClaim( $claim_id, $action_ids );
592
+		return new ActionScheduler_ActionClaim($claim_id, $action_ids);
593 593
 	}
594 594
 
595 595
 	/**
@@ -604,7 +604,7 @@  discard block
 block discarded – undo
604 604
 		return $wpdb->get_var(
605 605
 			$wpdb->prepare(
606 606
 				"SELECT COUNT(DISTINCT post_password) FROM {$wpdb->posts} WHERE post_password != '' AND post_type = %s AND post_status IN ('in-progress','pending')",
607
-				array( self::POST_TYPE )
607
+				array(self::POST_TYPE)
608 608
 			)
609 609
 		);
610 610
 	}
@@ -615,8 +615,8 @@  discard block
 block discarded – undo
615 615
 	 * @return string
616 616
 	 */
617 617
 	protected function generate_claim_id() {
618
-		$claim_id = md5( microtime( true ) . wp_rand( 0, 1000 ) );
619
-		return substr( $claim_id, 0, 20 ); // to fit in db field with 20 char limit.
618
+		$claim_id = md5(microtime(true).wp_rand(0, 1000));
619
+		return substr($claim_id, 0, 20); // to fit in db field with 20 char limit.
620 620
 	}
621 621
 
622 622
 	/**
@@ -631,14 +631,14 @@  discard block
 block discarded – undo
631 631
 	 * @return int The number of actions that were claimed.
632 632
 	 * @throws RuntimeException  When there is a database error.
633 633
 	 */
634
-	protected function claim_actions( $claim_id, $limit, DateTime $before_date = null, $hooks = array(), $group = '' ) {
634
+	protected function claim_actions($claim_id, $limit, DateTime $before_date = null, $hooks = array(), $group = '') {
635 635
 		// Set up initial variables.
636 636
 		$date      = null === $before_date ? as_get_datetime_object() : clone $before_date;
637
-		$limit_ids = ! empty( $group );
638
-		$ids       = $limit_ids ? $this->get_actions_by_group( $group, $limit, $date ) : array();
637
+		$limit_ids = ! empty($group);
638
+		$ids       = $limit_ids ? $this->get_actions_by_group($group, $limit, $date) : array();
639 639
 
640 640
 		// If limiting by IDs and no posts found, then return early since we have nothing to update.
641
-		if ( $limit_ids && 0 === count( $ids ) ) {
641
+		if ($limit_ids && 0 === count($ids)) {
642 642
 			return 0;
643 643
 		}
644 644
 
@@ -658,8 +658,8 @@  discard block
 block discarded – undo
658 658
 		$update = "UPDATE {$wpdb->posts} SET post_password = %s, post_modified_gmt = %s, post_modified = %s";
659 659
 		$params = array(
660 660
 			$claim_id,
661
-			current_time( 'mysql', true ),
662
-			current_time( 'mysql' ),
661
+			current_time('mysql', true),
662
+			current_time('mysql'),
663 663
 		);
664 664
 
665 665
 		// Build initial WHERE clause.
@@ -667,10 +667,10 @@  discard block
 block discarded – undo
667 667
 		$params[] = self::POST_TYPE;
668 668
 		$params[] = ActionScheduler_Store::STATUS_PENDING;
669 669
 
670
-		if ( ! empty( $hooks ) ) {
671
-			$placeholders = array_fill( 0, count( $hooks ), '%s' );
672
-			$where       .= ' AND post_title IN (' . join( ', ', $placeholders ) . ')';
673
-			$params       = array_merge( $params, array_values( $hooks ) );
670
+		if ( ! empty($hooks)) {
671
+			$placeholders = array_fill(0, count($hooks), '%s');
672
+			$where       .= ' AND post_title IN ('.join(', ', $placeholders).')';
673
+			$params       = array_merge($params, array_values($hooks));
674 674
 		}
675 675
 
676 676
 		/*
@@ -678,11 +678,11 @@  discard block
 block discarded – undo
678 678
 		 *
679 679
 		 * If we're not limiting by IDs, then include the post_date_gmt clause.
680 680
 		 */
681
-		if ( $limit_ids ) {
682
-			$where .= ' AND ID IN (' . join( ',', $ids ) . ')';
681
+		if ($limit_ids) {
682
+			$where .= ' AND ID IN ('.join(',', $ids).')';
683 683
 		} else {
684 684
 			$where   .= ' AND post_date_gmt <= %s';
685
-			$params[] = $date->format( 'Y-m-d H:i:s' );
685
+			$params[] = $date->format('Y-m-d H:i:s');
686 686
 		}
687 687
 
688 688
 		// Add the ORDER BY clause and,ms limit.
@@ -690,10 +690,10 @@  discard block
 block discarded – undo
690 690
 		$params[] = $limit;
691 691
 
692 692
 		// Run the query and gather results.
693
-		$rows_affected = $wpdb->query( $wpdb->prepare( "{$update} {$where} {$order}", $params ) ); // phpcs:ignore // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
693
+		$rows_affected = $wpdb->query($wpdb->prepare("{$update} {$where} {$order}", $params)); // phpcs:ignore // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
694 694
 
695
-		if ( false === $rows_affected ) {
696
-			throw new RuntimeException( __( 'Unable to claim actions. Database error.', 'action-scheduler' ) );
695
+		if (false === $rows_affected) {
696
+			throw new RuntimeException(__('Unable to claim actions. Database error.', 'action-scheduler'));
697 697
 		}
698 698
 
699 699
 		return (int) $rows_affected;
@@ -710,11 +710,11 @@  discard block
 block discarded – undo
710 710
 	 * @return array IDs of actions in the appropriate group and before the appropriate time.
711 711
 	 * @throws InvalidArgumentException When the group does not exist.
712 712
 	 */
713
-	protected function get_actions_by_group( $group, $limit, DateTime $date ) {
713
+	protected function get_actions_by_group($group, $limit, DateTime $date) {
714 714
 		// Ensure the group exists before continuing.
715
-		if ( ! term_exists( $group, self::GROUP_TAXONOMY ) ) {
715
+		if ( ! term_exists($group, self::GROUP_TAXONOMY)) {
716 716
 			/* translators: %s is the group name */
717
-			throw new InvalidArgumentException( sprintf( __( 'The group "%s" does not exist.', 'action-scheduler' ), $group ) );
717
+			throw new InvalidArgumentException(sprintf(__('The group "%s" does not exist.', 'action-scheduler'), $group));
718 718
 		}
719 719
 
720 720
 		// Set up a query for post IDs to use later.
@@ -734,7 +734,7 @@  discard block
 block discarded – undo
734 734
 			),
735 735
 			'date_query'       => array(
736 736
 				'column'    => 'post_date_gmt',
737
-				'before'    => $date->format( 'Y-m-d H:i' ),
737
+				'before'    => $date->format('Y-m-d H:i'),
738 738
 				'inclusive' => true,
739 739
 			),
740 740
 			'tax_query'        => array( // phpcs:ignore WordPress.DB.SlowDBQuery
@@ -747,7 +747,7 @@  discard block
 block discarded – undo
747 747
 			),
748 748
 		);
749 749
 
750
-		return $query->query( $query_args );
750
+		return $query->query($query_args);
751 751
 	}
752 752
 
753 753
 	/**
@@ -756,7 +756,7 @@  discard block
 block discarded – undo
756 756
 	 * @param string $claim_id Claim ID.
757 757
 	 * @return array
758 758
 	 */
759
-	public function find_actions_by_claim_id( $claim_id ) {
759
+	public function find_actions_by_claim_id($claim_id) {
760 760
 		/**
761 761
 		 * Global wpdb object.
762 762
 		 *
@@ -765,8 +765,8 @@  discard block
 block discarded – undo
765 765
 		global $wpdb;
766 766
 
767 767
 		$action_ids  = array();
768
-		$before_date = isset( $this->claim_before_date ) ? $this->claim_before_date : as_get_datetime_object();
769
-		$cut_off     = $before_date->format( 'Y-m-d H:i:s' );
768
+		$before_date = isset($this->claim_before_date) ? $this->claim_before_date : as_get_datetime_object();
769
+		$cut_off     = $before_date->format('Y-m-d H:i:s');
770 770
 
771 771
 		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
772 772
 		$results = $wpdb->get_results(
@@ -781,9 +781,9 @@  discard block
 block discarded – undo
781 781
 
782 782
 		// Verify that the scheduled date for each action is within the expected bounds (in some unusual
783 783
 		// cases, we cannot depend on MySQL to honor all of the WHERE conditions we specify).
784
-		foreach ( $results as $claimed_action ) {
785
-			if ( $claimed_action->post_date_gmt <= $cut_off ) {
786
-				$action_ids[] = absint( $claimed_action->ID );
784
+		foreach ($results as $claimed_action) {
785
+			if ($claimed_action->post_date_gmt <= $cut_off) {
786
+				$action_ids[] = absint($claimed_action->ID);
787 787
 			}
788 788
 		}
789 789
 
@@ -797,12 +797,12 @@  discard block
 block discarded – undo
797 797
 	 * @return void
798 798
 	 * @throws RuntimeException When the claim is not unlocked.
799 799
 	 */
800
-	public function release_claim( ActionScheduler_ActionClaim $claim ) {
801
-		$action_ids = $this->find_actions_by_claim_id( $claim->get_id() );
802
-		if ( empty( $action_ids ) ) {
800
+	public function release_claim(ActionScheduler_ActionClaim $claim) {
801
+		$action_ids = $this->find_actions_by_claim_id($claim->get_id());
802
+		if (empty($action_ids)) {
803 803
 			return; // nothing to do.
804 804
 		}
805
-		$action_id_string = implode( ',', array_map( 'intval', $action_ids ) );
805
+		$action_id_string = implode(',', array_map('intval', $action_ids));
806 806
 		/**
807 807
 		 * Global wpdb object.
808 808
 		 *
@@ -819,9 +819,9 @@  discard block
 block discarded – undo
819 819
 				)
820 820
 			)
821 821
 		);
822
-		if ( false === $result ) {
822
+		if (false === $result) {
823 823
 			/* translators: %s: claim ID */
824
-			throw new RuntimeException( sprintf( __( 'Unable to unlock claim %s. Database error.', 'action-scheduler' ), $claim->get_id() ) );
824
+			throw new RuntimeException(sprintf(__('Unable to unlock claim %s. Database error.', 'action-scheduler'), $claim->get_id()));
825 825
 		}
826 826
 	}
827 827
 
@@ -831,7 +831,7 @@  discard block
 block discarded – undo
831 831
 	 * @param string $action_id Action ID.
832 832
 	 * @throws RuntimeException When unable to unlock claim on action ID.
833 833
 	 */
834
-	public function unclaim_action( $action_id ) {
834
+	public function unclaim_action($action_id) {
835 835
 		/**
836 836
 		 * Global wpdb object.
837 837
 		 *
@@ -847,9 +847,9 @@  discard block
 block discarded – undo
847 847
 				self::POST_TYPE
848 848
 			)
849 849
 		);
850
-		if ( false === $result ) {
850
+		if (false === $result) {
851 851
 			/* translators: %s: action ID */
852
-			throw new RuntimeException( sprintf( __( 'Unable to unlock claim on action %s. Database error.', 'action-scheduler' ), $action_id ) );
852
+			throw new RuntimeException(sprintf(__('Unable to unlock claim on action %s. Database error.', 'action-scheduler'), $action_id));
853 853
 		}
854 854
 	}
855 855
 
@@ -861,7 +861,7 @@  discard block
 block discarded – undo
861 861
 	 * @return void
862 862
 	 * @throws RuntimeException When unable to mark failure on action ID.
863 863
 	 */
864
-	public function mark_failure( $action_id ) {
864
+	public function mark_failure($action_id) {
865 865
 		/**
866 866
 		 * Global wpdb object.
867 867
 		 *
@@ -871,11 +871,11 @@  discard block
 block discarded – undo
871 871
 
872 872
 		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
873 873
 		$result = $wpdb->query(
874
-			$wpdb->prepare( "UPDATE {$wpdb->posts} SET post_status = %s WHERE ID = %d AND post_type = %s", self::STATUS_FAILED, $action_id, self::POST_TYPE )
874
+			$wpdb->prepare("UPDATE {$wpdb->posts} SET post_status = %s WHERE ID = %d AND post_type = %s", self::STATUS_FAILED, $action_id, self::POST_TYPE)
875 875
 		);
876
-		if ( false === $result ) {
876
+		if (false === $result) {
877 877
 			/* translators: %s: action ID */
878
-			throw new RuntimeException( sprintf( __( 'Unable to mark failure on action %s. Database error.', 'action-scheduler' ), $action_id ) );
878
+			throw new RuntimeException(sprintf(__('Unable to mark failure on action %s. Database error.', 'action-scheduler'), $action_id));
879 879
 		}
880 880
 	}
881 881
 
@@ -885,8 +885,8 @@  discard block
 block discarded – undo
885 885
 	 * @param int $action_id Action ID.
886 886
 	 * @return mixed
887 887
 	 */
888
-	public function get_claim_id( $action_id ) {
889
-		return $this->get_post_column( $action_id, 'post_password' );
888
+	public function get_claim_id($action_id) {
889
+		return $this->get_post_column($action_id, 'post_password');
890 890
 	}
891 891
 
892 892
 	/**
@@ -897,14 +897,14 @@  discard block
 block discarded – undo
897 897
 	 * @return mixed
898 898
 	 * @throws InvalidArgumentException When the action ID is invalid.
899 899
 	 */
900
-	public function get_status( $action_id ) {
901
-		$status = $this->get_post_column( $action_id, 'post_status' );
900
+	public function get_status($action_id) {
901
+		$status = $this->get_post_column($action_id, 'post_status');
902 902
 
903
-		if ( null === $status ) {
904
-			throw new InvalidArgumentException( __( 'Invalid action ID. No status found.', 'action-scheduler' ) );
903
+		if (null === $status) {
904
+			throw new InvalidArgumentException(__('Invalid action ID. No status found.', 'action-scheduler'));
905 905
 		}
906 906
 
907
-		return $this->get_action_status_by_post_status( $status );
907
+		return $this->get_action_status_by_post_status($status);
908 908
 	}
909 909
 
910 910
 	/**
@@ -915,7 +915,7 @@  discard block
 block discarded – undo
915 915
 	 *
916 916
 	 * @return string|null
917 917
 	 */
918
-	private function get_post_column( $action_id, $column_name ) {
918
+	private function get_post_column($action_id, $column_name) {
919 919
 		/**
920 920
 		 * Global wpdb object.
921 921
 		 *
@@ -938,7 +938,7 @@  discard block
 block discarded – undo
938 938
 	 *
939 939
 	 * @param string $action_id Action ID.
940 940
 	 */
941
-	public function log_execution( $action_id ) {
941
+	public function log_execution($action_id) {
942 942
 		/**
943 943
 		 * Global wpdb object.
944 944
 		 *
@@ -951,8 +951,8 @@  discard block
 block discarded – undo
951 951
 			$wpdb->prepare(
952 952
 				"UPDATE {$wpdb->posts} SET menu_order = menu_order+1, post_status=%s, post_modified_gmt = %s, post_modified = %s WHERE ID = %d AND post_type = %s",
953 953
 				self::STATUS_RUNNING,
954
-				current_time( 'mysql', true ),
955
-				current_time( 'mysql' ),
954
+				current_time('mysql', true),
955
+				current_time('mysql'),
956 956
 				$action_id,
957 957
 				self::POST_TYPE
958 958
 			)
@@ -967,14 +967,14 @@  discard block
 block discarded – undo
967 967
 	 * @throws InvalidArgumentException When the action ID is invalid.
968 968
 	 * @throws RuntimeException         When there was an error executing the action.
969 969
 	 */
970
-	public function mark_complete( $action_id ) {
971
-		$post = get_post( $action_id );
972
-		if ( empty( $post ) || ( self::POST_TYPE !== $post->post_type ) ) {
970
+	public function mark_complete($action_id) {
971
+		$post = get_post($action_id);
972
+		if (empty($post) || (self::POST_TYPE !== $post->post_type)) {
973 973
 			/* translators: %s is the action ID */
974
-			throw new InvalidArgumentException( sprintf( __( 'Unidentified action %s', 'action-scheduler' ), $action_id ) );
974
+			throw new InvalidArgumentException(sprintf(__('Unidentified action %s', 'action-scheduler'), $action_id));
975 975
 		}
976
-		add_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10, 1 );
977
-		add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10, 5 );
976
+		add_filter('wp_insert_post_data', array($this, 'filter_insert_post_data'), 10, 1);
977
+		add_filter('pre_wp_unique_post_slug', array($this, 'set_unique_post_slug'), 10, 5);
978 978
 		$result = wp_update_post(
979 979
 			array(
980 980
 				'ID'          => $action_id,
@@ -982,10 +982,10 @@  discard block
 block discarded – undo
982 982
 			),
983 983
 			true
984 984
 		);
985
-		remove_filter( 'wp_insert_post_data', array( $this, 'filter_insert_post_data' ), 10 );
986
-		remove_filter( 'pre_wp_unique_post_slug', array( $this, 'set_unique_post_slug' ), 10 );
987
-		if ( is_wp_error( $result ) ) {
988
-			throw new RuntimeException( $result->get_error_message() );
985
+		remove_filter('wp_insert_post_data', array($this, 'filter_insert_post_data'), 10);
986
+		remove_filter('pre_wp_unique_post_slug', array($this, 'set_unique_post_slug'), 10);
987
+		if (is_wp_error($result)) {
988
+			throw new RuntimeException($result->get_error_message());
989 989
 		}
990 990
 
991 991
 		/**
@@ -995,7 +995,7 @@  discard block
 block discarded – undo
995 995
 		 *
996 996
 		 * @param int $action_id Action ID.
997 997
 		 */
998
-		do_action( 'action_scheduler_completed_action', $action_id );
998
+		do_action('action_scheduler_completed_action', $action_id);
999 999
 	}
1000 1000
 
1001 1001
 	/**
@@ -1003,7 +1003,7 @@  discard block
 block discarded – undo
1003 1003
 	 *
1004 1004
 	 * @param int $action_id Action ID.
1005 1005
 	 */
1006
-	public function mark_migrated( $action_id ) {
1006
+	public function mark_migrated($action_id) {
1007 1007
 		wp_update_post(
1008 1008
 			array(
1009 1009
 				'ID'          => $action_id,
@@ -1018,12 +1018,12 @@  discard block
 block discarded – undo
1018 1018
 	 * @param [type] $setting - Setting value.
1019 1019
 	 * @return bool
1020 1020
 	 */
1021
-	public function migration_dependencies_met( $setting ) {
1021
+	public function migration_dependencies_met($setting) {
1022 1022
 		global $wpdb;
1023 1023
 
1024
-		$dependencies_met = get_transient( self::DEPENDENCIES_MET );
1025
-		if ( empty( $dependencies_met ) ) {
1026
-			$maximum_args_length = apply_filters( 'action_scheduler_maximum_args_length', 191 );
1024
+		$dependencies_met = get_transient(self::DEPENDENCIES_MET);
1025
+		if (empty($dependencies_met)) {
1026
+			$maximum_args_length = apply_filters('action_scheduler_maximum_args_length', 191);
1027 1027
 			$found_action        = $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1028 1028
 				$wpdb->prepare(
1029 1029
 					"SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND CHAR_LENGTH(post_content) > %d LIMIT 1",
@@ -1031,8 +1031,8 @@  discard block
 block discarded – undo
1031 1031
 					self::POST_TYPE
1032 1032
 				)
1033 1033
 			);
1034
-			$dependencies_met    = $found_action ? 'no' : 'yes';
1035
-			set_transient( self::DEPENDENCIES_MET, $dependencies_met, DAY_IN_SECONDS );
1034
+			$dependencies_met = $found_action ? 'no' : 'yes';
1035
+			set_transient(self::DEPENDENCIES_MET, $dependencies_met, DAY_IN_SECONDS);
1036 1036
 		}
1037 1037
 
1038 1038
 		return 'yes' === $dependencies_met ? $setting : false;
@@ -1047,13 +1047,13 @@  discard block
 block discarded – undo
1047 1047
 	 *
1048 1048
 	 * @param ActionScheduler_Action $action Action object.
1049 1049
 	 */
1050
-	protected function validate_action( ActionScheduler_Action $action ) {
1050
+	protected function validate_action(ActionScheduler_Action $action) {
1051 1051
 		try {
1052
-			parent::validate_action( $action );
1053
-		} catch ( Exception $e ) {
1052
+			parent::validate_action($action);
1053
+		} catch (Exception $e) {
1054 1054
 			/* translators: %s is the error message */
1055
-			$message = sprintf( __( '%s Support for strings longer than this will be removed in a future version.', 'action-scheduler' ), $e->getMessage() );
1056
-			_doing_it_wrong( 'ActionScheduler_Action::$args', esc_html( $message ), '2.1.0' );
1055
+			$message = sprintf(__('%s Support for strings longer than this will be removed in a future version.', 'action-scheduler'), $e->getMessage());
1056
+			_doing_it_wrong('ActionScheduler_Action::$args', esc_html($message), '2.1.0');
1057 1057
 		}
1058 1058
 	}
1059 1059
 
@@ -1061,7 +1061,7 @@  discard block
 block discarded – undo
1061 1061
 	 * (@codeCoverageIgnore)
1062 1062
 	 */
1063 1063
 	public function init() {
1064
-		add_filter( 'action_scheduler_migration_dependencies_met', array( $this, 'migration_dependencies_met' ) );
1064
+		add_filter('action_scheduler_migration_dependencies_met', array($this, 'migration_dependencies_met'));
1065 1065
 
1066 1066
 		$post_type_registrar = new ActionScheduler_wpPostStore_PostTypeRegistrar();
1067 1067
 		$post_type_registrar->register();
Please login to merge, or discard this patch.
action-scheduler/classes/data-stores/ActionScheduler_HybridStore.php 2 patches
Indentation   +406 added lines, -406 removed lines patch added patch discarded remove patch
@@ -13,415 +13,415 @@
 block discarded – undo
13 13
  * @since 3.0.0
14 14
  */
15 15
 class ActionScheduler_HybridStore extends Store {
16
-	const DEMARKATION_OPTION = 'action_scheduler_hybrid_store_demarkation';
17
-
18
-	private $primary_store;
19
-	private $secondary_store;
20
-	private $migration_runner;
21
-
22
-	/**
23
-	 * @var int The dividing line between IDs of actions created
24
-	 *          by the primary and secondary stores.
25
-	 *
26
-	 * Methods that accept an action ID will compare the ID against
27
-	 * this to determine which store will contain that ID. In almost
28
-	 * all cases, the ID should come from the primary store, but if
29
-	 * client code is bypassing the API functions and fetching IDs
30
-	 * from elsewhere, then there is a chance that an unmigrated ID
31
-	 * might be requested.
32
-	 */
33
-	private $demarkation_id = 0;
34
-
35
-	/**
36
-	 * ActionScheduler_HybridStore constructor.
37
-	 *
38
-	 * @param Config $config Migration config object.
39
-	 */
40
-	public function __construct( Config $config = null ) {
41
-		$this->demarkation_id = (int) get_option( self::DEMARKATION_OPTION, 0 );
42
-		if ( empty( $config ) ) {
43
-			$config = Controller::instance()->get_migration_config_object();
44
-		}
45
-		$this->primary_store    = $config->get_destination_store();
46
-		$this->secondary_store  = $config->get_source_store();
47
-		$this->migration_runner = new Runner( $config );
48
-	}
49
-
50
-	/**
51
-	 * Initialize the table data store tables.
52
-	 *
53
-	 * @codeCoverageIgnore
54
-	 */
55
-	public function init() {
56
-		add_action( 'action_scheduler/created_table', array( $this, 'set_autoincrement' ), 10, 2 );
57
-		$this->primary_store->init();
58
-		$this->secondary_store->init();
59
-		remove_action( 'action_scheduler/created_table', array( $this, 'set_autoincrement' ), 10 );
60
-	}
61
-
62
-	/**
63
-	 * When the actions table is created, set its autoincrement
64
-	 * value to be one higher than the posts table to ensure that
65
-	 * there are no ID collisions.
66
-	 *
67
-	 * @param string $table_name
68
-	 * @param string $table_suffix
69
-	 *
70
-	 * @return void
71
-	 * @codeCoverageIgnore
72
-	 */
73
-	public function set_autoincrement( $table_name, $table_suffix ) {
74
-		if ( ActionScheduler_StoreSchema::ACTIONS_TABLE === $table_suffix ) {
75
-			if ( empty( $this->demarkation_id ) ) {
76
-				$this->demarkation_id = $this->set_demarkation_id();
77
-			}
78
-			/** @var \wpdb $wpdb */
79
-			global $wpdb;
80
-			/**
81
-			 * A default date of '0000-00-00 00:00:00' is invalid in MySQL 5.7 when configured with
82
-			 * sql_mode including both STRICT_TRANS_TABLES and NO_ZERO_DATE.
83
-			 */
84
-			$default_date = new DateTime( 'tomorrow' );
85
-			$null_action  = new ActionScheduler_NullAction();
86
-			$date_gmt     = $this->get_scheduled_date_string( $null_action, $default_date );
87
-			$date_local   = $this->get_scheduled_date_string_local( $null_action, $default_date );
88
-
89
-			$row_count = $wpdb->insert(
90
-				$wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
91
-				array(
92
-					'action_id'            => $this->demarkation_id,
93
-					'hook'                 => '',
94
-					'status'               => '',
95
-					'scheduled_date_gmt'   => $date_gmt,
96
-					'scheduled_date_local' => $date_local,
97
-					'last_attempt_gmt'     => $date_gmt,
98
-					'last_attempt_local'   => $date_local,
99
-				)
100
-			);
101
-			if ( $row_count > 0 ) {
102
-				$wpdb->delete(
103
-					$wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
104
-					array( 'action_id' => $this->demarkation_id )
105
-				);
106
-			}
107
-		}
108
-	}
109
-
110
-	/**
111
-	 * Store the demarkation id in WP options.
112
-	 *
113
-	 * @param int $id The ID to set as the demarkation point between the two stores
114
-	 *                Leave null to use the next ID from the WP posts table.
115
-	 *
116
-	 * @return int The new ID.
117
-	 *
118
-	 * @codeCoverageIgnore
119
-	 */
120
-	private function set_demarkation_id( $id = null ) {
121
-		if ( empty( $id ) ) {
122
-			/** @var \wpdb $wpdb */
123
-			global $wpdb;
124
-			$id = (int) $wpdb->get_var( "SELECT MAX(ID) FROM $wpdb->posts" );
125
-			$id ++;
126
-		}
127
-		update_option( self::DEMARKATION_OPTION, $id );
128
-
129
-		return $id;
130
-	}
131
-
132
-	/**
133
-	 * Find the first matching action from the secondary store.
134
-	 * If it exists, migrate it to the primary store immediately.
135
-	 * After it migrates, the secondary store will logically contain
136
-	 * the next matching action, so return the result thence.
137
-	 *
138
-	 * @param string $hook
139
-	 * @param array  $params
140
-	 *
141
-	 * @return string
142
-	 */
143
-	public function find_action( $hook, $params = array() ) {
144
-		$found_unmigrated_action = $this->secondary_store->find_action( $hook, $params );
145
-		if ( ! empty( $found_unmigrated_action ) ) {
146
-			$this->migrate( array( $found_unmigrated_action ) );
147
-		}
148
-
149
-		return $this->primary_store->find_action( $hook, $params );
150
-	}
151
-
152
-	/**
153
-	 * Find actions matching the query in the secondary source first.
154
-	 * If any are found, migrate them immediately. Then the secondary
155
-	 * store will contain the canonical results.
156
-	 *
157
-	 * @param array  $query
158
-	 * @param string $query_type Whether to select or count the results. Default, select.
159
-	 *
160
-	 * @return int[]
161
-	 */
162
-	public function query_actions( $query = array(), $query_type = 'select' ) {
163
-		$found_unmigrated_actions = $this->secondary_store->query_actions( $query, 'select' );
164
-		if ( ! empty( $found_unmigrated_actions ) ) {
165
-			$this->migrate( $found_unmigrated_actions );
166
-		}
167
-
168
-		return $this->primary_store->query_actions( $query, $query_type );
169
-	}
170
-
171
-	/**
172
-	 * Get a count of all actions in the store, grouped by status
173
-	 *
174
-	 * @return array Set of 'status' => int $count pairs for statuses with 1 or more actions of that status.
175
-	 */
176
-	public function action_counts() {
177
-		$unmigrated_actions_count = $this->secondary_store->action_counts();
178
-		$migrated_actions_count   = $this->primary_store->action_counts();
179
-		$actions_count_by_status  = array();
180
-
181
-		foreach ( $this->get_status_labels() as $status_key => $status_label ) {
182
-
183
-			$count = 0;
184
-
185
-			if ( isset( $unmigrated_actions_count[ $status_key ] ) ) {
186
-				$count += $unmigrated_actions_count[ $status_key ];
187
-			}
188
-
189
-			if ( isset( $migrated_actions_count[ $status_key ] ) ) {
190
-				$count += $migrated_actions_count[ $status_key ];
191
-			}
192
-
193
-			$actions_count_by_status[ $status_key ] = $count;
194
-		}
195
-
196
-		$actions_count_by_status = array_filter( $actions_count_by_status );
197
-
198
-		return $actions_count_by_status;
199
-	}
200
-
201
-	/**
202
-	 * If any actions would have been claimed by the secondary store,
203
-	 * migrate them immediately, then ask the primary store for the
204
-	 * canonical claim.
205
-	 *
206
-	 * @param int           $max_actions
207
-	 * @param DateTime|null $before_date
208
-	 *
209
-	 * @return ActionScheduler_ActionClaim
210
-	 */
211
-	public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' ) {
212
-		$claim = $this->secondary_store->stake_claim( $max_actions, $before_date, $hooks, $group );
213
-
214
-		$claimed_actions = $claim->get_actions();
215
-		if ( ! empty( $claimed_actions ) ) {
216
-			$this->migrate( $claimed_actions );
217
-		}
218
-
219
-		$this->secondary_store->release_claim( $claim );
220
-
221
-		return $this->primary_store->stake_claim( $max_actions, $before_date, $hooks, $group );
222
-	}
223
-
224
-	/**
225
-	 * Migrate a list of actions to the table data store.
226
-	 *
227
-	 * @param array $action_ids List of action IDs.
228
-	 */
229
-	private function migrate( $action_ids ) {
230
-		$this->migration_runner->migrate_actions( $action_ids );
231
-	}
232
-
233
-	/**
234
-	 * Save an action to the primary store.
235
-	 *
236
-	 * @param ActionScheduler_Action $action Action object to be saved.
237
-	 * @param DateTime               $date Optional. Schedule date. Default null.
238
-	 *
239
-	 * @return int The action ID
240
-	 */
241
-	public function save_action( ActionScheduler_Action $action, DateTime $date = null ) {
242
-		return $this->primary_store->save_action( $action, $date );
243
-	}
244
-
245
-	/**
246
-	 * Retrieve an existing action whether migrated or not.
247
-	 *
248
-	 * @param int $action_id Action ID.
249
-	 */
250
-	public function fetch_action( $action_id ) {
251
-		$store = $this->get_store_from_action_id( $action_id, true );
252
-		if ( $store ) {
253
-			return $store->fetch_action( $action_id );
254
-		} else {
255
-			return new ActionScheduler_NullAction();
256
-		}
257
-	}
258
-
259
-	/**
260
-	 * Cancel an existing action whether migrated or not.
261
-	 *
262
-	 * @param int $action_id Action ID.
263
-	 */
264
-	public function cancel_action( $action_id ) {
265
-		$store = $this->get_store_from_action_id( $action_id );
266
-		if ( $store ) {
267
-			$store->cancel_action( $action_id );
268
-		}
269
-	}
270
-
271
-	/**
272
-	 * Delete an existing action whether migrated or not.
273
-	 *
274
-	 * @param int $action_id Action ID.
275
-	 */
276
-	public function delete_action( $action_id ) {
277
-		$store = $this->get_store_from_action_id( $action_id );
278
-		if ( $store ) {
279
-			$store->delete_action( $action_id );
280
-		}
281
-	}
282
-
283
-	/**
284
-	 * Get the schedule date an existing action whether migrated or not.
285
-	 *
286
-	 * @param int $action_id Action ID.
287
-	 */
288
-	public function get_date( $action_id ) {
289
-		$store = $this->get_store_from_action_id( $action_id );
290
-		if ( $store ) {
291
-			return $store->get_date( $action_id );
292
-		} else {
293
-			return null;
294
-		}
295
-	}
296
-
297
-	/**
298
-	 * Mark an existing action as failed whether migrated or not.
299
-	 *
300
-	 * @param int $action_id Action ID.
301
-	 */
302
-	public function mark_failure( $action_id ) {
303
-		$store = $this->get_store_from_action_id( $action_id );
304
-		if ( $store ) {
305
-			$store->mark_failure( $action_id );
306
-		}
307
-	}
308
-
309
-	/**
310
-	 * Log the execution of an existing action whether migrated or not.
311
-	 *
312
-	 * @param int $action_id Action ID.
313
-	 */
314
-	public function log_execution( $action_id ) {
315
-		$store = $this->get_store_from_action_id( $action_id );
316
-		if ( $store ) {
317
-			$store->log_execution( $action_id );
318
-		}
319
-	}
320
-
321
-	/**
322
-	 * Mark an existing action complete whether migrated or not.
323
-	 *
324
-	 * @param int $action_id Action ID.
325
-	 */
326
-	public function mark_complete( $action_id ) {
327
-		$store = $this->get_store_from_action_id( $action_id );
328
-		if ( $store ) {
329
-			$store->mark_complete( $action_id );
330
-		}
331
-	}
332
-
333
-	/**
334
-	 * Get an existing action status whether migrated or not.
335
-	 *
336
-	 * @param int $action_id Action ID.
337
-	 */
338
-	public function get_status( $action_id ) {
339
-		$store = $this->get_store_from_action_id( $action_id );
340
-		if ( $store ) {
341
-			return $store->get_status( $action_id );
342
-		}
343
-		return null;
344
-	}
345
-
346
-	/**
347
-	 * Return which store an action is stored in.
348
-	 *
349
-	 * @param int  $action_id ID of the action.
350
-	 * @param bool $primary_first Optional flag indicating search the primary store first.
351
-	 * @return ActionScheduler_Store
352
-	 */
353
-	protected function get_store_from_action_id( $action_id, $primary_first = false ) {
354
-		if ( $primary_first ) {
355
-			$stores = array(
356
-				$this->primary_store,
357
-				$this->secondary_store,
358
-			);
359
-		} elseif ( $action_id < $this->demarkation_id ) {
360
-			$stores = array(
361
-				$this->secondary_store,
362
-				$this->primary_store,
363
-			);
364
-		} else {
365
-			$stores = array(
366
-				$this->primary_store,
367
-			);
368
-		}
369
-
370
-		foreach ( $stores as $store ) {
371
-			$action = $store->fetch_action( $action_id );
372
-			if ( ! is_a( $action, 'ActionScheduler_NullAction' ) ) {
373
-				return $store;
374
-			}
375
-		}
376
-		return null;
377
-	}
378
-
379
-	/*
16
+    const DEMARKATION_OPTION = 'action_scheduler_hybrid_store_demarkation';
17
+
18
+    private $primary_store;
19
+    private $secondary_store;
20
+    private $migration_runner;
21
+
22
+    /**
23
+     * @var int The dividing line between IDs of actions created
24
+     *          by the primary and secondary stores.
25
+     *
26
+     * Methods that accept an action ID will compare the ID against
27
+     * this to determine which store will contain that ID. In almost
28
+     * all cases, the ID should come from the primary store, but if
29
+     * client code is bypassing the API functions and fetching IDs
30
+     * from elsewhere, then there is a chance that an unmigrated ID
31
+     * might be requested.
32
+     */
33
+    private $demarkation_id = 0;
34
+
35
+    /**
36
+     * ActionScheduler_HybridStore constructor.
37
+     *
38
+     * @param Config $config Migration config object.
39
+     */
40
+    public function __construct( Config $config = null ) {
41
+        $this->demarkation_id = (int) get_option( self::DEMARKATION_OPTION, 0 );
42
+        if ( empty( $config ) ) {
43
+            $config = Controller::instance()->get_migration_config_object();
44
+        }
45
+        $this->primary_store    = $config->get_destination_store();
46
+        $this->secondary_store  = $config->get_source_store();
47
+        $this->migration_runner = new Runner( $config );
48
+    }
49
+
50
+    /**
51
+     * Initialize the table data store tables.
52
+     *
53
+     * @codeCoverageIgnore
54
+     */
55
+    public function init() {
56
+        add_action( 'action_scheduler/created_table', array( $this, 'set_autoincrement' ), 10, 2 );
57
+        $this->primary_store->init();
58
+        $this->secondary_store->init();
59
+        remove_action( 'action_scheduler/created_table', array( $this, 'set_autoincrement' ), 10 );
60
+    }
61
+
62
+    /**
63
+     * When the actions table is created, set its autoincrement
64
+     * value to be one higher than the posts table to ensure that
65
+     * there are no ID collisions.
66
+     *
67
+     * @param string $table_name
68
+     * @param string $table_suffix
69
+     *
70
+     * @return void
71
+     * @codeCoverageIgnore
72
+     */
73
+    public function set_autoincrement( $table_name, $table_suffix ) {
74
+        if ( ActionScheduler_StoreSchema::ACTIONS_TABLE === $table_suffix ) {
75
+            if ( empty( $this->demarkation_id ) ) {
76
+                $this->demarkation_id = $this->set_demarkation_id();
77
+            }
78
+            /** @var \wpdb $wpdb */
79
+            global $wpdb;
80
+            /**
81
+             * A default date of '0000-00-00 00:00:00' is invalid in MySQL 5.7 when configured with
82
+             * sql_mode including both STRICT_TRANS_TABLES and NO_ZERO_DATE.
83
+             */
84
+            $default_date = new DateTime( 'tomorrow' );
85
+            $null_action  = new ActionScheduler_NullAction();
86
+            $date_gmt     = $this->get_scheduled_date_string( $null_action, $default_date );
87
+            $date_local   = $this->get_scheduled_date_string_local( $null_action, $default_date );
88
+
89
+            $row_count = $wpdb->insert(
90
+                $wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
91
+                array(
92
+                    'action_id'            => $this->demarkation_id,
93
+                    'hook'                 => '',
94
+                    'status'               => '',
95
+                    'scheduled_date_gmt'   => $date_gmt,
96
+                    'scheduled_date_local' => $date_local,
97
+                    'last_attempt_gmt'     => $date_gmt,
98
+                    'last_attempt_local'   => $date_local,
99
+                )
100
+            );
101
+            if ( $row_count > 0 ) {
102
+                $wpdb->delete(
103
+                    $wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
104
+                    array( 'action_id' => $this->demarkation_id )
105
+                );
106
+            }
107
+        }
108
+    }
109
+
110
+    /**
111
+     * Store the demarkation id in WP options.
112
+     *
113
+     * @param int $id The ID to set as the demarkation point between the two stores
114
+     *                Leave null to use the next ID from the WP posts table.
115
+     *
116
+     * @return int The new ID.
117
+     *
118
+     * @codeCoverageIgnore
119
+     */
120
+    private function set_demarkation_id( $id = null ) {
121
+        if ( empty( $id ) ) {
122
+            /** @var \wpdb $wpdb */
123
+            global $wpdb;
124
+            $id = (int) $wpdb->get_var( "SELECT MAX(ID) FROM $wpdb->posts" );
125
+            $id ++;
126
+        }
127
+        update_option( self::DEMARKATION_OPTION, $id );
128
+
129
+        return $id;
130
+    }
131
+
132
+    /**
133
+     * Find the first matching action from the secondary store.
134
+     * If it exists, migrate it to the primary store immediately.
135
+     * After it migrates, the secondary store will logically contain
136
+     * the next matching action, so return the result thence.
137
+     *
138
+     * @param string $hook
139
+     * @param array  $params
140
+     *
141
+     * @return string
142
+     */
143
+    public function find_action( $hook, $params = array() ) {
144
+        $found_unmigrated_action = $this->secondary_store->find_action( $hook, $params );
145
+        if ( ! empty( $found_unmigrated_action ) ) {
146
+            $this->migrate( array( $found_unmigrated_action ) );
147
+        }
148
+
149
+        return $this->primary_store->find_action( $hook, $params );
150
+    }
151
+
152
+    /**
153
+     * Find actions matching the query in the secondary source first.
154
+     * If any are found, migrate them immediately. Then the secondary
155
+     * store will contain the canonical results.
156
+     *
157
+     * @param array  $query
158
+     * @param string $query_type Whether to select or count the results. Default, select.
159
+     *
160
+     * @return int[]
161
+     */
162
+    public function query_actions( $query = array(), $query_type = 'select' ) {
163
+        $found_unmigrated_actions = $this->secondary_store->query_actions( $query, 'select' );
164
+        if ( ! empty( $found_unmigrated_actions ) ) {
165
+            $this->migrate( $found_unmigrated_actions );
166
+        }
167
+
168
+        return $this->primary_store->query_actions( $query, $query_type );
169
+    }
170
+
171
+    /**
172
+     * Get a count of all actions in the store, grouped by status
173
+     *
174
+     * @return array Set of 'status' => int $count pairs for statuses with 1 or more actions of that status.
175
+     */
176
+    public function action_counts() {
177
+        $unmigrated_actions_count = $this->secondary_store->action_counts();
178
+        $migrated_actions_count   = $this->primary_store->action_counts();
179
+        $actions_count_by_status  = array();
180
+
181
+        foreach ( $this->get_status_labels() as $status_key => $status_label ) {
182
+
183
+            $count = 0;
184
+
185
+            if ( isset( $unmigrated_actions_count[ $status_key ] ) ) {
186
+                $count += $unmigrated_actions_count[ $status_key ];
187
+            }
188
+
189
+            if ( isset( $migrated_actions_count[ $status_key ] ) ) {
190
+                $count += $migrated_actions_count[ $status_key ];
191
+            }
192
+
193
+            $actions_count_by_status[ $status_key ] = $count;
194
+        }
195
+
196
+        $actions_count_by_status = array_filter( $actions_count_by_status );
197
+
198
+        return $actions_count_by_status;
199
+    }
200
+
201
+    /**
202
+     * If any actions would have been claimed by the secondary store,
203
+     * migrate them immediately, then ask the primary store for the
204
+     * canonical claim.
205
+     *
206
+     * @param int           $max_actions
207
+     * @param DateTime|null $before_date
208
+     *
209
+     * @return ActionScheduler_ActionClaim
210
+     */
211
+    public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' ) {
212
+        $claim = $this->secondary_store->stake_claim( $max_actions, $before_date, $hooks, $group );
213
+
214
+        $claimed_actions = $claim->get_actions();
215
+        if ( ! empty( $claimed_actions ) ) {
216
+            $this->migrate( $claimed_actions );
217
+        }
218
+
219
+        $this->secondary_store->release_claim( $claim );
220
+
221
+        return $this->primary_store->stake_claim( $max_actions, $before_date, $hooks, $group );
222
+    }
223
+
224
+    /**
225
+     * Migrate a list of actions to the table data store.
226
+     *
227
+     * @param array $action_ids List of action IDs.
228
+     */
229
+    private function migrate( $action_ids ) {
230
+        $this->migration_runner->migrate_actions( $action_ids );
231
+    }
232
+
233
+    /**
234
+     * Save an action to the primary store.
235
+     *
236
+     * @param ActionScheduler_Action $action Action object to be saved.
237
+     * @param DateTime               $date Optional. Schedule date. Default null.
238
+     *
239
+     * @return int The action ID
240
+     */
241
+    public function save_action( ActionScheduler_Action $action, DateTime $date = null ) {
242
+        return $this->primary_store->save_action( $action, $date );
243
+    }
244
+
245
+    /**
246
+     * Retrieve an existing action whether migrated or not.
247
+     *
248
+     * @param int $action_id Action ID.
249
+     */
250
+    public function fetch_action( $action_id ) {
251
+        $store = $this->get_store_from_action_id( $action_id, true );
252
+        if ( $store ) {
253
+            return $store->fetch_action( $action_id );
254
+        } else {
255
+            return new ActionScheduler_NullAction();
256
+        }
257
+    }
258
+
259
+    /**
260
+     * Cancel an existing action whether migrated or not.
261
+     *
262
+     * @param int $action_id Action ID.
263
+     */
264
+    public function cancel_action( $action_id ) {
265
+        $store = $this->get_store_from_action_id( $action_id );
266
+        if ( $store ) {
267
+            $store->cancel_action( $action_id );
268
+        }
269
+    }
270
+
271
+    /**
272
+     * Delete an existing action whether migrated or not.
273
+     *
274
+     * @param int $action_id Action ID.
275
+     */
276
+    public function delete_action( $action_id ) {
277
+        $store = $this->get_store_from_action_id( $action_id );
278
+        if ( $store ) {
279
+            $store->delete_action( $action_id );
280
+        }
281
+    }
282
+
283
+    /**
284
+     * Get the schedule date an existing action whether migrated or not.
285
+     *
286
+     * @param int $action_id Action ID.
287
+     */
288
+    public function get_date( $action_id ) {
289
+        $store = $this->get_store_from_action_id( $action_id );
290
+        if ( $store ) {
291
+            return $store->get_date( $action_id );
292
+        } else {
293
+            return null;
294
+        }
295
+    }
296
+
297
+    /**
298
+     * Mark an existing action as failed whether migrated or not.
299
+     *
300
+     * @param int $action_id Action ID.
301
+     */
302
+    public function mark_failure( $action_id ) {
303
+        $store = $this->get_store_from_action_id( $action_id );
304
+        if ( $store ) {
305
+            $store->mark_failure( $action_id );
306
+        }
307
+    }
308
+
309
+    /**
310
+     * Log the execution of an existing action whether migrated or not.
311
+     *
312
+     * @param int $action_id Action ID.
313
+     */
314
+    public function log_execution( $action_id ) {
315
+        $store = $this->get_store_from_action_id( $action_id );
316
+        if ( $store ) {
317
+            $store->log_execution( $action_id );
318
+        }
319
+    }
320
+
321
+    /**
322
+     * Mark an existing action complete whether migrated or not.
323
+     *
324
+     * @param int $action_id Action ID.
325
+     */
326
+    public function mark_complete( $action_id ) {
327
+        $store = $this->get_store_from_action_id( $action_id );
328
+        if ( $store ) {
329
+            $store->mark_complete( $action_id );
330
+        }
331
+    }
332
+
333
+    /**
334
+     * Get an existing action status whether migrated or not.
335
+     *
336
+     * @param int $action_id Action ID.
337
+     */
338
+    public function get_status( $action_id ) {
339
+        $store = $this->get_store_from_action_id( $action_id );
340
+        if ( $store ) {
341
+            return $store->get_status( $action_id );
342
+        }
343
+        return null;
344
+    }
345
+
346
+    /**
347
+     * Return which store an action is stored in.
348
+     *
349
+     * @param int  $action_id ID of the action.
350
+     * @param bool $primary_first Optional flag indicating search the primary store first.
351
+     * @return ActionScheduler_Store
352
+     */
353
+    protected function get_store_from_action_id( $action_id, $primary_first = false ) {
354
+        if ( $primary_first ) {
355
+            $stores = array(
356
+                $this->primary_store,
357
+                $this->secondary_store,
358
+            );
359
+        } elseif ( $action_id < $this->demarkation_id ) {
360
+            $stores = array(
361
+                $this->secondary_store,
362
+                $this->primary_store,
363
+            );
364
+        } else {
365
+            $stores = array(
366
+                $this->primary_store,
367
+            );
368
+        }
369
+
370
+        foreach ( $stores as $store ) {
371
+            $action = $store->fetch_action( $action_id );
372
+            if ( ! is_a( $action, 'ActionScheduler_NullAction' ) ) {
373
+                return $store;
374
+            }
375
+        }
376
+        return null;
377
+    }
378
+
379
+    /*
380 380
 	 * * * * * * * * * * * * * * * * * * * * * * * * * *
381 381
 	 * All claim-related functions should operate solely
382 382
 	 * on the primary store.
383 383
 	 * * * * * * * * * * * * * * * * * * * * * * * * * * */
384 384
 
385
-	/**
386
-	 * Get the claim count from the table data store.
387
-	 */
388
-	public function get_claim_count() {
389
-		return $this->primary_store->get_claim_count();
390
-	}
391
-
392
-	/**
393
-	 * Retrieve the claim ID for an action from the table data store.
394
-	 *
395
-	 * @param int $action_id Action ID.
396
-	 */
397
-	public function get_claim_id( $action_id ) {
398
-		return $this->primary_store->get_claim_id( $action_id );
399
-	}
400
-
401
-	/**
402
-	 * Release a claim in the table data store.
403
-	 *
404
-	 * @param ActionScheduler_ActionClaim $claim Claim object.
405
-	 */
406
-	public function release_claim( ActionScheduler_ActionClaim $claim ) {
407
-		$this->primary_store->release_claim( $claim );
408
-	}
409
-
410
-	/**
411
-	 * Release claims on an action in the table data store.
412
-	 *
413
-	 * @param int $action_id Action ID.
414
-	 */
415
-	public function unclaim_action( $action_id ) {
416
-		$this->primary_store->unclaim_action( $action_id );
417
-	}
418
-
419
-	/**
420
-	 * Retrieve a list of action IDs by claim.
421
-	 *
422
-	 * @param int $claim_id Claim ID.
423
-	 */
424
-	public function find_actions_by_claim_id( $claim_id ) {
425
-		return $this->primary_store->find_actions_by_claim_id( $claim_id );
426
-	}
385
+    /**
386
+     * Get the claim count from the table data store.
387
+     */
388
+    public function get_claim_count() {
389
+        return $this->primary_store->get_claim_count();
390
+    }
391
+
392
+    /**
393
+     * Retrieve the claim ID for an action from the table data store.
394
+     *
395
+     * @param int $action_id Action ID.
396
+     */
397
+    public function get_claim_id( $action_id ) {
398
+        return $this->primary_store->get_claim_id( $action_id );
399
+    }
400
+
401
+    /**
402
+     * Release a claim in the table data store.
403
+     *
404
+     * @param ActionScheduler_ActionClaim $claim Claim object.
405
+     */
406
+    public function release_claim( ActionScheduler_ActionClaim $claim ) {
407
+        $this->primary_store->release_claim( $claim );
408
+    }
409
+
410
+    /**
411
+     * Release claims on an action in the table data store.
412
+     *
413
+     * @param int $action_id Action ID.
414
+     */
415
+    public function unclaim_action( $action_id ) {
416
+        $this->primary_store->unclaim_action( $action_id );
417
+    }
418
+
419
+    /**
420
+     * Retrieve a list of action IDs by claim.
421
+     *
422
+     * @param int $claim_id Claim ID.
423
+     */
424
+    public function find_actions_by_claim_id( $claim_id ) {
425
+        return $this->primary_store->find_actions_by_claim_id( $claim_id );
426
+    }
427 427
 }
Please login to merge, or discard this patch.
Spacing   +92 added lines, -92 removed lines patch added patch discarded remove patch
@@ -37,14 +37,14 @@  discard block
 block discarded – undo
37 37
 	 *
38 38
 	 * @param Config $config Migration config object.
39 39
 	 */
40
-	public function __construct( Config $config = null ) {
41
-		$this->demarkation_id = (int) get_option( self::DEMARKATION_OPTION, 0 );
42
-		if ( empty( $config ) ) {
40
+	public function __construct(Config $config = null) {
41
+		$this->demarkation_id = (int) get_option(self::DEMARKATION_OPTION, 0);
42
+		if (empty($config)) {
43 43
 			$config = Controller::instance()->get_migration_config_object();
44 44
 		}
45 45
 		$this->primary_store    = $config->get_destination_store();
46 46
 		$this->secondary_store  = $config->get_source_store();
47
-		$this->migration_runner = new Runner( $config );
47
+		$this->migration_runner = new Runner($config);
48 48
 	}
49 49
 
50 50
 	/**
@@ -53,10 +53,10 @@  discard block
 block discarded – undo
53 53
 	 * @codeCoverageIgnore
54 54
 	 */
55 55
 	public function init() {
56
-		add_action( 'action_scheduler/created_table', array( $this, 'set_autoincrement' ), 10, 2 );
56
+		add_action('action_scheduler/created_table', array($this, 'set_autoincrement'), 10, 2);
57 57
 		$this->primary_store->init();
58 58
 		$this->secondary_store->init();
59
-		remove_action( 'action_scheduler/created_table', array( $this, 'set_autoincrement' ), 10 );
59
+		remove_action('action_scheduler/created_table', array($this, 'set_autoincrement'), 10);
60 60
 	}
61 61
 
62 62
 	/**
@@ -70,9 +70,9 @@  discard block
 block discarded – undo
70 70
 	 * @return void
71 71
 	 * @codeCoverageIgnore
72 72
 	 */
73
-	public function set_autoincrement( $table_name, $table_suffix ) {
74
-		if ( ActionScheduler_StoreSchema::ACTIONS_TABLE === $table_suffix ) {
75
-			if ( empty( $this->demarkation_id ) ) {
73
+	public function set_autoincrement($table_name, $table_suffix) {
74
+		if (ActionScheduler_StoreSchema::ACTIONS_TABLE === $table_suffix) {
75
+			if (empty($this->demarkation_id)) {
76 76
 				$this->demarkation_id = $this->set_demarkation_id();
77 77
 			}
78 78
 			/** @var \wpdb $wpdb */
@@ -81,10 +81,10 @@  discard block
 block discarded – undo
81 81
 			 * A default date of '0000-00-00 00:00:00' is invalid in MySQL 5.7 when configured with
82 82
 			 * sql_mode including both STRICT_TRANS_TABLES and NO_ZERO_DATE.
83 83
 			 */
84
-			$default_date = new DateTime( 'tomorrow' );
84
+			$default_date = new DateTime('tomorrow');
85 85
 			$null_action  = new ActionScheduler_NullAction();
86
-			$date_gmt     = $this->get_scheduled_date_string( $null_action, $default_date );
87
-			$date_local   = $this->get_scheduled_date_string_local( $null_action, $default_date );
86
+			$date_gmt     = $this->get_scheduled_date_string($null_action, $default_date);
87
+			$date_local   = $this->get_scheduled_date_string_local($null_action, $default_date);
88 88
 
89 89
 			$row_count = $wpdb->insert(
90 90
 				$wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
@@ -98,10 +98,10 @@  discard block
 block discarded – undo
98 98
 					'last_attempt_local'   => $date_local,
99 99
 				)
100 100
 			);
101
-			if ( $row_count > 0 ) {
101
+			if ($row_count > 0) {
102 102
 				$wpdb->delete(
103 103
 					$wpdb->{ActionScheduler_StoreSchema::ACTIONS_TABLE},
104
-					array( 'action_id' => $this->demarkation_id )
104
+					array('action_id' => $this->demarkation_id)
105 105
 				);
106 106
 			}
107 107
 		}
@@ -117,14 +117,14 @@  discard block
 block discarded – undo
117 117
 	 *
118 118
 	 * @codeCoverageIgnore
119 119
 	 */
120
-	private function set_demarkation_id( $id = null ) {
121
-		if ( empty( $id ) ) {
120
+	private function set_demarkation_id($id = null) {
121
+		if (empty($id)) {
122 122
 			/** @var \wpdb $wpdb */
123 123
 			global $wpdb;
124
-			$id = (int) $wpdb->get_var( "SELECT MAX(ID) FROM $wpdb->posts" );
125
-			$id ++;
124
+			$id = (int) $wpdb->get_var("SELECT MAX(ID) FROM $wpdb->posts");
125
+			$id++;
126 126
 		}
127
-		update_option( self::DEMARKATION_OPTION, $id );
127
+		update_option(self::DEMARKATION_OPTION, $id);
128 128
 
129 129
 		return $id;
130 130
 	}
@@ -140,13 +140,13 @@  discard block
 block discarded – undo
140 140
 	 *
141 141
 	 * @return string
142 142
 	 */
143
-	public function find_action( $hook, $params = array() ) {
144
-		$found_unmigrated_action = $this->secondary_store->find_action( $hook, $params );
145
-		if ( ! empty( $found_unmigrated_action ) ) {
146
-			$this->migrate( array( $found_unmigrated_action ) );
143
+	public function find_action($hook, $params = array()) {
144
+		$found_unmigrated_action = $this->secondary_store->find_action($hook, $params);
145
+		if ( ! empty($found_unmigrated_action)) {
146
+			$this->migrate(array($found_unmigrated_action));
147 147
 		}
148 148
 
149
-		return $this->primary_store->find_action( $hook, $params );
149
+		return $this->primary_store->find_action($hook, $params);
150 150
 	}
151 151
 
152 152
 	/**
@@ -159,13 +159,13 @@  discard block
 block discarded – undo
159 159
 	 *
160 160
 	 * @return int[]
161 161
 	 */
162
-	public function query_actions( $query = array(), $query_type = 'select' ) {
163
-		$found_unmigrated_actions = $this->secondary_store->query_actions( $query, 'select' );
164
-		if ( ! empty( $found_unmigrated_actions ) ) {
165
-			$this->migrate( $found_unmigrated_actions );
162
+	public function query_actions($query = array(), $query_type = 'select') {
163
+		$found_unmigrated_actions = $this->secondary_store->query_actions($query, 'select');
164
+		if ( ! empty($found_unmigrated_actions)) {
165
+			$this->migrate($found_unmigrated_actions);
166 166
 		}
167 167
 
168
-		return $this->primary_store->query_actions( $query, $query_type );
168
+		return $this->primary_store->query_actions($query, $query_type);
169 169
 	}
170 170
 
171 171
 	/**
@@ -178,22 +178,22 @@  discard block
 block discarded – undo
178 178
 		$migrated_actions_count   = $this->primary_store->action_counts();
179 179
 		$actions_count_by_status  = array();
180 180
 
181
-		foreach ( $this->get_status_labels() as $status_key => $status_label ) {
181
+		foreach ($this->get_status_labels() as $status_key => $status_label) {
182 182
 
183 183
 			$count = 0;
184 184
 
185
-			if ( isset( $unmigrated_actions_count[ $status_key ] ) ) {
186
-				$count += $unmigrated_actions_count[ $status_key ];
185
+			if (isset($unmigrated_actions_count[$status_key])) {
186
+				$count += $unmigrated_actions_count[$status_key];
187 187
 			}
188 188
 
189
-			if ( isset( $migrated_actions_count[ $status_key ] ) ) {
190
-				$count += $migrated_actions_count[ $status_key ];
189
+			if (isset($migrated_actions_count[$status_key])) {
190
+				$count += $migrated_actions_count[$status_key];
191 191
 			}
192 192
 
193
-			$actions_count_by_status[ $status_key ] = $count;
193
+			$actions_count_by_status[$status_key] = $count;
194 194
 		}
195 195
 
196
-		$actions_count_by_status = array_filter( $actions_count_by_status );
196
+		$actions_count_by_status = array_filter($actions_count_by_status);
197 197
 
198 198
 		return $actions_count_by_status;
199 199
 	}
@@ -208,17 +208,17 @@  discard block
 block discarded – undo
208 208
 	 *
209 209
 	 * @return ActionScheduler_ActionClaim
210 210
 	 */
211
-	public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' ) {
212
-		$claim = $this->secondary_store->stake_claim( $max_actions, $before_date, $hooks, $group );
211
+	public function stake_claim($max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '') {
212
+		$claim = $this->secondary_store->stake_claim($max_actions, $before_date, $hooks, $group);
213 213
 
214 214
 		$claimed_actions = $claim->get_actions();
215
-		if ( ! empty( $claimed_actions ) ) {
216
-			$this->migrate( $claimed_actions );
215
+		if ( ! empty($claimed_actions)) {
216
+			$this->migrate($claimed_actions);
217 217
 		}
218 218
 
219
-		$this->secondary_store->release_claim( $claim );
219
+		$this->secondary_store->release_claim($claim);
220 220
 
221
-		return $this->primary_store->stake_claim( $max_actions, $before_date, $hooks, $group );
221
+		return $this->primary_store->stake_claim($max_actions, $before_date, $hooks, $group);
222 222
 	}
223 223
 
224 224
 	/**
@@ -226,8 +226,8 @@  discard block
 block discarded – undo
226 226
 	 *
227 227
 	 * @param array $action_ids List of action IDs.
228 228
 	 */
229
-	private function migrate( $action_ids ) {
230
-		$this->migration_runner->migrate_actions( $action_ids );
229
+	private function migrate($action_ids) {
230
+		$this->migration_runner->migrate_actions($action_ids);
231 231
 	}
232 232
 
233 233
 	/**
@@ -238,8 +238,8 @@  discard block
 block discarded – undo
238 238
 	 *
239 239
 	 * @return int The action ID
240 240
 	 */
241
-	public function save_action( ActionScheduler_Action $action, DateTime $date = null ) {
242
-		return $this->primary_store->save_action( $action, $date );
241
+	public function save_action(ActionScheduler_Action $action, DateTime $date = null) {
242
+		return $this->primary_store->save_action($action, $date);
243 243
 	}
244 244
 
245 245
 	/**
@@ -247,10 +247,10 @@  discard block
 block discarded – undo
247 247
 	 *
248 248
 	 * @param int $action_id Action ID.
249 249
 	 */
250
-	public function fetch_action( $action_id ) {
251
-		$store = $this->get_store_from_action_id( $action_id, true );
252
-		if ( $store ) {
253
-			return $store->fetch_action( $action_id );
250
+	public function fetch_action($action_id) {
251
+		$store = $this->get_store_from_action_id($action_id, true);
252
+		if ($store) {
253
+			return $store->fetch_action($action_id);
254 254
 		} else {
255 255
 			return new ActionScheduler_NullAction();
256 256
 		}
@@ -261,10 +261,10 @@  discard block
 block discarded – undo
261 261
 	 *
262 262
 	 * @param int $action_id Action ID.
263 263
 	 */
264
-	public function cancel_action( $action_id ) {
265
-		$store = $this->get_store_from_action_id( $action_id );
266
-		if ( $store ) {
267
-			$store->cancel_action( $action_id );
264
+	public function cancel_action($action_id) {
265
+		$store = $this->get_store_from_action_id($action_id);
266
+		if ($store) {
267
+			$store->cancel_action($action_id);
268 268
 		}
269 269
 	}
270 270
 
@@ -273,10 +273,10 @@  discard block
 block discarded – undo
273 273
 	 *
274 274
 	 * @param int $action_id Action ID.
275 275
 	 */
276
-	public function delete_action( $action_id ) {
277
-		$store = $this->get_store_from_action_id( $action_id );
278
-		if ( $store ) {
279
-			$store->delete_action( $action_id );
276
+	public function delete_action($action_id) {
277
+		$store = $this->get_store_from_action_id($action_id);
278
+		if ($store) {
279
+			$store->delete_action($action_id);
280 280
 		}
281 281
 	}
282 282
 
@@ -285,10 +285,10 @@  discard block
 block discarded – undo
285 285
 	 *
286 286
 	 * @param int $action_id Action ID.
287 287
 	 */
288
-	public function get_date( $action_id ) {
289
-		$store = $this->get_store_from_action_id( $action_id );
290
-		if ( $store ) {
291
-			return $store->get_date( $action_id );
288
+	public function get_date($action_id) {
289
+		$store = $this->get_store_from_action_id($action_id);
290
+		if ($store) {
291
+			return $store->get_date($action_id);
292 292
 		} else {
293 293
 			return null;
294 294
 		}
@@ -299,10 +299,10 @@  discard block
 block discarded – undo
299 299
 	 *
300 300
 	 * @param int $action_id Action ID.
301 301
 	 */
302
-	public function mark_failure( $action_id ) {
303
-		$store = $this->get_store_from_action_id( $action_id );
304
-		if ( $store ) {
305
-			$store->mark_failure( $action_id );
302
+	public function mark_failure($action_id) {
303
+		$store = $this->get_store_from_action_id($action_id);
304
+		if ($store) {
305
+			$store->mark_failure($action_id);
306 306
 		}
307 307
 	}
308 308
 
@@ -311,10 +311,10 @@  discard block
 block discarded – undo
311 311
 	 *
312 312
 	 * @param int $action_id Action ID.
313 313
 	 */
314
-	public function log_execution( $action_id ) {
315
-		$store = $this->get_store_from_action_id( $action_id );
316
-		if ( $store ) {
317
-			$store->log_execution( $action_id );
314
+	public function log_execution($action_id) {
315
+		$store = $this->get_store_from_action_id($action_id);
316
+		if ($store) {
317
+			$store->log_execution($action_id);
318 318
 		}
319 319
 	}
320 320
 
@@ -323,10 +323,10 @@  discard block
 block discarded – undo
323 323
 	 *
324 324
 	 * @param int $action_id Action ID.
325 325
 	 */
326
-	public function mark_complete( $action_id ) {
327
-		$store = $this->get_store_from_action_id( $action_id );
328
-		if ( $store ) {
329
-			$store->mark_complete( $action_id );
326
+	public function mark_complete($action_id) {
327
+		$store = $this->get_store_from_action_id($action_id);
328
+		if ($store) {
329
+			$store->mark_complete($action_id);
330 330
 		}
331 331
 	}
332 332
 
@@ -335,10 +335,10 @@  discard block
 block discarded – undo
335 335
 	 *
336 336
 	 * @param int $action_id Action ID.
337 337
 	 */
338
-	public function get_status( $action_id ) {
339
-		$store = $this->get_store_from_action_id( $action_id );
340
-		if ( $store ) {
341
-			return $store->get_status( $action_id );
338
+	public function get_status($action_id) {
339
+		$store = $this->get_store_from_action_id($action_id);
340
+		if ($store) {
341
+			return $store->get_status($action_id);
342 342
 		}
343 343
 		return null;
344 344
 	}
@@ -350,13 +350,13 @@  discard block
 block discarded – undo
350 350
 	 * @param bool $primary_first Optional flag indicating search the primary store first.
351 351
 	 * @return ActionScheduler_Store
352 352
 	 */
353
-	protected function get_store_from_action_id( $action_id, $primary_first = false ) {
354
-		if ( $primary_first ) {
353
+	protected function get_store_from_action_id($action_id, $primary_first = false) {
354
+		if ($primary_first) {
355 355
 			$stores = array(
356 356
 				$this->primary_store,
357 357
 				$this->secondary_store,
358 358
 			);
359
-		} elseif ( $action_id < $this->demarkation_id ) {
359
+		} elseif ($action_id < $this->demarkation_id) {
360 360
 			$stores = array(
361 361
 				$this->secondary_store,
362 362
 				$this->primary_store,
@@ -367,9 +367,9 @@  discard block
 block discarded – undo
367 367
 			);
368 368
 		}
369 369
 
370
-		foreach ( $stores as $store ) {
371
-			$action = $store->fetch_action( $action_id );
372
-			if ( ! is_a( $action, 'ActionScheduler_NullAction' ) ) {
370
+		foreach ($stores as $store) {
371
+			$action = $store->fetch_action($action_id);
372
+			if ( ! is_a($action, 'ActionScheduler_NullAction')) {
373 373
 				return $store;
374 374
 			}
375 375
 		}
@@ -394,8 +394,8 @@  discard block
 block discarded – undo
394 394
 	 *
395 395
 	 * @param int $action_id Action ID.
396 396
 	 */
397
-	public function get_claim_id( $action_id ) {
398
-		return $this->primary_store->get_claim_id( $action_id );
397
+	public function get_claim_id($action_id) {
398
+		return $this->primary_store->get_claim_id($action_id);
399 399
 	}
400 400
 
401 401
 	/**
@@ -403,8 +403,8 @@  discard block
 block discarded – undo
403 403
 	 *
404 404
 	 * @param ActionScheduler_ActionClaim $claim Claim object.
405 405
 	 */
406
-	public function release_claim( ActionScheduler_ActionClaim $claim ) {
407
-		$this->primary_store->release_claim( $claim );
406
+	public function release_claim(ActionScheduler_ActionClaim $claim) {
407
+		$this->primary_store->release_claim($claim);
408 408
 	}
409 409
 
410 410
 	/**
@@ -412,8 +412,8 @@  discard block
 block discarded – undo
412 412
 	 *
413 413
 	 * @param int $action_id Action ID.
414 414
 	 */
415
-	public function unclaim_action( $action_id ) {
416
-		$this->primary_store->unclaim_action( $action_id );
415
+	public function unclaim_action($action_id) {
416
+		$this->primary_store->unclaim_action($action_id);
417 417
 	}
418 418
 
419 419
 	/**
@@ -421,7 +421,7 @@  discard block
 block discarded – undo
421 421
 	 *
422 422
 	 * @param int $claim_id Claim ID.
423 423
 	 */
424
-	public function find_actions_by_claim_id( $claim_id ) {
425
-		return $this->primary_store->find_actions_by_claim_id( $claim_id );
424
+	public function find_actions_by_claim_id($claim_id) {
425
+		return $this->primary_store->find_actions_by_claim_id($claim_id);
426 426
 	}
427 427
 }
Please login to merge, or discard this patch.
classes/data-stores/ActionScheduler_wpPostStore_PostTypeRegistrar.php 2 patches
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -6,46 +6,46 @@
 block discarded – undo
6 6
  * @codeCoverageIgnore
7 7
  */
8 8
 class ActionScheduler_wpPostStore_PostTypeRegistrar {
9
-	public function register() {
10
-		register_post_type( ActionScheduler_wpPostStore::POST_TYPE, $this->post_type_args() );
11
-	}
9
+    public function register() {
10
+        register_post_type( ActionScheduler_wpPostStore::POST_TYPE, $this->post_type_args() );
11
+    }
12 12
 
13
-	/**
14
-	 * Build the args array for the post type definition
15
-	 *
16
-	 * @return array
17
-	 */
18
-	protected function post_type_args() {
19
-		$args = array(
20
-			'label'        => __( 'Scheduled Actions', 'action-scheduler' ),
21
-			'description'  => __( 'Scheduled actions are hooks triggered on a cetain date and time.', 'action-scheduler' ),
22
-			'public'       => false,
23
-			'map_meta_cap' => true,
24
-			'hierarchical' => false,
25
-			'supports'     => array( 'title', 'editor', 'comments' ),
26
-			'rewrite'      => false,
27
-			'query_var'    => false,
28
-			'can_export'   => true,
29
-			'ep_mask'      => EP_NONE,
30
-			'labels'       => array(
31
-				'name'               => __( 'Scheduled Actions', 'action-scheduler' ),
32
-				'singular_name'      => __( 'Scheduled Action', 'action-scheduler' ),
33
-				'menu_name'          => _x( 'Scheduled Actions', 'Admin menu name', 'action-scheduler' ),
34
-				'add_new'            => __( 'Add', 'action-scheduler' ),
35
-				'add_new_item'       => __( 'Add New Scheduled Action', 'action-scheduler' ),
36
-				'edit'               => __( 'Edit', 'action-scheduler' ),
37
-				'edit_item'          => __( 'Edit Scheduled Action', 'action-scheduler' ),
38
-				'new_item'           => __( 'New Scheduled Action', 'action-scheduler' ),
39
-				'view'               => __( 'View Action', 'action-scheduler' ),
40
-				'view_item'          => __( 'View Action', 'action-scheduler' ),
41
-				'search_items'       => __( 'Search Scheduled Actions', 'action-scheduler' ),
42
-				'not_found'          => __( 'No actions found', 'action-scheduler' ),
43
-				'not_found_in_trash' => __( 'No actions found in trash', 'action-scheduler' ),
44
-			),
45
-		);
13
+    /**
14
+     * Build the args array for the post type definition
15
+     *
16
+     * @return array
17
+     */
18
+    protected function post_type_args() {
19
+        $args = array(
20
+            'label'        => __( 'Scheduled Actions', 'action-scheduler' ),
21
+            'description'  => __( 'Scheduled actions are hooks triggered on a cetain date and time.', 'action-scheduler' ),
22
+            'public'       => false,
23
+            'map_meta_cap' => true,
24
+            'hierarchical' => false,
25
+            'supports'     => array( 'title', 'editor', 'comments' ),
26
+            'rewrite'      => false,
27
+            'query_var'    => false,
28
+            'can_export'   => true,
29
+            'ep_mask'      => EP_NONE,
30
+            'labels'       => array(
31
+                'name'               => __( 'Scheduled Actions', 'action-scheduler' ),
32
+                'singular_name'      => __( 'Scheduled Action', 'action-scheduler' ),
33
+                'menu_name'          => _x( 'Scheduled Actions', 'Admin menu name', 'action-scheduler' ),
34
+                'add_new'            => __( 'Add', 'action-scheduler' ),
35
+                'add_new_item'       => __( 'Add New Scheduled Action', 'action-scheduler' ),
36
+                'edit'               => __( 'Edit', 'action-scheduler' ),
37
+                'edit_item'          => __( 'Edit Scheduled Action', 'action-scheduler' ),
38
+                'new_item'           => __( 'New Scheduled Action', 'action-scheduler' ),
39
+                'view'               => __( 'View Action', 'action-scheduler' ),
40
+                'view_item'          => __( 'View Action', 'action-scheduler' ),
41
+                'search_items'       => __( 'Search Scheduled Actions', 'action-scheduler' ),
42
+                'not_found'          => __( 'No actions found', 'action-scheduler' ),
43
+                'not_found_in_trash' => __( 'No actions found in trash', 'action-scheduler' ),
44
+            ),
45
+        );
46 46
 
47
-		$args = apply_filters( 'action_scheduler_post_type_args', $args );
48
-		return $args;
49
-	}
47
+        $args = apply_filters( 'action_scheduler_post_type_args', $args );
48
+        return $args;
49
+    }
50 50
 }
51 51
 
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -7,7 +7,7 @@  discard block
 block discarded – undo
7 7
  */
8 8
 class ActionScheduler_wpPostStore_PostTypeRegistrar {
9 9
 	public function register() {
10
-		register_post_type( ActionScheduler_wpPostStore::POST_TYPE, $this->post_type_args() );
10
+		register_post_type(ActionScheduler_wpPostStore::POST_TYPE, $this->post_type_args());
11 11
 	}
12 12
 
13 13
 	/**
@@ -17,34 +17,34 @@  discard block
 block discarded – undo
17 17
 	 */
18 18
 	protected function post_type_args() {
19 19
 		$args = array(
20
-			'label'        => __( 'Scheduled Actions', 'action-scheduler' ),
21
-			'description'  => __( 'Scheduled actions are hooks triggered on a cetain date and time.', 'action-scheduler' ),
20
+			'label'        => __('Scheduled Actions', 'action-scheduler'),
21
+			'description'  => __('Scheduled actions are hooks triggered on a cetain date and time.', 'action-scheduler'),
22 22
 			'public'       => false,
23 23
 			'map_meta_cap' => true,
24 24
 			'hierarchical' => false,
25
-			'supports'     => array( 'title', 'editor', 'comments' ),
25
+			'supports'     => array('title', 'editor', 'comments'),
26 26
 			'rewrite'      => false,
27 27
 			'query_var'    => false,
28 28
 			'can_export'   => true,
29 29
 			'ep_mask'      => EP_NONE,
30 30
 			'labels'       => array(
31
-				'name'               => __( 'Scheduled Actions', 'action-scheduler' ),
32
-				'singular_name'      => __( 'Scheduled Action', 'action-scheduler' ),
33
-				'menu_name'          => _x( 'Scheduled Actions', 'Admin menu name', 'action-scheduler' ),
34
-				'add_new'            => __( 'Add', 'action-scheduler' ),
35
-				'add_new_item'       => __( 'Add New Scheduled Action', 'action-scheduler' ),
36
-				'edit'               => __( 'Edit', 'action-scheduler' ),
37
-				'edit_item'          => __( 'Edit Scheduled Action', 'action-scheduler' ),
38
-				'new_item'           => __( 'New Scheduled Action', 'action-scheduler' ),
39
-				'view'               => __( 'View Action', 'action-scheduler' ),
40
-				'view_item'          => __( 'View Action', 'action-scheduler' ),
41
-				'search_items'       => __( 'Search Scheduled Actions', 'action-scheduler' ),
42
-				'not_found'          => __( 'No actions found', 'action-scheduler' ),
43
-				'not_found_in_trash' => __( 'No actions found in trash', 'action-scheduler' ),
31
+				'name'               => __('Scheduled Actions', 'action-scheduler'),
32
+				'singular_name'      => __('Scheduled Action', 'action-scheduler'),
33
+				'menu_name'          => _x('Scheduled Actions', 'Admin menu name', 'action-scheduler'),
34
+				'add_new'            => __('Add', 'action-scheduler'),
35
+				'add_new_item'       => __('Add New Scheduled Action', 'action-scheduler'),
36
+				'edit'               => __('Edit', 'action-scheduler'),
37
+				'edit_item'          => __('Edit Scheduled Action', 'action-scheduler'),
38
+				'new_item'           => __('New Scheduled Action', 'action-scheduler'),
39
+				'view'               => __('View Action', 'action-scheduler'),
40
+				'view_item'          => __('View Action', 'action-scheduler'),
41
+				'search_items'       => __('Search Scheduled Actions', 'action-scheduler'),
42
+				'not_found'          => __('No actions found', 'action-scheduler'),
43
+				'not_found_in_trash' => __('No actions found in trash', 'action-scheduler'),
44 44
 			),
45 45
 		);
46 46
 
47
-		$args = apply_filters( 'action_scheduler_post_type_args', $args );
47
+		$args = apply_filters('action_scheduler_post_type_args', $args);
48 48
 		return $args;
49 49
 	}
50 50
 }
Please login to merge, or discard this patch.
classes/data-stores/ActionScheduler_wpPostStore_TaxonomyRegistrar.php 2 patches
Indentation   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -6,22 +6,22 @@
 block discarded – undo
6 6
  * @codeCoverageIgnore
7 7
  */
8 8
 class ActionScheduler_wpPostStore_TaxonomyRegistrar {
9
-	public function register() {
10
-		register_taxonomy( ActionScheduler_wpPostStore::GROUP_TAXONOMY, ActionScheduler_wpPostStore::POST_TYPE, $this->taxonomy_args() );
11
-	}
9
+    public function register() {
10
+        register_taxonomy( ActionScheduler_wpPostStore::GROUP_TAXONOMY, ActionScheduler_wpPostStore::POST_TYPE, $this->taxonomy_args() );
11
+    }
12 12
 
13
-	protected function taxonomy_args() {
14
-		$args = array(
15
-			'label'             => __( 'Action Group', 'action-scheduler' ),
16
-			'public'            => false,
17
-			'hierarchical'      => false,
18
-			'show_admin_column' => true,
19
-			'query_var'         => false,
20
-			'rewrite'           => false,
21
-		);
13
+    protected function taxonomy_args() {
14
+        $args = array(
15
+            'label'             => __( 'Action Group', 'action-scheduler' ),
16
+            'public'            => false,
17
+            'hierarchical'      => false,
18
+            'show_admin_column' => true,
19
+            'query_var'         => false,
20
+            'rewrite'           => false,
21
+        );
22 22
 
23
-		$args = apply_filters( 'action_scheduler_taxonomy_args', $args );
24
-		return $args;
25
-	}
23
+        $args = apply_filters( 'action_scheduler_taxonomy_args', $args );
24
+        return $args;
25
+    }
26 26
 }
27 27
 
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -7,12 +7,12 @@  discard block
 block discarded – undo
7 7
  */
8 8
 class ActionScheduler_wpPostStore_TaxonomyRegistrar {
9 9
 	public function register() {
10
-		register_taxonomy( ActionScheduler_wpPostStore::GROUP_TAXONOMY, ActionScheduler_wpPostStore::POST_TYPE, $this->taxonomy_args() );
10
+		register_taxonomy(ActionScheduler_wpPostStore::GROUP_TAXONOMY, ActionScheduler_wpPostStore::POST_TYPE, $this->taxonomy_args());
11 11
 	}
12 12
 
13 13
 	protected function taxonomy_args() {
14 14
 		$args = array(
15
-			'label'             => __( 'Action Group', 'action-scheduler' ),
15
+			'label'             => __('Action Group', 'action-scheduler'),
16 16
 			'public'            => false,
17 17
 			'hierarchical'      => false,
18 18
 			'show_admin_column' => true,
@@ -20,7 +20,7 @@  discard block
 block discarded – undo
20 20
 			'rewrite'           => false,
21 21
 		);
22 22
 
23
-		$args = apply_filters( 'action_scheduler_taxonomy_args', $args );
23
+		$args = apply_filters('action_scheduler_taxonomy_args', $args);
24 24
 		return $args;
25 25
 	}
26 26
 }
Please login to merge, or discard this patch.
libraries/action-scheduler/classes/ActionScheduler_FatalErrorMonitor.php 2 patches
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -4,52 +4,52 @@
 block discarded – undo
4 4
  * Class ActionScheduler_FatalErrorMonitor
5 5
  */
6 6
 class ActionScheduler_FatalErrorMonitor {
7
-	/** @var ActionScheduler_ActionClaim */
8
-	private $claim = null;
9
-	/** @var ActionScheduler_Store */
10
-	private $store     = null;
11
-	private $action_id = 0;
7
+    /** @var ActionScheduler_ActionClaim */
8
+    private $claim = null;
9
+    /** @var ActionScheduler_Store */
10
+    private $store     = null;
11
+    private $action_id = 0;
12 12
 
13
-	public function __construct( ActionScheduler_Store $store ) {
14
-		$this->store = $store;
15
-	}
13
+    public function __construct( ActionScheduler_Store $store ) {
14
+        $this->store = $store;
15
+    }
16 16
 
17
-	public function attach( ActionScheduler_ActionClaim $claim ) {
18
-		$this->claim = $claim;
19
-		add_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) );
20
-		add_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0, 1 );
21
-		add_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0, 0 );
22
-		add_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0, 0 );
23
-		add_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0, 0 );
24
-	}
17
+    public function attach( ActionScheduler_ActionClaim $claim ) {
18
+        $this->claim = $claim;
19
+        add_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) );
20
+        add_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0, 1 );
21
+        add_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0, 0 );
22
+        add_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0, 0 );
23
+        add_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0, 0 );
24
+    }
25 25
 
26
-	public function detach() {
27
-		$this->claim = null;
28
-		$this->untrack_action();
29
-		remove_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) );
30
-		remove_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0 );
31
-		remove_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0 );
32
-		remove_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0 );
33
-		remove_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0 );
34
-	}
26
+    public function detach() {
27
+        $this->claim = null;
28
+        $this->untrack_action();
29
+        remove_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) );
30
+        remove_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0 );
31
+        remove_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0 );
32
+        remove_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0 );
33
+        remove_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0 );
34
+    }
35 35
 
36
-	public function track_current_action( $action_id ) {
37
-		$this->action_id = $action_id;
38
-	}
36
+    public function track_current_action( $action_id ) {
37
+        $this->action_id = $action_id;
38
+    }
39 39
 
40
-	public function untrack_action() {
41
-		$this->action_id = 0;
42
-	}
40
+    public function untrack_action() {
41
+        $this->action_id = 0;
42
+    }
43 43
 
44
-	public function handle_unexpected_shutdown() {
45
-		if ( $error = error_get_last() ) {
46
-			if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ) ) ) {
47
-				if ( ! empty( $this->action_id ) ) {
48
-					$this->store->mark_failure( $this->action_id );
49
-					do_action( 'action_scheduler_unexpected_shutdown', $this->action_id, $error );
50
-				}
51
-			}
52
-			$this->store->release_claim( $this->claim );
53
-		}
54
-	}
44
+    public function handle_unexpected_shutdown() {
45
+        if ( $error = error_get_last() ) {
46
+            if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ) ) ) {
47
+                if ( ! empty( $this->action_id ) ) {
48
+                    $this->store->mark_failure( $this->action_id );
49
+                    do_action( 'action_scheduler_unexpected_shutdown', $this->action_id, $error );
50
+                }
51
+            }
52
+            $this->store->release_claim( $this->claim );
53
+        }
54
+    }
55 55
 }
Please login to merge, or discard this patch.
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -10,30 +10,30 @@  discard block
 block discarded – undo
10 10
 	private $store     = null;
11 11
 	private $action_id = 0;
12 12
 
13
-	public function __construct( ActionScheduler_Store $store ) {
13
+	public function __construct(ActionScheduler_Store $store) {
14 14
 		$this->store = $store;
15 15
 	}
16 16
 
17
-	public function attach( ActionScheduler_ActionClaim $claim ) {
17
+	public function attach(ActionScheduler_ActionClaim $claim) {
18 18
 		$this->claim = $claim;
19
-		add_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) );
20
-		add_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0, 1 );
21
-		add_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0, 0 );
22
-		add_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0, 0 );
23
-		add_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0, 0 );
19
+		add_action('shutdown', array($this, 'handle_unexpected_shutdown'));
20
+		add_action('action_scheduler_before_execute', array($this, 'track_current_action'), 0, 1);
21
+		add_action('action_scheduler_after_execute', array($this, 'untrack_action'), 0, 0);
22
+		add_action('action_scheduler_execution_ignored', array($this, 'untrack_action'), 0, 0);
23
+		add_action('action_scheduler_failed_execution', array($this, 'untrack_action'), 0, 0);
24 24
 	}
25 25
 
26 26
 	public function detach() {
27 27
 		$this->claim = null;
28 28
 		$this->untrack_action();
29
-		remove_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) );
30
-		remove_action( 'action_scheduler_before_execute', array( $this, 'track_current_action' ), 0 );
31
-		remove_action( 'action_scheduler_after_execute', array( $this, 'untrack_action' ), 0 );
32
-		remove_action( 'action_scheduler_execution_ignored', array( $this, 'untrack_action' ), 0 );
33
-		remove_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0 );
29
+		remove_action('shutdown', array($this, 'handle_unexpected_shutdown'));
30
+		remove_action('action_scheduler_before_execute', array($this, 'track_current_action'), 0);
31
+		remove_action('action_scheduler_after_execute', array($this, 'untrack_action'), 0);
32
+		remove_action('action_scheduler_execution_ignored', array($this, 'untrack_action'), 0);
33
+		remove_action('action_scheduler_failed_execution', array($this, 'untrack_action'), 0);
34 34
 	}
35 35
 
36
-	public function track_current_action( $action_id ) {
36
+	public function track_current_action($action_id) {
37 37
 		$this->action_id = $action_id;
38 38
 	}
39 39
 
@@ -42,14 +42,14 @@  discard block
 block discarded – undo
42 42
 	}
43 43
 
44 44
 	public function handle_unexpected_shutdown() {
45
-		if ( $error = error_get_last() ) {
46
-			if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ) ) ) {
47
-				if ( ! empty( $this->action_id ) ) {
48
-					$this->store->mark_failure( $this->action_id );
49
-					do_action( 'action_scheduler_unexpected_shutdown', $this->action_id, $error );
45
+		if ($error = error_get_last()) {
46
+			if (in_array($error['type'], array(E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR))) {
47
+				if ( ! empty($this->action_id)) {
48
+					$this->store->mark_failure($this->action_id);
49
+					do_action('action_scheduler_unexpected_shutdown', $this->action_id, $error);
50 50
 				}
51 51
 			}
52
-			$this->store->release_claim( $this->claim );
52
+			$this->store->release_claim($this->claim);
53 53
 		}
54 54
 	}
55 55
 }
Please login to merge, or discard this patch.
src/libraries/action-scheduler/classes/ActionScheduler_QueueCleaner.php 2 patches
Indentation   +156 added lines, -156 removed lines patch added patch discarded remove patch
@@ -5,160 +5,160 @@
 block discarded – undo
5 5
  */
6 6
 class ActionScheduler_QueueCleaner {
7 7
 
8
-	/** @var int */
9
-	protected $batch_size;
10
-
11
-	/** @var ActionScheduler_Store */
12
-	private $store = null;
13
-
14
-	/**
15
-	 * 31 days in seconds.
16
-	 *
17
-	 * @var int
18
-	 */
19
-	private $month_in_seconds = 2678400;
20
-
21
-	/**
22
-	 * ActionScheduler_QueueCleaner constructor.
23
-	 *
24
-	 * @param ActionScheduler_Store $store      The store instance.
25
-	 * @param int                   $batch_size The batch size.
26
-	 */
27
-	public function __construct( ActionScheduler_Store $store = null, $batch_size = 20 ) {
28
-		$this->store      = $store ? $store : ActionScheduler_Store::instance();
29
-		$this->batch_size = $batch_size;
30
-	}
31
-
32
-	public function delete_old_actions() {
33
-		$lifespan = apply_filters( 'action_scheduler_retention_period', $this->month_in_seconds );
34
-		$cutoff   = as_get_datetime_object( $lifespan . ' seconds ago' );
35
-
36
-		$statuses_to_purge = array(
37
-			ActionScheduler_Store::STATUS_COMPLETE,
38
-			ActionScheduler_Store::STATUS_CANCELED,
39
-		);
40
-
41
-		foreach ( $statuses_to_purge as $status ) {
42
-			$actions_to_delete = $this->store->query_actions(
43
-				array(
44
-					'status'           => $status,
45
-					'modified'         => $cutoff,
46
-					'modified_compare' => '<=',
47
-					'per_page'         => $this->get_batch_size(),
48
-					'orderby'          => 'none',
49
-				)
50
-			);
51
-
52
-			foreach ( $actions_to_delete as $action_id ) {
53
-				try {
54
-					$this->store->delete_action( $action_id );
55
-				} catch ( Exception $e ) {
56
-
57
-					/**
58
-					 * Notify 3rd party code of exceptions when deleting a completed action older than the retention period
59
-					 *
60
-					 * This hook provides a way for 3rd party code to log or otherwise handle exceptions relating to their
61
-					 * actions.
62
-					 *
63
-					 * @since 2.0.0
64
-					 *
65
-					 * @param int $action_id The scheduled actions ID in the data store
66
-					 * @param Exception $e The exception thrown when attempting to delete the action from the data store
67
-					 * @param int $lifespan The retention period, in seconds, for old actions
68
-					 * @param int $count_of_actions_to_delete The number of old actions being deleted in this batch
69
-					 */
70
-					do_action( 'action_scheduler_failed_old_action_deletion', $action_id, $e, $lifespan, count( $actions_to_delete ) );
71
-				}
72
-			}
73
-		}
74
-	}
75
-
76
-	/**
77
-	 * Unclaim pending actions that have not been run within a given time limit.
78
-	 *
79
-	 * When called by ActionScheduler_Abstract_QueueRunner::run_cleanup(), the time limit passed
80
-	 * as a parameter is 10x the time limit used for queue processing.
81
-	 *
82
-	 * @param int $time_limit The number of seconds to allow a queue to run before unclaiming its pending actions. Default 300 (5 minutes).
83
-	 */
84
-	public function reset_timeouts( $time_limit = 300 ) {
85
-		$timeout = apply_filters( 'action_scheduler_timeout_period', $time_limit );
86
-		if ( $timeout < 0 ) {
87
-			return;
88
-		}
89
-		$cutoff           = as_get_datetime_object( $timeout . ' seconds ago' );
90
-		$actions_to_reset = $this->store->query_actions(
91
-			array(
92
-				'status'           => ActionScheduler_Store::STATUS_PENDING,
93
-				'modified'         => $cutoff,
94
-				'modified_compare' => '<=',
95
-				'claimed'          => true,
96
-				'per_page'         => $this->get_batch_size(),
97
-				'orderby'          => 'none',
98
-			)
99
-		);
100
-
101
-		foreach ( $actions_to_reset as $action_id ) {
102
-			$this->store->unclaim_action( $action_id );
103
-			do_action( 'action_scheduler_reset_action', $action_id );
104
-		}
105
-	}
106
-
107
-	/**
108
-	 * Mark actions that have been running for more than a given time limit as failed, based on
109
-	 * the assumption some uncatachable and unloggable fatal error occurred during processing.
110
-	 *
111
-	 * When called by ActionScheduler_Abstract_QueueRunner::run_cleanup(), the time limit passed
112
-	 * as a parameter is 10x the time limit used for queue processing.
113
-	 *
114
-	 * @param int $time_limit The number of seconds to allow an action to run before it is considered to have failed. Default 300 (5 minutes).
115
-	 */
116
-	public function mark_failures( $time_limit = 300 ) {
117
-		$timeout = apply_filters( 'action_scheduler_failure_period', $time_limit );
118
-		if ( $timeout < 0 ) {
119
-			return;
120
-		}
121
-		$cutoff           = as_get_datetime_object( $timeout . ' seconds ago' );
122
-		$actions_to_reset = $this->store->query_actions(
123
-			array(
124
-				'status'           => ActionScheduler_Store::STATUS_RUNNING,
125
-				'modified'         => $cutoff,
126
-				'modified_compare' => '<=',
127
-				'per_page'         => $this->get_batch_size(),
128
-				'orderby'          => 'none',
129
-			)
130
-		);
131
-
132
-		foreach ( $actions_to_reset as $action_id ) {
133
-			$this->store->mark_failure( $action_id );
134
-			do_action( 'action_scheduler_failed_action', $action_id, $timeout );
135
-		}
136
-	}
137
-
138
-	/**
139
-	 * Do all of the cleaning actions.
140
-	 *
141
-	 * @param int $time_limit The number of seconds to use as the timeout and failure period. Default 300 (5 minutes).
142
-	 * @author Jeremy Pry
143
-	 */
144
-	public function clean( $time_limit = 300 ) {
145
-		$this->delete_old_actions();
146
-		$this->reset_timeouts( $time_limit );
147
-		$this->mark_failures( $time_limit );
148
-	}
149
-
150
-	/**
151
-	 * Get the batch size for cleaning the queue.
152
-	 *
153
-	 * @author Jeremy Pry
154
-	 * @return int
155
-	 */
156
-	protected function get_batch_size() {
157
-		/**
158
-		 * Filter the batch size when cleaning the queue.
159
-		 *
160
-		 * @param int $batch_size The number of actions to clean in one batch.
161
-		 */
162
-		return absint( apply_filters( 'action_scheduler_cleanup_batch_size', $this->batch_size ) );
163
-	}
8
+    /** @var int */
9
+    protected $batch_size;
10
+
11
+    /** @var ActionScheduler_Store */
12
+    private $store = null;
13
+
14
+    /**
15
+     * 31 days in seconds.
16
+     *
17
+     * @var int
18
+     */
19
+    private $month_in_seconds = 2678400;
20
+
21
+    /**
22
+     * ActionScheduler_QueueCleaner constructor.
23
+     *
24
+     * @param ActionScheduler_Store $store      The store instance.
25
+     * @param int                   $batch_size The batch size.
26
+     */
27
+    public function __construct( ActionScheduler_Store $store = null, $batch_size = 20 ) {
28
+        $this->store      = $store ? $store : ActionScheduler_Store::instance();
29
+        $this->batch_size = $batch_size;
30
+    }
31
+
32
+    public function delete_old_actions() {
33
+        $lifespan = apply_filters( 'action_scheduler_retention_period', $this->month_in_seconds );
34
+        $cutoff   = as_get_datetime_object( $lifespan . ' seconds ago' );
35
+
36
+        $statuses_to_purge = array(
37
+            ActionScheduler_Store::STATUS_COMPLETE,
38
+            ActionScheduler_Store::STATUS_CANCELED,
39
+        );
40
+
41
+        foreach ( $statuses_to_purge as $status ) {
42
+            $actions_to_delete = $this->store->query_actions(
43
+                array(
44
+                    'status'           => $status,
45
+                    'modified'         => $cutoff,
46
+                    'modified_compare' => '<=',
47
+                    'per_page'         => $this->get_batch_size(),
48
+                    'orderby'          => 'none',
49
+                )
50
+            );
51
+
52
+            foreach ( $actions_to_delete as $action_id ) {
53
+                try {
54
+                    $this->store->delete_action( $action_id );
55
+                } catch ( Exception $e ) {
56
+
57
+                    /**
58
+                     * Notify 3rd party code of exceptions when deleting a completed action older than the retention period
59
+                     *
60
+                     * This hook provides a way for 3rd party code to log or otherwise handle exceptions relating to their
61
+                     * actions.
62
+                     *
63
+                     * @since 2.0.0
64
+                     *
65
+                     * @param int $action_id The scheduled actions ID in the data store
66
+                     * @param Exception $e The exception thrown when attempting to delete the action from the data store
67
+                     * @param int $lifespan The retention period, in seconds, for old actions
68
+                     * @param int $count_of_actions_to_delete The number of old actions being deleted in this batch
69
+                     */
70
+                    do_action( 'action_scheduler_failed_old_action_deletion', $action_id, $e, $lifespan, count( $actions_to_delete ) );
71
+                }
72
+            }
73
+        }
74
+    }
75
+
76
+    /**
77
+     * Unclaim pending actions that have not been run within a given time limit.
78
+     *
79
+     * When called by ActionScheduler_Abstract_QueueRunner::run_cleanup(), the time limit passed
80
+     * as a parameter is 10x the time limit used for queue processing.
81
+     *
82
+     * @param int $time_limit The number of seconds to allow a queue to run before unclaiming its pending actions. Default 300 (5 minutes).
83
+     */
84
+    public function reset_timeouts( $time_limit = 300 ) {
85
+        $timeout = apply_filters( 'action_scheduler_timeout_period', $time_limit );
86
+        if ( $timeout < 0 ) {
87
+            return;
88
+        }
89
+        $cutoff           = as_get_datetime_object( $timeout . ' seconds ago' );
90
+        $actions_to_reset = $this->store->query_actions(
91
+            array(
92
+                'status'           => ActionScheduler_Store::STATUS_PENDING,
93
+                'modified'         => $cutoff,
94
+                'modified_compare' => '<=',
95
+                'claimed'          => true,
96
+                'per_page'         => $this->get_batch_size(),
97
+                'orderby'          => 'none',
98
+            )
99
+        );
100
+
101
+        foreach ( $actions_to_reset as $action_id ) {
102
+            $this->store->unclaim_action( $action_id );
103
+            do_action( 'action_scheduler_reset_action', $action_id );
104
+        }
105
+    }
106
+
107
+    /**
108
+     * Mark actions that have been running for more than a given time limit as failed, based on
109
+     * the assumption some uncatachable and unloggable fatal error occurred during processing.
110
+     *
111
+     * When called by ActionScheduler_Abstract_QueueRunner::run_cleanup(), the time limit passed
112
+     * as a parameter is 10x the time limit used for queue processing.
113
+     *
114
+     * @param int $time_limit The number of seconds to allow an action to run before it is considered to have failed. Default 300 (5 minutes).
115
+     */
116
+    public function mark_failures( $time_limit = 300 ) {
117
+        $timeout = apply_filters( 'action_scheduler_failure_period', $time_limit );
118
+        if ( $timeout < 0 ) {
119
+            return;
120
+        }
121
+        $cutoff           = as_get_datetime_object( $timeout . ' seconds ago' );
122
+        $actions_to_reset = $this->store->query_actions(
123
+            array(
124
+                'status'           => ActionScheduler_Store::STATUS_RUNNING,
125
+                'modified'         => $cutoff,
126
+                'modified_compare' => '<=',
127
+                'per_page'         => $this->get_batch_size(),
128
+                'orderby'          => 'none',
129
+            )
130
+        );
131
+
132
+        foreach ( $actions_to_reset as $action_id ) {
133
+            $this->store->mark_failure( $action_id );
134
+            do_action( 'action_scheduler_failed_action', $action_id, $timeout );
135
+        }
136
+    }
137
+
138
+    /**
139
+     * Do all of the cleaning actions.
140
+     *
141
+     * @param int $time_limit The number of seconds to use as the timeout and failure period. Default 300 (5 minutes).
142
+     * @author Jeremy Pry
143
+     */
144
+    public function clean( $time_limit = 300 ) {
145
+        $this->delete_old_actions();
146
+        $this->reset_timeouts( $time_limit );
147
+        $this->mark_failures( $time_limit );
148
+    }
149
+
150
+    /**
151
+     * Get the batch size for cleaning the queue.
152
+     *
153
+     * @author Jeremy Pry
154
+     * @return int
155
+     */
156
+    protected function get_batch_size() {
157
+        /**
158
+         * Filter the batch size when cleaning the queue.
159
+         *
160
+         * @param int $batch_size The number of actions to clean in one batch.
161
+         */
162
+        return absint( apply_filters( 'action_scheduler_cleanup_batch_size', $this->batch_size ) );
163
+    }
164 164
 }
Please login to merge, or discard this patch.
Spacing   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -24,21 +24,21 @@  discard block
 block discarded – undo
24 24
 	 * @param ActionScheduler_Store $store      The store instance.
25 25
 	 * @param int                   $batch_size The batch size.
26 26
 	 */
27
-	public function __construct( ActionScheduler_Store $store = null, $batch_size = 20 ) {
27
+	public function __construct(ActionScheduler_Store $store = null, $batch_size = 20) {
28 28
 		$this->store      = $store ? $store : ActionScheduler_Store::instance();
29 29
 		$this->batch_size = $batch_size;
30 30
 	}
31 31
 
32 32
 	public function delete_old_actions() {
33
-		$lifespan = apply_filters( 'action_scheduler_retention_period', $this->month_in_seconds );
34
-		$cutoff   = as_get_datetime_object( $lifespan . ' seconds ago' );
33
+		$lifespan = apply_filters('action_scheduler_retention_period', $this->month_in_seconds);
34
+		$cutoff   = as_get_datetime_object($lifespan.' seconds ago');
35 35
 
36 36
 		$statuses_to_purge = array(
37 37
 			ActionScheduler_Store::STATUS_COMPLETE,
38 38
 			ActionScheduler_Store::STATUS_CANCELED,
39 39
 		);
40 40
 
41
-		foreach ( $statuses_to_purge as $status ) {
41
+		foreach ($statuses_to_purge as $status) {
42 42
 			$actions_to_delete = $this->store->query_actions(
43 43
 				array(
44 44
 					'status'           => $status,
@@ -49,10 +49,10 @@  discard block
 block discarded – undo
49 49
 				)
50 50
 			);
51 51
 
52
-			foreach ( $actions_to_delete as $action_id ) {
52
+			foreach ($actions_to_delete as $action_id) {
53 53
 				try {
54
-					$this->store->delete_action( $action_id );
55
-				} catch ( Exception $e ) {
54
+					$this->store->delete_action($action_id);
55
+				} catch (Exception $e) {
56 56
 
57 57
 					/**
58 58
 					 * Notify 3rd party code of exceptions when deleting a completed action older than the retention period
@@ -67,7 +67,7 @@  discard block
 block discarded – undo
67 67
 					 * @param int $lifespan The retention period, in seconds, for old actions
68 68
 					 * @param int $count_of_actions_to_delete The number of old actions being deleted in this batch
69 69
 					 */
70
-					do_action( 'action_scheduler_failed_old_action_deletion', $action_id, $e, $lifespan, count( $actions_to_delete ) );
70
+					do_action('action_scheduler_failed_old_action_deletion', $action_id, $e, $lifespan, count($actions_to_delete));
71 71
 				}
72 72
 			}
73 73
 		}
@@ -81,12 +81,12 @@  discard block
 block discarded – undo
81 81
 	 *
82 82
 	 * @param int $time_limit The number of seconds to allow a queue to run before unclaiming its pending actions. Default 300 (5 minutes).
83 83
 	 */
84
-	public function reset_timeouts( $time_limit = 300 ) {
85
-		$timeout = apply_filters( 'action_scheduler_timeout_period', $time_limit );
86
-		if ( $timeout < 0 ) {
84
+	public function reset_timeouts($time_limit = 300) {
85
+		$timeout = apply_filters('action_scheduler_timeout_period', $time_limit);
86
+		if ($timeout < 0) {
87 87
 			return;
88 88
 		}
89
-		$cutoff           = as_get_datetime_object( $timeout . ' seconds ago' );
89
+		$cutoff           = as_get_datetime_object($timeout.' seconds ago');
90 90
 		$actions_to_reset = $this->store->query_actions(
91 91
 			array(
92 92
 				'status'           => ActionScheduler_Store::STATUS_PENDING,
@@ -98,9 +98,9 @@  discard block
 block discarded – undo
98 98
 			)
99 99
 		);
100 100
 
101
-		foreach ( $actions_to_reset as $action_id ) {
102
-			$this->store->unclaim_action( $action_id );
103
-			do_action( 'action_scheduler_reset_action', $action_id );
101
+		foreach ($actions_to_reset as $action_id) {
102
+			$this->store->unclaim_action($action_id);
103
+			do_action('action_scheduler_reset_action', $action_id);
104 104
 		}
105 105
 	}
106 106
 
@@ -113,12 +113,12 @@  discard block
 block discarded – undo
113 113
 	 *
114 114
 	 * @param int $time_limit The number of seconds to allow an action to run before it is considered to have failed. Default 300 (5 minutes).
115 115
 	 */
116
-	public function mark_failures( $time_limit = 300 ) {
117
-		$timeout = apply_filters( 'action_scheduler_failure_period', $time_limit );
118
-		if ( $timeout < 0 ) {
116
+	public function mark_failures($time_limit = 300) {
117
+		$timeout = apply_filters('action_scheduler_failure_period', $time_limit);
118
+		if ($timeout < 0) {
119 119
 			return;
120 120
 		}
121
-		$cutoff           = as_get_datetime_object( $timeout . ' seconds ago' );
121
+		$cutoff           = as_get_datetime_object($timeout.' seconds ago');
122 122
 		$actions_to_reset = $this->store->query_actions(
123 123
 			array(
124 124
 				'status'           => ActionScheduler_Store::STATUS_RUNNING,
@@ -129,9 +129,9 @@  discard block
 block discarded – undo
129 129
 			)
130 130
 		);
131 131
 
132
-		foreach ( $actions_to_reset as $action_id ) {
133
-			$this->store->mark_failure( $action_id );
134
-			do_action( 'action_scheduler_failed_action', $action_id, $timeout );
132
+		foreach ($actions_to_reset as $action_id) {
133
+			$this->store->mark_failure($action_id);
134
+			do_action('action_scheduler_failed_action', $action_id, $timeout);
135 135
 		}
136 136
 	}
137 137
 
@@ -141,10 +141,10 @@  discard block
 block discarded – undo
141 141
 	 * @param int $time_limit The number of seconds to use as the timeout and failure period. Default 300 (5 minutes).
142 142
 	 * @author Jeremy Pry
143 143
 	 */
144
-	public function clean( $time_limit = 300 ) {
144
+	public function clean($time_limit = 300) {
145 145
 		$this->delete_old_actions();
146
-		$this->reset_timeouts( $time_limit );
147
-		$this->mark_failures( $time_limit );
146
+		$this->reset_timeouts($time_limit);
147
+		$this->mark_failures($time_limit);
148 148
 	}
149 149
 
150 150
 	/**
@@ -159,6 +159,6 @@  discard block
 block discarded – undo
159 159
 		 *
160 160
 		 * @param int $batch_size The number of actions to clean in one batch.
161 161
 		 */
162
-		return absint( apply_filters( 'action_scheduler_cleanup_batch_size', $this->batch_size ) );
162
+		return absint(apply_filters('action_scheduler_cleanup_batch_size', $this->batch_size));
163 163
 	}
164 164
 }
Please login to merge, or discard this patch.
src/libraries/action-scheduler/classes/ActionScheduler_AdminView.php 2 patches
Indentation   +238 added lines, -238 removed lines patch added patch discarded remove patch
@@ -7,242 +7,242 @@
 block discarded – undo
7 7
  */
8 8
 class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
9 9
 
10
-	private static $admin_view = null;
11
-
12
-	private static $screen_id = 'tools_page_action-scheduler';
13
-
14
-	/** @var ActionScheduler_ListTable */
15
-	protected $list_table;
16
-
17
-	/**
18
-	 * @return ActionScheduler_AdminView
19
-	 * @codeCoverageIgnore
20
-	 */
21
-	public static function instance() {
22
-
23
-		if ( empty( self::$admin_view ) ) {
24
-			$class            = apply_filters( 'action_scheduler_admin_view_class', 'ActionScheduler_AdminView' );
25
-			self::$admin_view = new $class();
26
-		}
27
-
28
-		return self::$admin_view;
29
-	}
30
-
31
-	/**
32
-	 * @codeCoverageIgnore
33
-	 */
34
-	public function init() {
35
-		if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || false == DOING_AJAX ) ) {
36
-
37
-			if ( class_exists( 'WooCommerce' ) ) {
38
-				add_action( 'woocommerce_admin_status_content_action-scheduler', array( $this, 'render_admin_ui' ) );
39
-				add_action( 'woocommerce_system_status_report', array( $this, 'system_status_report' ) );
40
-				add_filter( 'woocommerce_admin_status_tabs', array( $this, 'register_system_status_tab' ) );
41
-			}
42
-
43
-			add_action( 'admin_menu', array( $this, 'register_menu' ) );
44
-			add_action( 'admin_notices', array( $this, 'maybe_check_pastdue_actions' ) );
45
-			add_action( 'current_screen', array( $this, 'add_help_tabs' ) );
46
-		}
47
-	}
48
-
49
-	public function system_status_report() {
50
-		$table = new ActionScheduler_wcSystemStatus( ActionScheduler::store() );
51
-		$table->render();
52
-	}
53
-
54
-	/**
55
-	 * Registers action-scheduler into WooCommerce > System status.
56
-	 *
57
-	 * @param array $tabs An associative array of tab key => label.
58
-	 * @return array $tabs An associative array of tab key => label, including Action Scheduler's tabs
59
-	 */
60
-	public function register_system_status_tab( array $tabs ) {
61
-		$tabs['action-scheduler'] = __( 'Scheduled Actions', 'action-scheduler' );
62
-
63
-		return $tabs;
64
-	}
65
-
66
-	/**
67
-	 * Include Action Scheduler's administration under the Tools menu.
68
-	 *
69
-	 * A menu under the Tools menu is important for backward compatibility (as that's
70
-	 * where it started), and also provides more convenient access than the WooCommerce
71
-	 * System Status page, and for sites where WooCommerce isn't active.
72
-	 */
73
-	public function register_menu() {
74
-		$hook_suffix = add_submenu_page(
75
-			'tools.php',
76
-			__( 'Scheduled Actions', 'action-scheduler' ),
77
-			__( 'Scheduled Actions', 'action-scheduler' ),
78
-			'manage_options',
79
-			'action-scheduler',
80
-			array( $this, 'render_admin_ui' )
81
-		);
82
-		add_action( 'load-' . $hook_suffix, array( $this, 'process_admin_ui' ) );
83
-	}
84
-
85
-	/**
86
-	 * Triggers processing of any pending actions.
87
-	 */
88
-	public function process_admin_ui() {
89
-		$this->get_list_table();
90
-	}
91
-
92
-	/**
93
-	 * Renders the Admin UI
94
-	 */
95
-	public function render_admin_ui() {
96
-		$table = $this->get_list_table();
97
-		$table->display_page();
98
-	}
99
-
100
-	/**
101
-	 * Get the admin UI object and process any requested actions.
102
-	 *
103
-	 * @return ActionScheduler_ListTable
104
-	 */
105
-	protected function get_list_table() {
106
-		if ( null === $this->list_table ) {
107
-			$this->list_table = new ActionScheduler_ListTable( ActionScheduler::store(), ActionScheduler::logger(), ActionScheduler::runner() );
108
-			$this->list_table->process_actions();
109
-		}
110
-
111
-		return $this->list_table;
112
-	}
113
-
114
-	/**
115
-	 * Action: admin_notices
116
-	 *
117
-	 * Maybe check past-due actions, and print notice.
118
-	 *
119
-	 * @uses $this->check_pastdue_actions()
120
-	 */
121
-	public function maybe_check_pastdue_actions() {
122
-
123
-		// Filter to prevent checking actions (ex: inappropriate user).
124
-		if ( ! apply_filters( 'action_scheduler_check_pastdue_actions', current_user_can( 'manage_options' ) ) ) {
125
-			return;
126
-		}
127
-
128
-		// Get last check transient.
129
-		$last_check = get_transient( 'action_scheduler_last_pastdue_actions_check' );
130
-
131
-		// If transient exists, we're within interval, so bail.
132
-		if ( ! empty( $last_check ) ) {
133
-			return;
134
-		}
135
-
136
-		// Perform the check.
137
-		$this->check_pastdue_actions();
138
-	}
139
-
140
-	/**
141
-	 * Check past-due actions, and print notice.
142
-	 *
143
-	 * @todo update $link_url to "Past-due" filter when released (see issue #510, PR #511)
144
-	 */
145
-	protected function check_pastdue_actions() {
146
-
147
-		// Set thresholds.
148
-		$threshold_seconds = (int) apply_filters( 'action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS );
149
-		$threshhold_min    = (int) apply_filters( 'action_scheduler_pastdue_actions_min', 1 );
150
-
151
-		// Allow third-parties to preempt the default check logic.
152
-		$check = apply_filters( 'action_scheduler_pastdue_actions_check_pre', null );
153
-
154
-		// Scheduled actions query arguments.
155
-		$query_args = array(
156
-			'date'     => as_get_datetime_object( time() - $threshold_seconds ),
157
-			'status'   => ActionScheduler_Store::STATUS_PENDING,
158
-			'per_page' => $threshhold_min,
159
-		);
160
-
161
-		// If no third-party preempted, run default check.
162
-		if ( $check === null ) {
163
-			$store               = ActionScheduler_Store::instance();
164
-			$num_pastdue_actions = (int) $store->query_actions( $query_args, 'count' );
165
-
166
-			// Check if past-due actions count is greater than or equal to threshold.
167
-			$check = ( $num_pastdue_actions >= $threshhold_min );
168
-			$check = (bool) apply_filters( 'action_scheduler_pastdue_actions_check', $check, $num_pastdue_actions, $threshold_seconds, $threshhold_min );
169
-		}
170
-
171
-		// If check failed, set transient and abort.
172
-		if ( ! boolval( $check ) ) {
173
-			$interval = apply_filters( 'action_scheduler_pastdue_actions_check_interval', round( $threshold_seconds / 4 ), $threshold_seconds );
174
-			set_transient( 'action_scheduler_last_pastdue_actions_check', time(), $interval );
175
-
176
-			return;
177
-		}
178
-
179
-		$actions_url = add_query_arg(
180
-			array(
181
-				'page'   => 'action-scheduler',
182
-				'status' => 'past-due',
183
-				'order'  => 'asc',
184
-			),
185
-			admin_url( 'tools.php' )
186
-		);
187
-
188
-		// Print notice.
189
-		echo '<div class="notice notice-warning"><p>';
190
-		printf(
191
-			_n(
192
-				// translators: 1) is the number of affected actions, 2) is a link to an admin screen.
193
-				'<strong>Action Scheduler:</strong> %1$d <a href="%2$s">past-due action</a> found; something may be wrong. <a href="https://actionscheduler.org/faq/#my-site-has-past-due-actions-what-can-i-do" target="_blank">Read documentation &raquo;</a>',
194
-				'<strong>Action Scheduler:</strong> %1$d <a href="%2$s">past-due actions</a> found; something may be wrong. <a href="https://actionscheduler.org/faq/#my-site-has-past-due-actions-what-can-i-do" target="_blank">Read documentation &raquo;</a>',
195
-				$num_pastdue_actions,
196
-				'action-scheduler'
197
-			),
198
-			$num_pastdue_actions,
199
-			esc_attr( esc_url( $actions_url ) )
200
-		);
201
-		echo '</p></div>';
202
-
203
-		// Facilitate third-parties to evaluate and print notices.
204
-		do_action( 'action_scheduler_pastdue_actions_extra_notices', $query_args );
205
-	}
206
-
207
-	/**
208
-	 * Provide more information about the screen and its data in the help tab.
209
-	 */
210
-	public function add_help_tabs() {
211
-		$screen = get_current_screen();
212
-
213
-		if ( ! $screen || self::$screen_id != $screen->id ) {
214
-			return;
215
-		}
216
-
217
-		$as_version = ActionScheduler_Versions::instance()->latest_version();
218
-		$screen->add_help_tab(
219
-			array(
220
-				'id'      => 'action_scheduler_about',
221
-				'title'   => __( 'About', 'action-scheduler' ),
222
-				'content' =>
223
-					'<h2>' . sprintf( __( 'About Action Scheduler %s', 'action-scheduler' ), $as_version ) . '</h2>' .
224
-					'<p>' .
225
-						__( 'Action Scheduler is a scalable, traceable job queue for background processing large sets of actions. Action Scheduler works by triggering an action hook to run at some time in the future. Scheduled actions can also be scheduled to run on a recurring schedule.', 'action-scheduler' ) .
226
-					'</p>',
227
-			)
228
-		);
229
-
230
-		$screen->add_help_tab(
231
-			array(
232
-				'id'      => 'action_scheduler_columns',
233
-				'title'   => __( 'Columns', 'action-scheduler' ),
234
-				'content' =>
235
-					'<h2>' . __( 'Scheduled Action Columns', 'action-scheduler' ) . '</h2>' .
236
-					'<ul>' .
237
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Hook', 'action-scheduler' ), __( 'Name of the action hook that will be triggered.', 'action-scheduler' ) ) .
238
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Status', 'action-scheduler' ), __( 'Action statuses are Pending, Complete, Canceled, Failed', 'action-scheduler' ) ) .
239
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Arguments', 'action-scheduler' ), __( 'Optional data array passed to the action hook.', 'action-scheduler' ) ) .
240
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Group', 'action-scheduler' ), __( 'Optional action group.', 'action-scheduler' ) ) .
241
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Recurrence', 'action-scheduler' ), __( 'The action\'s schedule frequency.', 'action-scheduler' ) ) .
242
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Scheduled', 'action-scheduler' ), __( 'The date/time the action is/was scheduled to run.', 'action-scheduler' ) ) .
243
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Log', 'action-scheduler' ), __( 'Activity log for the action.', 'action-scheduler' ) ) .
244
-					'</ul>',
245
-			)
246
-		);
247
-	}
10
+    private static $admin_view = null;
11
+
12
+    private static $screen_id = 'tools_page_action-scheduler';
13
+
14
+    /** @var ActionScheduler_ListTable */
15
+    protected $list_table;
16
+
17
+    /**
18
+     * @return ActionScheduler_AdminView
19
+     * @codeCoverageIgnore
20
+     */
21
+    public static function instance() {
22
+
23
+        if ( empty( self::$admin_view ) ) {
24
+            $class            = apply_filters( 'action_scheduler_admin_view_class', 'ActionScheduler_AdminView' );
25
+            self::$admin_view = new $class();
26
+        }
27
+
28
+        return self::$admin_view;
29
+    }
30
+
31
+    /**
32
+     * @codeCoverageIgnore
33
+     */
34
+    public function init() {
35
+        if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || false == DOING_AJAX ) ) {
36
+
37
+            if ( class_exists( 'WooCommerce' ) ) {
38
+                add_action( 'woocommerce_admin_status_content_action-scheduler', array( $this, 'render_admin_ui' ) );
39
+                add_action( 'woocommerce_system_status_report', array( $this, 'system_status_report' ) );
40
+                add_filter( 'woocommerce_admin_status_tabs', array( $this, 'register_system_status_tab' ) );
41
+            }
42
+
43
+            add_action( 'admin_menu', array( $this, 'register_menu' ) );
44
+            add_action( 'admin_notices', array( $this, 'maybe_check_pastdue_actions' ) );
45
+            add_action( 'current_screen', array( $this, 'add_help_tabs' ) );
46
+        }
47
+    }
48
+
49
+    public function system_status_report() {
50
+        $table = new ActionScheduler_wcSystemStatus( ActionScheduler::store() );
51
+        $table->render();
52
+    }
53
+
54
+    /**
55
+     * Registers action-scheduler into WooCommerce > System status.
56
+     *
57
+     * @param array $tabs An associative array of tab key => label.
58
+     * @return array $tabs An associative array of tab key => label, including Action Scheduler's tabs
59
+     */
60
+    public function register_system_status_tab( array $tabs ) {
61
+        $tabs['action-scheduler'] = __( 'Scheduled Actions', 'action-scheduler' );
62
+
63
+        return $tabs;
64
+    }
65
+
66
+    /**
67
+     * Include Action Scheduler's administration under the Tools menu.
68
+     *
69
+     * A menu under the Tools menu is important for backward compatibility (as that's
70
+     * where it started), and also provides more convenient access than the WooCommerce
71
+     * System Status page, and for sites where WooCommerce isn't active.
72
+     */
73
+    public function register_menu() {
74
+        $hook_suffix = add_submenu_page(
75
+            'tools.php',
76
+            __( 'Scheduled Actions', 'action-scheduler' ),
77
+            __( 'Scheduled Actions', 'action-scheduler' ),
78
+            'manage_options',
79
+            'action-scheduler',
80
+            array( $this, 'render_admin_ui' )
81
+        );
82
+        add_action( 'load-' . $hook_suffix, array( $this, 'process_admin_ui' ) );
83
+    }
84
+
85
+    /**
86
+     * Triggers processing of any pending actions.
87
+     */
88
+    public function process_admin_ui() {
89
+        $this->get_list_table();
90
+    }
91
+
92
+    /**
93
+     * Renders the Admin UI
94
+     */
95
+    public function render_admin_ui() {
96
+        $table = $this->get_list_table();
97
+        $table->display_page();
98
+    }
99
+
100
+    /**
101
+     * Get the admin UI object and process any requested actions.
102
+     *
103
+     * @return ActionScheduler_ListTable
104
+     */
105
+    protected function get_list_table() {
106
+        if ( null === $this->list_table ) {
107
+            $this->list_table = new ActionScheduler_ListTable( ActionScheduler::store(), ActionScheduler::logger(), ActionScheduler::runner() );
108
+            $this->list_table->process_actions();
109
+        }
110
+
111
+        return $this->list_table;
112
+    }
113
+
114
+    /**
115
+     * Action: admin_notices
116
+     *
117
+     * Maybe check past-due actions, and print notice.
118
+     *
119
+     * @uses $this->check_pastdue_actions()
120
+     */
121
+    public function maybe_check_pastdue_actions() {
122
+
123
+        // Filter to prevent checking actions (ex: inappropriate user).
124
+        if ( ! apply_filters( 'action_scheduler_check_pastdue_actions', current_user_can( 'manage_options' ) ) ) {
125
+            return;
126
+        }
127
+
128
+        // Get last check transient.
129
+        $last_check = get_transient( 'action_scheduler_last_pastdue_actions_check' );
130
+
131
+        // If transient exists, we're within interval, so bail.
132
+        if ( ! empty( $last_check ) ) {
133
+            return;
134
+        }
135
+
136
+        // Perform the check.
137
+        $this->check_pastdue_actions();
138
+    }
139
+
140
+    /**
141
+     * Check past-due actions, and print notice.
142
+     *
143
+     * @todo update $link_url to "Past-due" filter when released (see issue #510, PR #511)
144
+     */
145
+    protected function check_pastdue_actions() {
146
+
147
+        // Set thresholds.
148
+        $threshold_seconds = (int) apply_filters( 'action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS );
149
+        $threshhold_min    = (int) apply_filters( 'action_scheduler_pastdue_actions_min', 1 );
150
+
151
+        // Allow third-parties to preempt the default check logic.
152
+        $check = apply_filters( 'action_scheduler_pastdue_actions_check_pre', null );
153
+
154
+        // Scheduled actions query arguments.
155
+        $query_args = array(
156
+            'date'     => as_get_datetime_object( time() - $threshold_seconds ),
157
+            'status'   => ActionScheduler_Store::STATUS_PENDING,
158
+            'per_page' => $threshhold_min,
159
+        );
160
+
161
+        // If no third-party preempted, run default check.
162
+        if ( $check === null ) {
163
+            $store               = ActionScheduler_Store::instance();
164
+            $num_pastdue_actions = (int) $store->query_actions( $query_args, 'count' );
165
+
166
+            // Check if past-due actions count is greater than or equal to threshold.
167
+            $check = ( $num_pastdue_actions >= $threshhold_min );
168
+            $check = (bool) apply_filters( 'action_scheduler_pastdue_actions_check', $check, $num_pastdue_actions, $threshold_seconds, $threshhold_min );
169
+        }
170
+
171
+        // If check failed, set transient and abort.
172
+        if ( ! boolval( $check ) ) {
173
+            $interval = apply_filters( 'action_scheduler_pastdue_actions_check_interval', round( $threshold_seconds / 4 ), $threshold_seconds );
174
+            set_transient( 'action_scheduler_last_pastdue_actions_check', time(), $interval );
175
+
176
+            return;
177
+        }
178
+
179
+        $actions_url = add_query_arg(
180
+            array(
181
+                'page'   => 'action-scheduler',
182
+                'status' => 'past-due',
183
+                'order'  => 'asc',
184
+            ),
185
+            admin_url( 'tools.php' )
186
+        );
187
+
188
+        // Print notice.
189
+        echo '<div class="notice notice-warning"><p>';
190
+        printf(
191
+            _n(
192
+                // translators: 1) is the number of affected actions, 2) is a link to an admin screen.
193
+                '<strong>Action Scheduler:</strong> %1$d <a href="%2$s">past-due action</a> found; something may be wrong. <a href="https://actionscheduler.org/faq/#my-site-has-past-due-actions-what-can-i-do" target="_blank">Read documentation &raquo;</a>',
194
+                '<strong>Action Scheduler:</strong> %1$d <a href="%2$s">past-due actions</a> found; something may be wrong. <a href="https://actionscheduler.org/faq/#my-site-has-past-due-actions-what-can-i-do" target="_blank">Read documentation &raquo;</a>',
195
+                $num_pastdue_actions,
196
+                'action-scheduler'
197
+            ),
198
+            $num_pastdue_actions,
199
+            esc_attr( esc_url( $actions_url ) )
200
+        );
201
+        echo '</p></div>';
202
+
203
+        // Facilitate third-parties to evaluate and print notices.
204
+        do_action( 'action_scheduler_pastdue_actions_extra_notices', $query_args );
205
+    }
206
+
207
+    /**
208
+     * Provide more information about the screen and its data in the help tab.
209
+     */
210
+    public function add_help_tabs() {
211
+        $screen = get_current_screen();
212
+
213
+        if ( ! $screen || self::$screen_id != $screen->id ) {
214
+            return;
215
+        }
216
+
217
+        $as_version = ActionScheduler_Versions::instance()->latest_version();
218
+        $screen->add_help_tab(
219
+            array(
220
+                'id'      => 'action_scheduler_about',
221
+                'title'   => __( 'About', 'action-scheduler' ),
222
+                'content' =>
223
+                    '<h2>' . sprintf( __( 'About Action Scheduler %s', 'action-scheduler' ), $as_version ) . '</h2>' .
224
+                    '<p>' .
225
+                        __( 'Action Scheduler is a scalable, traceable job queue for background processing large sets of actions. Action Scheduler works by triggering an action hook to run at some time in the future. Scheduled actions can also be scheduled to run on a recurring schedule.', 'action-scheduler' ) .
226
+                    '</p>',
227
+            )
228
+        );
229
+
230
+        $screen->add_help_tab(
231
+            array(
232
+                'id'      => 'action_scheduler_columns',
233
+                'title'   => __( 'Columns', 'action-scheduler' ),
234
+                'content' =>
235
+                    '<h2>' . __( 'Scheduled Action Columns', 'action-scheduler' ) . '</h2>' .
236
+                    '<ul>' .
237
+                    sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Hook', 'action-scheduler' ), __( 'Name of the action hook that will be triggered.', 'action-scheduler' ) ) .
238
+                    sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Status', 'action-scheduler' ), __( 'Action statuses are Pending, Complete, Canceled, Failed', 'action-scheduler' ) ) .
239
+                    sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Arguments', 'action-scheduler' ), __( 'Optional data array passed to the action hook.', 'action-scheduler' ) ) .
240
+                    sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Group', 'action-scheduler' ), __( 'Optional action group.', 'action-scheduler' ) ) .
241
+                    sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Recurrence', 'action-scheduler' ), __( 'The action\'s schedule frequency.', 'action-scheduler' ) ) .
242
+                    sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Scheduled', 'action-scheduler' ), __( 'The date/time the action is/was scheduled to run.', 'action-scheduler' ) ) .
243
+                    sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Log', 'action-scheduler' ), __( 'Activity log for the action.', 'action-scheduler' ) ) .
244
+                    '</ul>',
245
+            )
246
+        );
247
+    }
248 248
 }
Please login to merge, or discard this patch.
Spacing   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -20,8 +20,8 @@  discard block
 block discarded – undo
20 20
 	 */
21 21
 	public static function instance() {
22 22
 
23
-		if ( empty( self::$admin_view ) ) {
24
-			$class            = apply_filters( 'action_scheduler_admin_view_class', 'ActionScheduler_AdminView' );
23
+		if (empty(self::$admin_view)) {
24
+			$class            = apply_filters('action_scheduler_admin_view_class', 'ActionScheduler_AdminView');
25 25
 			self::$admin_view = new $class();
26 26
 		}
27 27
 
@@ -32,22 +32,22 @@  discard block
 block discarded – undo
32 32
 	 * @codeCoverageIgnore
33 33
 	 */
34 34
 	public function init() {
35
-		if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || false == DOING_AJAX ) ) {
35
+		if (is_admin() && ( ! defined('DOING_AJAX') || false == DOING_AJAX)) {
36 36
 
37
-			if ( class_exists( 'WooCommerce' ) ) {
38
-				add_action( 'woocommerce_admin_status_content_action-scheduler', array( $this, 'render_admin_ui' ) );
39
-				add_action( 'woocommerce_system_status_report', array( $this, 'system_status_report' ) );
40
-				add_filter( 'woocommerce_admin_status_tabs', array( $this, 'register_system_status_tab' ) );
37
+			if (class_exists('WooCommerce')) {
38
+				add_action('woocommerce_admin_status_content_action-scheduler', array($this, 'render_admin_ui'));
39
+				add_action('woocommerce_system_status_report', array($this, 'system_status_report'));
40
+				add_filter('woocommerce_admin_status_tabs', array($this, 'register_system_status_tab'));
41 41
 			}
42 42
 
43
-			add_action( 'admin_menu', array( $this, 'register_menu' ) );
44
-			add_action( 'admin_notices', array( $this, 'maybe_check_pastdue_actions' ) );
45
-			add_action( 'current_screen', array( $this, 'add_help_tabs' ) );
43
+			add_action('admin_menu', array($this, 'register_menu'));
44
+			add_action('admin_notices', array($this, 'maybe_check_pastdue_actions'));
45
+			add_action('current_screen', array($this, 'add_help_tabs'));
46 46
 		}
47 47
 	}
48 48
 
49 49
 	public function system_status_report() {
50
-		$table = new ActionScheduler_wcSystemStatus( ActionScheduler::store() );
50
+		$table = new ActionScheduler_wcSystemStatus(ActionScheduler::store());
51 51
 		$table->render();
52 52
 	}
53 53
 
@@ -57,8 +57,8 @@  discard block
 block discarded – undo
57 57
 	 * @param array $tabs An associative array of tab key => label.
58 58
 	 * @return array $tabs An associative array of tab key => label, including Action Scheduler's tabs
59 59
 	 */
60
-	public function register_system_status_tab( array $tabs ) {
61
-		$tabs['action-scheduler'] = __( 'Scheduled Actions', 'action-scheduler' );
60
+	public function register_system_status_tab(array $tabs) {
61
+		$tabs['action-scheduler'] = __('Scheduled Actions', 'action-scheduler');
62 62
 
63 63
 		return $tabs;
64 64
 	}
@@ -73,13 +73,13 @@  discard block
 block discarded – undo
73 73
 	public function register_menu() {
74 74
 		$hook_suffix = add_submenu_page(
75 75
 			'tools.php',
76
-			__( 'Scheduled Actions', 'action-scheduler' ),
77
-			__( 'Scheduled Actions', 'action-scheduler' ),
76
+			__('Scheduled Actions', 'action-scheduler'),
77
+			__('Scheduled Actions', 'action-scheduler'),
78 78
 			'manage_options',
79 79
 			'action-scheduler',
80
-			array( $this, 'render_admin_ui' )
80
+			array($this, 'render_admin_ui')
81 81
 		);
82
-		add_action( 'load-' . $hook_suffix, array( $this, 'process_admin_ui' ) );
82
+		add_action('load-'.$hook_suffix, array($this, 'process_admin_ui'));
83 83
 	}
84 84
 
85 85
 	/**
@@ -103,8 +103,8 @@  discard block
 block discarded – undo
103 103
 	 * @return ActionScheduler_ListTable
104 104
 	 */
105 105
 	protected function get_list_table() {
106
-		if ( null === $this->list_table ) {
107
-			$this->list_table = new ActionScheduler_ListTable( ActionScheduler::store(), ActionScheduler::logger(), ActionScheduler::runner() );
106
+		if (null === $this->list_table) {
107
+			$this->list_table = new ActionScheduler_ListTable(ActionScheduler::store(), ActionScheduler::logger(), ActionScheduler::runner());
108 108
 			$this->list_table->process_actions();
109 109
 		}
110 110
 
@@ -121,15 +121,15 @@  discard block
 block discarded – undo
121 121
 	public function maybe_check_pastdue_actions() {
122 122
 
123 123
 		// Filter to prevent checking actions (ex: inappropriate user).
124
-		if ( ! apply_filters( 'action_scheduler_check_pastdue_actions', current_user_can( 'manage_options' ) ) ) {
124
+		if ( ! apply_filters('action_scheduler_check_pastdue_actions', current_user_can('manage_options'))) {
125 125
 			return;
126 126
 		}
127 127
 
128 128
 		// Get last check transient.
129
-		$last_check = get_transient( 'action_scheduler_last_pastdue_actions_check' );
129
+		$last_check = get_transient('action_scheduler_last_pastdue_actions_check');
130 130
 
131 131
 		// If transient exists, we're within interval, so bail.
132
-		if ( ! empty( $last_check ) ) {
132
+		if ( ! empty($last_check)) {
133 133
 			return;
134 134
 		}
135 135
 
@@ -145,33 +145,33 @@  discard block
 block discarded – undo
145 145
 	protected function check_pastdue_actions() {
146 146
 
147 147
 		// Set thresholds.
148
-		$threshold_seconds = (int) apply_filters( 'action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS );
149
-		$threshhold_min    = (int) apply_filters( 'action_scheduler_pastdue_actions_min', 1 );
148
+		$threshold_seconds = (int) apply_filters('action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS);
149
+		$threshhold_min    = (int) apply_filters('action_scheduler_pastdue_actions_min', 1);
150 150
 
151 151
 		// Allow third-parties to preempt the default check logic.
152
-		$check = apply_filters( 'action_scheduler_pastdue_actions_check_pre', null );
152
+		$check = apply_filters('action_scheduler_pastdue_actions_check_pre', null);
153 153
 
154 154
 		// Scheduled actions query arguments.
155 155
 		$query_args = array(
156
-			'date'     => as_get_datetime_object( time() - $threshold_seconds ),
156
+			'date'     => as_get_datetime_object(time() - $threshold_seconds),
157 157
 			'status'   => ActionScheduler_Store::STATUS_PENDING,
158 158
 			'per_page' => $threshhold_min,
159 159
 		);
160 160
 
161 161
 		// If no third-party preempted, run default check.
162
-		if ( $check === null ) {
162
+		if ($check === null) {
163 163
 			$store               = ActionScheduler_Store::instance();
164
-			$num_pastdue_actions = (int) $store->query_actions( $query_args, 'count' );
164
+			$num_pastdue_actions = (int) $store->query_actions($query_args, 'count');
165 165
 
166 166
 			// Check if past-due actions count is greater than or equal to threshold.
167
-			$check = ( $num_pastdue_actions >= $threshhold_min );
168
-			$check = (bool) apply_filters( 'action_scheduler_pastdue_actions_check', $check, $num_pastdue_actions, $threshold_seconds, $threshhold_min );
167
+			$check = ($num_pastdue_actions >= $threshhold_min);
168
+			$check = (bool) apply_filters('action_scheduler_pastdue_actions_check', $check, $num_pastdue_actions, $threshold_seconds, $threshhold_min);
169 169
 		}
170 170
 
171 171
 		// If check failed, set transient and abort.
172
-		if ( ! boolval( $check ) ) {
173
-			$interval = apply_filters( 'action_scheduler_pastdue_actions_check_interval', round( $threshold_seconds / 4 ), $threshold_seconds );
174
-			set_transient( 'action_scheduler_last_pastdue_actions_check', time(), $interval );
172
+		if ( ! boolval($check)) {
173
+			$interval = apply_filters('action_scheduler_pastdue_actions_check_interval', round($threshold_seconds / 4), $threshold_seconds);
174
+			set_transient('action_scheduler_last_pastdue_actions_check', time(), $interval);
175 175
 
176 176
 			return;
177 177
 		}
@@ -182,7 +182,7 @@  discard block
 block discarded – undo
182 182
 				'status' => 'past-due',
183 183
 				'order'  => 'asc',
184 184
 			),
185
-			admin_url( 'tools.php' )
185
+			admin_url('tools.php')
186 186
 		);
187 187
 
188 188
 		// Print notice.
@@ -196,12 +196,12 @@  discard block
 block discarded – undo
196 196
 				'action-scheduler'
197 197
 			),
198 198
 			$num_pastdue_actions,
199
-			esc_attr( esc_url( $actions_url ) )
199
+			esc_attr(esc_url($actions_url))
200 200
 		);
201 201
 		echo '</p></div>';
202 202
 
203 203
 		// Facilitate third-parties to evaluate and print notices.
204
-		do_action( 'action_scheduler_pastdue_actions_extra_notices', $query_args );
204
+		do_action('action_scheduler_pastdue_actions_extra_notices', $query_args);
205 205
 	}
206 206
 
207 207
 	/**
@@ -210,7 +210,7 @@  discard block
 block discarded – undo
210 210
 	public function add_help_tabs() {
211 211
 		$screen = get_current_screen();
212 212
 
213
-		if ( ! $screen || self::$screen_id != $screen->id ) {
213
+		if ( ! $screen || self::$screen_id != $screen->id) {
214 214
 			return;
215 215
 		}
216 216
 
@@ -218,11 +218,11 @@  discard block
 block discarded – undo
218 218
 		$screen->add_help_tab(
219 219
 			array(
220 220
 				'id'      => 'action_scheduler_about',
221
-				'title'   => __( 'About', 'action-scheduler' ),
221
+				'title'   => __('About', 'action-scheduler'),
222 222
 				'content' =>
223
-					'<h2>' . sprintf( __( 'About Action Scheduler %s', 'action-scheduler' ), $as_version ) . '</h2>' .
224
-					'<p>' .
225
-						__( 'Action Scheduler is a scalable, traceable job queue for background processing large sets of actions. Action Scheduler works by triggering an action hook to run at some time in the future. Scheduled actions can also be scheduled to run on a recurring schedule.', 'action-scheduler' ) .
223
+					'<h2>'.sprintf(__('About Action Scheduler %s', 'action-scheduler'), $as_version).'</h2>'.
224
+					'<p>'.
225
+						__('Action Scheduler is a scalable, traceable job queue for background processing large sets of actions. Action Scheduler works by triggering an action hook to run at some time in the future. Scheduled actions can also be scheduled to run on a recurring schedule.', 'action-scheduler').
226 226
 					'</p>',
227 227
 			)
228 228
 		);
@@ -230,17 +230,17 @@  discard block
 block discarded – undo
230 230
 		$screen->add_help_tab(
231 231
 			array(
232 232
 				'id'      => 'action_scheduler_columns',
233
-				'title'   => __( 'Columns', 'action-scheduler' ),
233
+				'title'   => __('Columns', 'action-scheduler'),
234 234
 				'content' =>
235
-					'<h2>' . __( 'Scheduled Action Columns', 'action-scheduler' ) . '</h2>' .
236
-					'<ul>' .
237
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Hook', 'action-scheduler' ), __( 'Name of the action hook that will be triggered.', 'action-scheduler' ) ) .
238
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Status', 'action-scheduler' ), __( 'Action statuses are Pending, Complete, Canceled, Failed', 'action-scheduler' ) ) .
239
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Arguments', 'action-scheduler' ), __( 'Optional data array passed to the action hook.', 'action-scheduler' ) ) .
240
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Group', 'action-scheduler' ), __( 'Optional action group.', 'action-scheduler' ) ) .
241
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Recurrence', 'action-scheduler' ), __( 'The action\'s schedule frequency.', 'action-scheduler' ) ) .
242
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Scheduled', 'action-scheduler' ), __( 'The date/time the action is/was scheduled to run.', 'action-scheduler' ) ) .
243
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Log', 'action-scheduler' ), __( 'Activity log for the action.', 'action-scheduler' ) ) .
235
+					'<h2>'.__('Scheduled Action Columns', 'action-scheduler').'</h2>'.
236
+					'<ul>'.
237
+					sprintf('<li><strong>%1$s</strong>: %2$s</li>', __('Hook', 'action-scheduler'), __('Name of the action hook that will be triggered.', 'action-scheduler')).
238
+					sprintf('<li><strong>%1$s</strong>: %2$s</li>', __('Status', 'action-scheduler'), __('Action statuses are Pending, Complete, Canceled, Failed', 'action-scheduler')).
239
+					sprintf('<li><strong>%1$s</strong>: %2$s</li>', __('Arguments', 'action-scheduler'), __('Optional data array passed to the action hook.', 'action-scheduler')).
240
+					sprintf('<li><strong>%1$s</strong>: %2$s</li>', __('Group', 'action-scheduler'), __('Optional action group.', 'action-scheduler')).
241
+					sprintf('<li><strong>%1$s</strong>: %2$s</li>', __('Recurrence', 'action-scheduler'), __('The action\'s schedule frequency.', 'action-scheduler')).
242
+					sprintf('<li><strong>%1$s</strong>: %2$s</li>', __('Scheduled', 'action-scheduler'), __('The date/time the action is/was scheduled to run.', 'action-scheduler')).
243
+					sprintf('<li><strong>%1$s</strong>: %2$s</li>', __('Log', 'action-scheduler'), __('Activity log for the action.', 'action-scheduler')).
244 244
 					'</ul>',
245 245
 			)
246 246
 		);
Please login to merge, or discard this patch.
action-scheduler/lib/cron-expression/CronExpression_DayOfMonthField.php 2 patches
Indentation   +72 added lines, -72 removed lines patch added patch discarded remove patch
@@ -20,87 +20,87 @@
 block discarded – undo
20 20
  */
21 21
 class CronExpression_DayOfMonthField extends CronExpression_AbstractField {
22 22
 
23
-	/**
24
-	 * Get the nearest day of the week for a given day in a month
25
-	 *
26
-	 * @param int $currentYear  Current year
27
-	 * @param int $currentMonth Current month
28
-	 * @param int $targetDay    Target day of the month
29
-	 *
30
-	 * @return DateTime Returns the nearest date
31
-	 */
32
-	private static function getNearestWeekday( $currentYear, $currentMonth, $targetDay ) {
33
-		$tday           = str_pad( $targetDay, 2, '0', STR_PAD_LEFT );
34
-		$target         = new DateTime( "$currentYear-$currentMonth-$tday" );
35
-		$currentWeekday = (int) $target->format( 'N' );
23
+    /**
24
+     * Get the nearest day of the week for a given day in a month
25
+     *
26
+     * @param int $currentYear  Current year
27
+     * @param int $currentMonth Current month
28
+     * @param int $targetDay    Target day of the month
29
+     *
30
+     * @return DateTime Returns the nearest date
31
+     */
32
+    private static function getNearestWeekday( $currentYear, $currentMonth, $targetDay ) {
33
+        $tday           = str_pad( $targetDay, 2, '0', STR_PAD_LEFT );
34
+        $target         = new DateTime( "$currentYear-$currentMonth-$tday" );
35
+        $currentWeekday = (int) $target->format( 'N' );
36 36
 
37
-		if ( $currentWeekday < 6 ) {
38
-			return $target;
39
-		}
37
+        if ( $currentWeekday < 6 ) {
38
+            return $target;
39
+        }
40 40
 
41
-		$lastDayOfMonth = $target->format( 't' );
41
+        $lastDayOfMonth = $target->format( 't' );
42 42
 
43
-		foreach ( array( -1, 1, -2, 2 ) as $i ) {
44
-			$adjusted = $targetDay + $i;
45
-			if ( $adjusted > 0 && $adjusted <= $lastDayOfMonth ) {
46
-				$target->setDate( $currentYear, $currentMonth, $adjusted );
47
-				if ( $target->format( 'N' ) < 6 && $target->format( 'm' ) == $currentMonth ) {
48
-					return $target;
49
-				}
50
-			}
51
-		}
52
-	}
43
+        foreach ( array( -1, 1, -2, 2 ) as $i ) {
44
+            $adjusted = $targetDay + $i;
45
+            if ( $adjusted > 0 && $adjusted <= $lastDayOfMonth ) {
46
+                $target->setDate( $currentYear, $currentMonth, $adjusted );
47
+                if ( $target->format( 'N' ) < 6 && $target->format( 'm' ) == $currentMonth ) {
48
+                    return $target;
49
+                }
50
+            }
51
+        }
52
+    }
53 53
 
54
-	/**
55
-	 * {@inheritdoc}
56
-	 */
57
-	public function isSatisfiedBy( DateTime $date, $value ) {
58
-		// ? states that the field value is to be skipped
59
-		if ( $value == '?' ) {
60
-			return true;
61
-		}
54
+    /**
55
+     * {@inheritdoc}
56
+     */
57
+    public function isSatisfiedBy( DateTime $date, $value ) {
58
+        // ? states that the field value is to be skipped
59
+        if ( $value == '?' ) {
60
+            return true;
61
+        }
62 62
 
63
-		$fieldValue = $date->format( 'd' );
63
+        $fieldValue = $date->format( 'd' );
64 64
 
65
-		// Check to see if this is the last day of the month
66
-		if ( $value == 'L' ) {
67
-			return $fieldValue == $date->format( 't' );
68
-		}
65
+        // Check to see if this is the last day of the month
66
+        if ( $value == 'L' ) {
67
+            return $fieldValue == $date->format( 't' );
68
+        }
69 69
 
70
-		// Check to see if this is the nearest weekday to a particular value
71
-		if ( strpos( $value, 'W' ) ) {
72
-			// Parse the target day
73
-			$targetDay = substr( $value, 0, strpos( $value, 'W' ) );
74
-			// Find out if the current day is the nearest day of the week
75
-			return $date->format( 'j' ) == self::getNearestWeekday(
76
-				$date->format( 'Y' ),
77
-				$date->format( 'm' ),
78
-				$targetDay
79
-			)->format( 'j' );
80
-		}
70
+        // Check to see if this is the nearest weekday to a particular value
71
+        if ( strpos( $value, 'W' ) ) {
72
+            // Parse the target day
73
+            $targetDay = substr( $value, 0, strpos( $value, 'W' ) );
74
+            // Find out if the current day is the nearest day of the week
75
+            return $date->format( 'j' ) == self::getNearestWeekday(
76
+                $date->format( 'Y' ),
77
+                $date->format( 'm' ),
78
+                $targetDay
79
+            )->format( 'j' );
80
+        }
81 81
 
82
-		return $this->isSatisfied( $date->format( 'd' ), $value );
83
-	}
82
+        return $this->isSatisfied( $date->format( 'd' ), $value );
83
+    }
84 84
 
85
-	/**
86
-	 * {@inheritdoc}
87
-	 */
88
-	public function increment( DateTime $date, $invert = false ) {
89
-		if ( $invert ) {
90
-			$date->modify( 'previous day' );
91
-			$date->setTime( 23, 59 );
92
-		} else {
93
-			$date->modify( 'next day' );
94
-			$date->setTime( 0, 0 );
95
-		}
85
+    /**
86
+     * {@inheritdoc}
87
+     */
88
+    public function increment( DateTime $date, $invert = false ) {
89
+        if ( $invert ) {
90
+            $date->modify( 'previous day' );
91
+            $date->setTime( 23, 59 );
92
+        } else {
93
+            $date->modify( 'next day' );
94
+            $date->setTime( 0, 0 );
95
+        }
96 96
 
97
-		return $this;
98
-	}
97
+        return $this;
98
+    }
99 99
 
100
-	/**
101
-	 * {@inheritdoc}
102
-	 */
103
-	public function validate( $value ) {
104
-		return (bool) preg_match( '/[\*,\/\-\?LW0-9A-Za-z]+/', $value );
105
-	}
100
+    /**
101
+     * {@inheritdoc}
102
+     */
103
+    public function validate( $value ) {
104
+        return (bool) preg_match( '/[\*,\/\-\?LW0-9A-Za-z]+/', $value );
105
+    }
106 106
 }
Please login to merge, or discard this patch.
Spacing   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -29,22 +29,22 @@  discard block
 block discarded – undo
29 29
 	 *
30 30
 	 * @return DateTime Returns the nearest date
31 31
 	 */
32
-	private static function getNearestWeekday( $currentYear, $currentMonth, $targetDay ) {
33
-		$tday           = str_pad( $targetDay, 2, '0', STR_PAD_LEFT );
34
-		$target         = new DateTime( "$currentYear-$currentMonth-$tday" );
35
-		$currentWeekday = (int) $target->format( 'N' );
32
+	private static function getNearestWeekday($currentYear, $currentMonth, $targetDay) {
33
+		$tday           = str_pad($targetDay, 2, '0', STR_PAD_LEFT);
34
+		$target         = new DateTime("$currentYear-$currentMonth-$tday");
35
+		$currentWeekday = (int) $target->format('N');
36 36
 
37
-		if ( $currentWeekday < 6 ) {
37
+		if ($currentWeekday < 6) {
38 38
 			return $target;
39 39
 		}
40 40
 
41
-		$lastDayOfMonth = $target->format( 't' );
41
+		$lastDayOfMonth = $target->format('t');
42 42
 
43
-		foreach ( array( -1, 1, -2, 2 ) as $i ) {
43
+		foreach (array( -1, 1, -2, 2 ) as $i) {
44 44
 			$adjusted = $targetDay + $i;
45
-			if ( $adjusted > 0 && $adjusted <= $lastDayOfMonth ) {
46
-				$target->setDate( $currentYear, $currentMonth, $adjusted );
47
-				if ( $target->format( 'N' ) < 6 && $target->format( 'm' ) == $currentMonth ) {
45
+			if ($adjusted > 0 && $adjusted <= $lastDayOfMonth) {
46
+				$target->setDate($currentYear, $currentMonth, $adjusted);
47
+				if ($target->format('N') < 6 && $target->format('m') == $currentMonth) {
48 48
 					return $target;
49 49
 				}
50 50
 			}
@@ -54,44 +54,44 @@  discard block
 block discarded – undo
54 54
 	/**
55 55
 	 * {@inheritdoc}
56 56
 	 */
57
-	public function isSatisfiedBy( DateTime $date, $value ) {
57
+	public function isSatisfiedBy(DateTime $date, $value) {
58 58
 		// ? states that the field value is to be skipped
59
-		if ( $value == '?' ) {
59
+		if ($value == '?') {
60 60
 			return true;
61 61
 		}
62 62
 
63
-		$fieldValue = $date->format( 'd' );
63
+		$fieldValue = $date->format('d');
64 64
 
65 65
 		// Check to see if this is the last day of the month
66
-		if ( $value == 'L' ) {
67
-			return $fieldValue == $date->format( 't' );
66
+		if ($value == 'L') {
67
+			return $fieldValue == $date->format('t');
68 68
 		}
69 69
 
70 70
 		// Check to see if this is the nearest weekday to a particular value
71
-		if ( strpos( $value, 'W' ) ) {
71
+		if (strpos($value, 'W')) {
72 72
 			// Parse the target day
73
-			$targetDay = substr( $value, 0, strpos( $value, 'W' ) );
73
+			$targetDay = substr($value, 0, strpos($value, 'W'));
74 74
 			// Find out if the current day is the nearest day of the week
75
-			return $date->format( 'j' ) == self::getNearestWeekday(
76
-				$date->format( 'Y' ),
77
-				$date->format( 'm' ),
75
+			return $date->format('j') == self::getNearestWeekday(
76
+				$date->format('Y'),
77
+				$date->format('m'),
78 78
 				$targetDay
79
-			)->format( 'j' );
79
+			)->format('j');
80 80
 		}
81 81
 
82
-		return $this->isSatisfied( $date->format( 'd' ), $value );
82
+		return $this->isSatisfied($date->format('d'), $value);
83 83
 	}
84 84
 
85 85
 	/**
86 86
 	 * {@inheritdoc}
87 87
 	 */
88
-	public function increment( DateTime $date, $invert = false ) {
89
-		if ( $invert ) {
90
-			$date->modify( 'previous day' );
91
-			$date->setTime( 23, 59 );
88
+	public function increment(DateTime $date, $invert = false) {
89
+		if ($invert) {
90
+			$date->modify('previous day');
91
+			$date->setTime(23, 59);
92 92
 		} else {
93
-			$date->modify( 'next day' );
94
-			$date->setTime( 0, 0 );
93
+			$date->modify('next day');
94
+			$date->setTime(0, 0);
95 95
 		}
96 96
 
97 97
 		return $this;
@@ -100,7 +100,7 @@  discard block
 block discarded – undo
100 100
 	/**
101 101
 	 * {@inheritdoc}
102 102
 	 */
103
-	public function validate( $value ) {
104
-		return (bool) preg_match( '/[\*,\/\-\?LW0-9A-Za-z]+/', $value );
103
+	public function validate($value) {
104
+		return (bool) preg_match('/[\*,\/\-\?LW0-9A-Za-z]+/', $value);
105 105
 	}
106 106
 }
Please login to merge, or discard this patch.
libraries/action-scheduler/lib/cron-expression/CronExpression_YearField.php 2 patches
Indentation   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -7,34 +7,34 @@
 block discarded – undo
7 7
  */
8 8
 class CronExpression_YearField extends CronExpression_AbstractField {
9 9
 
10
-	/**
11
-	 * {@inheritdoc}
12
-	 */
13
-	public function isSatisfiedBy( DateTime $date, $value ) {
14
-		return $this->isSatisfied( $date->format( 'Y' ), $value );
15
-	}
10
+    /**
11
+     * {@inheritdoc}
12
+     */
13
+    public function isSatisfiedBy( DateTime $date, $value ) {
14
+        return $this->isSatisfied( $date->format( 'Y' ), $value );
15
+    }
16 16
 
17
-	/**
18
-	 * {@inheritdoc}
19
-	 */
20
-	public function increment( DateTime $date, $invert = false ) {
21
-		if ( $invert ) {
22
-			$date->modify( '-1 year' );
23
-			$date->setDate( $date->format( 'Y' ), 12, 31 );
24
-			$date->setTime( 23, 59, 0 );
25
-		} else {
26
-			$date->modify( '+1 year' );
27
-			$date->setDate( $date->format( 'Y' ), 1, 1 );
28
-			$date->setTime( 0, 0, 0 );
29
-		}
17
+    /**
18
+     * {@inheritdoc}
19
+     */
20
+    public function increment( DateTime $date, $invert = false ) {
21
+        if ( $invert ) {
22
+            $date->modify( '-1 year' );
23
+            $date->setDate( $date->format( 'Y' ), 12, 31 );
24
+            $date->setTime( 23, 59, 0 );
25
+        } else {
26
+            $date->modify( '+1 year' );
27
+            $date->setDate( $date->format( 'Y' ), 1, 1 );
28
+            $date->setTime( 0, 0, 0 );
29
+        }
30 30
 
31
-		return $this;
32
-	}
31
+        return $this;
32
+    }
33 33
 
34
-	/**
35
-	 * {@inheritdoc}
36
-	 */
37
-	public function validate( $value ) {
38
-		return (bool) preg_match( '/[\*,\/\-0-9]+/', $value );
39
-	}
34
+    /**
35
+     * {@inheritdoc}
36
+     */
37
+    public function validate( $value ) {
38
+        return (bool) preg_match( '/[\*,\/\-0-9]+/', $value );
39
+    }
40 40
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -10,22 +10,22 @@  discard block
 block discarded – undo
10 10
 	/**
11 11
 	 * {@inheritdoc}
12 12
 	 */
13
-	public function isSatisfiedBy( DateTime $date, $value ) {
14
-		return $this->isSatisfied( $date->format( 'Y' ), $value );
13
+	public function isSatisfiedBy(DateTime $date, $value) {
14
+		return $this->isSatisfied($date->format('Y'), $value);
15 15
 	}
16 16
 
17 17
 	/**
18 18
 	 * {@inheritdoc}
19 19
 	 */
20
-	public function increment( DateTime $date, $invert = false ) {
21
-		if ( $invert ) {
22
-			$date->modify( '-1 year' );
23
-			$date->setDate( $date->format( 'Y' ), 12, 31 );
24
-			$date->setTime( 23, 59, 0 );
20
+	public function increment(DateTime $date, $invert = false) {
21
+		if ($invert) {
22
+			$date->modify('-1 year');
23
+			$date->setDate($date->format('Y'), 12, 31);
24
+			$date->setTime(23, 59, 0);
25 25
 		} else {
26
-			$date->modify( '+1 year' );
27
-			$date->setDate( $date->format( 'Y' ), 1, 1 );
28
-			$date->setTime( 0, 0, 0 );
26
+			$date->modify('+1 year');
27
+			$date->setDate($date->format('Y'), 1, 1);
28
+			$date->setTime(0, 0, 0);
29 29
 		}
30 30
 
31 31
 		return $this;
@@ -34,7 +34,7 @@  discard block
 block discarded – undo
34 34
 	/**
35 35
 	 * {@inheritdoc}
36 36
 	 */
37
-	public function validate( $value ) {
38
-		return (bool) preg_match( '/[\*,\/\-0-9]+/', $value );
37
+	public function validate($value) {
38
+		return (bool) preg_match('/[\*,\/\-0-9]+/', $value);
39 39
 	}
40 40
 }
Please login to merge, or discard this patch.