PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 4.16.6.1
GiveWP – Donation Plugin and Fundraising Platform v4.16.6.1
4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / vendor / woocommerce / action-scheduler / classes / ActionScheduler_ListTable.php
give / vendor / woocommerce / action-scheduler / classes Last commit date
WP_CLI 6 months ago abstracts 6 months ago actions 1 year ago data-stores 6 months ago migration 1 year ago schedules 1 year ago schema 6 months ago ActionScheduler_ActionClaim.php 1 year ago ActionScheduler_ActionFactory.php 6 months ago ActionScheduler_AdminView.php 6 months ago ActionScheduler_AsyncRequest_QueueRunner.php 1 year ago ActionScheduler_Compatibility.php 1 year ago ActionScheduler_DataController.php 6 months ago ActionScheduler_DateTime.php 1 year ago ActionScheduler_Exception.php 3 years ago ActionScheduler_FatalErrorMonitor.php 1 year ago ActionScheduler_InvalidActionException.php 1 year ago ActionScheduler_ListTable.php 1 year ago ActionScheduler_LogEntry.php 1 year ago ActionScheduler_NullLogEntry.php 1 year ago ActionScheduler_OptionLock.php 1 year ago ActionScheduler_QueueCleaner.php 1 year ago ActionScheduler_QueueRunner.php 1 year ago ActionScheduler_RecurringActionScheduler.php 6 months ago ActionScheduler_SystemInformation.php 6 months ago ActionScheduler_Versions.php 6 months ago ActionScheduler_WPCommentCleaner.php 6 months ago ActionScheduler_wcSystemStatus.php 6 months ago
ActionScheduler_ListTable.php
676 lines
1 <?php
2
3 /**
4 * Implements the admin view of the actions.
5 *
6 * @codeCoverageIgnore
7 */
8 class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
9
10 /**
11 * The package name.
12 *
13 * @var string
14 */
15 protected $package = 'action-scheduler';
16
17 /**
18 * Columns to show (name => label).
19 *
20 * @var array
21 */
22 protected $columns = array();
23
24 /**
25 * Actions (name => label).
26 *
27 * @var array
28 */
29 protected $row_actions = array();
30
31 /**
32 * The active data stores
33 *
34 * @var ActionScheduler_Store
35 */
36 protected $store;
37
38 /**
39 * A logger to use for getting action logs to display
40 *
41 * @var ActionScheduler_Logger
42 */
43 protected $logger;
44
45 /**
46 * A ActionScheduler_QueueRunner runner instance (or child class)
47 *
48 * @var ActionScheduler_QueueRunner
49 */
50 protected $runner;
51
52 /**
53 * Bulk actions. The key of the array is the method name of the implementation.
54 * Example: bulk_<key>(array $ids, string $sql_in).
55 *
56 * See the comments in the parent class for further details
57 *
58 * @var array
59 */
60 protected $bulk_actions = array();
61
62 /**
63 * Flag variable to render our notifications, if any, once.
64 *
65 * @var bool
66 */
67 protected static $did_notification = false;
68
69 /**
70 * Array of seconds for common time periods, like week or month, alongside an internationalised string representation, i.e. "Day" or "Days"
71 *
72 * @var array
73 */
74 private static $time_periods;
75
76 /**
77 * Sets the current data store object into `store->action` and initialises the object.
78 *
79 * @param ActionScheduler_Store $store Store object.
80 * @param ActionScheduler_Logger $logger Logger object.
81 * @param ActionScheduler_QueueRunner $runner Runner object.
82 */
83 public function __construct( ActionScheduler_Store $store, ActionScheduler_Logger $logger, ActionScheduler_QueueRunner $runner ) {
84
85 $this->store = $store;
86 $this->logger = $logger;
87 $this->runner = $runner;
88
89 $this->table_header = __( 'Scheduled Actions', 'action-scheduler' );
90
91 $this->bulk_actions = array(
92 'delete' => __( 'Delete', 'action-scheduler' ),
93 );
94
95 $this->columns = array(
96 'hook' => __( 'Hook', 'action-scheduler' ),
97 'status' => __( 'Status', 'action-scheduler' ),
98 'args' => __( 'Arguments', 'action-scheduler' ),
99 'group' => __( 'Group', 'action-scheduler' ),
100 'recurrence' => __( 'Recurrence', 'action-scheduler' ),
101 'schedule' => __( 'Scheduled Date', 'action-scheduler' ),
102 'log_entries' => __( 'Log', 'action-scheduler' ),
103 );
104
105 $this->sort_by = array(
106 'schedule',
107 'hook',
108 'group',
109 );
110
111 $this->search_by = array(
112 'hook',
113 'args',
114 'claim_id',
115 );
116
117 $request_status = $this->get_request_status();
118
119 if ( empty( $request_status ) ) {
120 $this->sort_by[] = 'status';
121 } elseif ( in_array( $request_status, array( 'in-progress', 'failed' ), true ) ) {
122 $this->columns += array( 'claim_id' => __( 'Claim ID', 'action-scheduler' ) );
123 $this->sort_by[] = 'claim_id';
124 }
125
126 $this->row_actions = array(
127 'hook' => array(
128 'run' => array(
129 'name' => __( 'Run', 'action-scheduler' ),
130 'desc' => __( 'Process the action now as if it were run as part of a queue', 'action-scheduler' ),
131 ),
132 'cancel' => array(
133 'name' => __( 'Cancel', 'action-scheduler' ),
134 'desc' => __( 'Cancel the action now to avoid it being run in future', 'action-scheduler' ),
135 'class' => 'cancel trash',
136 ),
137 ),
138 );
139
140 self::$time_periods = array(
141 array(
142 'seconds' => YEAR_IN_SECONDS,
143 /* translators: %s: amount of time */
144 'names' => _n_noop( '%s year', '%s years', 'action-scheduler' ),
145 ),
146 array(
147 'seconds' => MONTH_IN_SECONDS,
148 /* translators: %s: amount of time */
149 'names' => _n_noop( '%s month', '%s months', 'action-scheduler' ),
150 ),
151 array(
152 'seconds' => WEEK_IN_SECONDS,
153 /* translators: %s: amount of time */
154 'names' => _n_noop( '%s week', '%s weeks', 'action-scheduler' ),
155 ),
156 array(
157 'seconds' => DAY_IN_SECONDS,
158 /* translators: %s: amount of time */
159 'names' => _n_noop( '%s day', '%s days', 'action-scheduler' ),
160 ),
161 array(
162 'seconds' => HOUR_IN_SECONDS,
163 /* translators: %s: amount of time */
164 'names' => _n_noop( '%s hour', '%s hours', 'action-scheduler' ),
165 ),
166 array(
167 'seconds' => MINUTE_IN_SECONDS,
168 /* translators: %s: amount of time */
169 'names' => _n_noop( '%s minute', '%s minutes', 'action-scheduler' ),
170 ),
171 array(
172 'seconds' => 1,
173 /* translators: %s: amount of time */
174 'names' => _n_noop( '%s second', '%s seconds', 'action-scheduler' ),
175 ),
176 );
177
178 parent::__construct(
179 array(
180 'singular' => 'action-scheduler',
181 'plural' => 'action-scheduler',
182 'ajax' => false,
183 )
184 );
185
186 add_screen_option(
187 'per_page',
188 array(
189 'default' => $this->items_per_page,
190 )
191 );
192
193 add_filter( 'set_screen_option_' . $this->get_per_page_option_name(), array( $this, 'set_items_per_page_option' ), 10, 3 );
194 set_screen_options();
195 }
196
197 /**
198 * Handles setting the items_per_page option for this screen.
199 *
200 * @param mixed $status Default false (to skip saving the current option).
201 * @param string $option Screen option name.
202 * @param int $value Screen option value.
203 * @return int
204 */
205 public function set_items_per_page_option( $status, $option, $value ) {
206 return $value;
207 }
208 /**
209 * Convert an interval of seconds into a two part human friendly string.
210 *
211 * The WordPress human_time_diff() function only calculates the time difference to one degree, meaning
212 * even if an action is 1 day and 11 hours away, it will display "1 day". This function goes one step
213 * further to display two degrees of accuracy.
214 *
215 * Inspired by the Crontrol::interval() function by Edward Dale: https://wordpress.org/plugins/wp-crontrol/
216 *
217 * @param int $interval A interval in seconds.
218 * @param int $periods_to_include Depth of time periods to include, e.g. for an interval of 70, and $periods_to_include of 2, both minutes and seconds would be included. With a value of 1, only minutes would be included.
219 * @return string A human friendly string representation of the interval.
220 */
221 private static function human_interval( $interval, $periods_to_include = 2 ) {
222
223 if ( $interval <= 0 ) {
224 return __( 'Now!', 'action-scheduler' );
225 }
226
227 $output = '';
228 $num_time_periods = count( self::$time_periods );
229
230 for ( $time_period_index = 0, $periods_included = 0, $seconds_remaining = $interval; $time_period_index < $num_time_periods && $seconds_remaining > 0 && $periods_included < $periods_to_include; $time_period_index++ ) {
231
232 $periods_in_interval = floor( $seconds_remaining / self::$time_periods[ $time_period_index ]['seconds'] );
233
234 if ( $periods_in_interval > 0 ) {
235 if ( ! empty( $output ) ) {
236 $output .= ' ';
237 }
238 $output .= sprintf( translate_nooped_plural( self::$time_periods[ $time_period_index ]['names'], $periods_in_interval, 'action-scheduler' ), $periods_in_interval );
239 $seconds_remaining -= $periods_in_interval * self::$time_periods[ $time_period_index ]['seconds'];
240 $periods_included++;
241 }
242 }
243
244 return $output;
245 }
246
247 /**
248 * Returns the recurrence of an action or 'Non-repeating'. The output is human readable.
249 *
250 * @param ActionScheduler_Action $action Action object.
251 *
252 * @return string
253 */
254 protected function get_recurrence( $action ) {
255 $schedule = $action->get_schedule();
256 if ( $schedule->is_recurring() && method_exists( $schedule, 'get_recurrence' ) ) {
257 $recurrence = $schedule->get_recurrence();
258
259 if ( is_numeric( $recurrence ) ) {
260 /* translators: %s: time interval */
261 return sprintf( __( 'Every %s', 'action-scheduler' ), self::human_interval( $recurrence ) );
262 } else {
263 return $recurrence;
264 }
265 }
266
267 return __( 'Non-repeating', 'action-scheduler' );
268 }
269
270 /**
271 * Serializes the argument of an action to render it in a human friendly format.
272 *
273 * @param array $row The array representation of the current row of the table.
274 *
275 * @return string
276 */
277 public function column_args( array $row ) {
278 if ( empty( $row['args'] ) ) {
279 return apply_filters( 'action_scheduler_list_table_column_args', '', $row );
280 }
281
282 $row_html = '<ul>';
283 foreach ( $row['args'] as $key => $value ) {
284 $row_html .= sprintf( '<li><code>%s => %s</code></li>', esc_html( var_export( $key, true ) ), esc_html( var_export( $value, true ) ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
285 }
286 $row_html .= '</ul>';
287
288 return apply_filters( 'action_scheduler_list_table_column_args', $row_html, $row );
289 }
290
291 /**
292 * Prints the logs entries inline. We do so to avoid loading Javascript and other hacks to show it in a modal.
293 *
294 * @param array $row Action array.
295 * @return string
296 */
297 public function column_log_entries( array $row ) {
298
299 $log_entries_html = '<ol>';
300
301 $timezone = new DateTimezone( 'UTC' );
302
303 foreach ( $row['log_entries'] as $log_entry ) {
304 $log_entries_html .= $this->get_log_entry_html( $log_entry, $timezone );
305 }
306
307 $log_entries_html .= '</ol>';
308
309 return $log_entries_html;
310 }
311
312 /**
313 * Prints the logs entries inline. We do so to avoid loading Javascript and other hacks to show it in a modal.
314 *
315 * @param ActionScheduler_LogEntry $log_entry Log entry object.
316 * @param DateTimezone $timezone Timestamp.
317 * @return string
318 */
319 protected function get_log_entry_html( ActionScheduler_LogEntry $log_entry, DateTimezone $timezone ) {
320 $date = $log_entry->get_date();
321 $date->setTimezone( $timezone );
322 return sprintf( '<li><strong>%s</strong><br/>%s</li>', esc_html( $date->format( 'Y-m-d H:i:s O' ) ), esc_html( $log_entry->get_message() ) );
323 }
324
325 /**
326 * Only display row actions for pending actions.
327 *
328 * @param array $row Row to render.
329 * @param string $column_name Current row.
330 *
331 * @return string
332 */
333 protected function maybe_render_actions( $row, $column_name ) {
334 if ( 'pending' === strtolower( $row['status_name'] ) ) {
335 return parent::maybe_render_actions( $row, $column_name );
336 }
337
338 return '';
339 }
340
341 /**
342 * Renders admin notifications
343 *
344 * Notifications:
345 * 1. When the maximum number of tasks are being executed simultaneously.
346 * 2. Notifications when a task is manually executed.
347 * 3. Tables are missing.
348 */
349 public function display_admin_notices() {
350 global $wpdb;
351
352 if ( ( is_a( $this->store, 'ActionScheduler_HybridStore' ) || is_a( $this->store, 'ActionScheduler_DBStore' ) ) && apply_filters( 'action_scheduler_enable_recreate_data_store', true ) ) {
353 $table_list = array(
354 'actionscheduler_actions',
355 'actionscheduler_logs',
356 'actionscheduler_groups',
357 'actionscheduler_claims',
358 );
359
360 $found_tables = $wpdb->get_col( "SHOW TABLES LIKE '{$wpdb->prefix}actionscheduler%'" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
361 foreach ( $table_list as $table_name ) {
362 if ( ! in_array( $wpdb->prefix . $table_name, $found_tables, true ) ) {
363 $this->admin_notices[] = array(
364 'class' => 'error',
365 'message' => __( 'It appears one or more database tables were missing. Attempting to re-create the missing table(s).', 'action-scheduler' ),
366 );
367 $this->recreate_tables();
368 parent::display_admin_notices();
369
370 return;
371 }
372 }
373 }
374
375 if ( $this->runner->has_maximum_concurrent_batches() ) {
376 $claim_count = $this->store->get_claim_count();
377 $this->admin_notices[] = array(
378 'class' => 'updated',
379 'message' => sprintf(
380 /* translators: %s: amount of claims */
381 _n(
382 'Maximum simultaneous queues already in progress (%s queue). No additional queues will begin processing until the current queues are complete.',
383 'Maximum simultaneous queues already in progress (%s queues). No additional queues will begin processing until the current queues are complete.',
384 $claim_count,
385 'action-scheduler'
386 ),
387 $claim_count
388 ),
389 );
390 } elseif ( $this->store->has_pending_actions_due() ) {
391
392 $async_request_lock_expiration = ActionScheduler::lock()->get_expiration( 'async-request-runner' );
393
394 // No lock set or lock expired.
395 if ( false === $async_request_lock_expiration || $async_request_lock_expiration < time() ) {
396 $in_progress_url = add_query_arg( 'status', 'in-progress', remove_query_arg( 'status' ) );
397 /* translators: %s: process URL */
398 $async_request_message = sprintf( __( 'A new queue has begun processing. <a href="%s">View actions in-progress &raquo;</a>', 'action-scheduler' ), esc_url( $in_progress_url ) );
399 } else {
400 /* translators: %d: seconds */
401 $async_request_message = sprintf( __( 'The next queue will begin processing in approximately %d seconds.', 'action-scheduler' ), $async_request_lock_expiration - time() );
402 }
403
404 $this->admin_notices[] = array(
405 'class' => 'notice notice-info',
406 'message' => $async_request_message,
407 );
408 }
409
410 $notification = get_transient( 'action_scheduler_admin_notice' );
411
412 if ( is_array( $notification ) ) {
413 delete_transient( 'action_scheduler_admin_notice' );
414
415 $action = $this->store->fetch_action( $notification['action_id'] );
416 $action_hook_html = '<strong><code>' . $action->get_hook() . '</code></strong>';
417
418 if ( 1 === absint( $notification['success'] ) ) {
419 $class = 'updated';
420 switch ( $notification['row_action_type'] ) {
421 case 'run':
422 /* translators: %s: action HTML */
423 $action_message_html = sprintf( __( 'Successfully executed action: %s', 'action-scheduler' ), $action_hook_html );
424 break;
425 case 'cancel':
426 /* translators: %s: action HTML */
427 $action_message_html = sprintf( __( 'Successfully canceled action: %s', 'action-scheduler' ), $action_hook_html );
428 break;
429 default:
430 /* translators: %s: action HTML */
431 $action_message_html = sprintf( __( 'Successfully processed change for action: %s', 'action-scheduler' ), $action_hook_html );
432 break;
433 }
434 } else {
435 $class = 'error';
436 /* translators: 1: action HTML 2: action ID 3: error message */
437 $action_message_html = sprintf( __( 'Could not process change for action: "%1$s" (ID: %2$d). Error: %3$s', 'action-scheduler' ), $action_hook_html, esc_html( $notification['action_id'] ), esc_html( $notification['error_message'] ) );
438 }
439
440 $action_message_html = apply_filters( 'action_scheduler_admin_notice_html', $action_message_html, $action, $notification );
441
442 $this->admin_notices[] = array(
443 'class' => $class,
444 'message' => $action_message_html,
445 );
446 }
447
448 parent::display_admin_notices();
449 }
450
451 /**
452 * Prints the scheduled date in a human friendly format.
453 *
454 * @param array $row The array representation of the current row of the table.
455 *
456 * @return string
457 */
458 public function column_schedule( $row ) {
459 return $this->get_schedule_display_string( $row['schedule'] );
460 }
461
462 /**
463 * Get the scheduled date in a human friendly format.
464 *
465 * @param ActionScheduler_Schedule $schedule Action's schedule.
466 * @return string
467 */
468 protected function get_schedule_display_string( ActionScheduler_Schedule $schedule ) {
469
470 $schedule_display_string = '';
471
472 if ( is_a( $schedule, 'ActionScheduler_NullSchedule' ) ) {
473 return __( 'async', 'action-scheduler' );
474 }
475
476 if ( ! method_exists( $schedule, 'get_date' ) || ! $schedule->get_date() ) {
477 return '0000-00-00 00:00:00';
478 }
479
480 $next_timestamp = $schedule->get_date()->getTimestamp();
481
482 $schedule_display_string .= $schedule->get_date()->format( 'Y-m-d H:i:s O' );
483 $schedule_display_string .= '<br/>';
484
485 if ( gmdate( 'U' ) > $next_timestamp ) {
486 /* translators: %s: date interval */
487 $schedule_display_string .= sprintf( __( ' (%s ago)', 'action-scheduler' ), self::human_interval( gmdate( 'U' ) - $next_timestamp ) );
488 } else {
489 /* translators: %s: date interval */
490 $schedule_display_string .= sprintf( __( ' (%s)', 'action-scheduler' ), self::human_interval( $next_timestamp - gmdate( 'U' ) ) );
491 }
492
493 return $schedule_display_string;
494 }
495
496 /**
497 * Bulk delete.
498 *
499 * Deletes actions based on their ID. This is the handler for the bulk delete. It assumes the data
500 * properly validated by the callee and it will delete the actions without any extra validation.
501 *
502 * @param int[] $ids Action IDs.
503 * @param string $ids_sql Inherited and unused.
504 */
505 protected function bulk_delete( array $ids, $ids_sql ) {
506 foreach ( $ids as $id ) {
507 try {
508 $this->store->delete_action( $id );
509 } catch ( Exception $e ) {
510 // A possible reason for an exception would include a scenario where the same action is deleted by a
511 // concurrent request.
512 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
513 error_log(
514 sprintf(
515 /* translators: 1: action ID 2: exception message. */
516 __( 'Action Scheduler was unable to delete action %1$d. Reason: %2$s', 'action-scheduler' ),
517 $id,
518 $e->getMessage()
519 )
520 );
521 }
522 }
523 }
524
525 /**
526 * Implements the logic behind running an action. ActionScheduler_Abstract_ListTable validates the request and their
527 * parameters are valid.
528 *
529 * @param int $action_id Action ID.
530 */
531 protected function row_action_cancel( $action_id ) {
532 $this->process_row_action( $action_id, 'cancel' );
533 }
534
535 /**
536 * Implements the logic behind running an action. ActionScheduler_Abstract_ListTable validates the request and their
537 * parameters are valid.
538 *
539 * @param int $action_id Action ID.
540 */
541 protected function row_action_run( $action_id ) {
542 $this->process_row_action( $action_id, 'run' );
543 }
544
545 /**
546 * Force the data store schema updates.
547 */
548 protected function recreate_tables() {
549 if ( is_a( $this->store, 'ActionScheduler_HybridStore' ) ) {
550 $store = $this->store;
551 } else {
552 $store = new ActionScheduler_HybridStore();
553 }
554 add_action( 'action_scheduler/created_table', array( $store, 'set_autoincrement' ), 10, 2 );
555
556 $store_schema = new ActionScheduler_StoreSchema();
557 $logger_schema = new ActionScheduler_LoggerSchema();
558 $store_schema->register_tables( true );
559 $logger_schema->register_tables( true );
560
561 remove_action( 'action_scheduler/created_table', array( $store, 'set_autoincrement' ), 10 );
562 }
563 /**
564 * Implements the logic behind processing an action once an action link is clicked on the list table.
565 *
566 * @param int $action_id Action ID.
567 * @param string $row_action_type The type of action to perform on the action.
568 */
569 protected function process_row_action( $action_id, $row_action_type ) {
570 try {
571 switch ( $row_action_type ) {
572 case 'run':
573 $this->runner->process_action( $action_id, 'Admin List Table' );
574 break;
575 case 'cancel':
576 $this->store->cancel_action( $action_id );
577 break;
578 }
579 $success = 1;
580 $error_message = '';
581 } catch ( Exception $e ) {
582 $success = 0;
583 $error_message = $e->getMessage();
584 }
585
586 set_transient( 'action_scheduler_admin_notice', compact( 'action_id', 'success', 'error_message', 'row_action_type' ), 30 );
587 }
588
589 /**
590 * {@inheritDoc}
591 */
592 public function prepare_items() {
593 $this->prepare_column_headers();
594
595 $per_page = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
596
597 $query = array(
598 'per_page' => $per_page,
599 'offset' => $this->get_items_offset(),
600 'status' => $this->get_request_status(),
601 'orderby' => $this->get_request_orderby(),
602 'order' => $this->get_request_order(),
603 'search' => $this->get_request_search_query(),
604 );
605
606 /**
607 * Change query arguments to query for past-due actions.
608 * Past-due actions have the 'pending' status and are in the past.
609 * This is needed because registering 'past-due' as a status is overkill.
610 */
611 if ( 'past-due' === $this->get_request_status() ) {
612 $query['status'] = ActionScheduler_Store::STATUS_PENDING;
613 $query['date'] = as_get_datetime_object();
614 }
615
616 $this->items = array();
617
618 $total_items = $this->store->query_actions( $query, 'count' );
619
620 $status_labels = $this->store->get_status_labels();
621
622 foreach ( $this->store->query_actions( $query ) as $action_id ) {
623 try {
624 $action = $this->store->fetch_action( $action_id );
625 } catch ( Exception $e ) {
626 continue;
627 }
628 if ( is_a( $action, 'ActionScheduler_NullAction' ) ) {
629 continue;
630 }
631 $this->items[ $action_id ] = array(
632 'ID' => $action_id,
633 'hook' => $action->get_hook(),
634 'status_name' => $this->store->get_status( $action_id ),
635 'status' => $status_labels[ $this->store->get_status( $action_id ) ],
636 'args' => $action->get_args(),
637 'group' => $action->get_group(),
638 'log_entries' => $this->logger->get_logs( $action_id ),
639 'claim_id' => $this->store->get_claim_id( $action_id ),
640 'recurrence' => $this->get_recurrence( $action ),
641 'schedule' => $action->get_schedule(),
642 );
643 }
644
645 $this->set_pagination_args(
646 array(
647 'total_items' => $total_items,
648 'per_page' => $per_page,
649 'total_pages' => ceil( $total_items / $per_page ),
650 )
651 );
652 }
653
654 /**
655 * Prints the available statuses so the user can click to filter.
656 */
657 protected function display_filter_by_status() {
658 $this->status_counts = $this->store->action_counts() + $this->store->extra_action_counts();
659 parent::display_filter_by_status();
660 }
661
662 /**
663 * Get the text to display in the search box on the list table.
664 */
665 protected function get_search_box_button_text() {
666 return __( 'Search hook, args and claim ID', 'action-scheduler' );
667 }
668
669 /**
670 * {@inheritDoc}
671 */
672 protected function get_per_page_option_name() {
673 return str_replace( '-', '_', $this->screen->id ) . '_per_page';
674 }
675 }
676