PluginProbe ʕ •ᴥ•ʔ
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin / 3.11.0
WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin v3.11.0
4.9.0 0.9.6 1.0.0 1.0.1 1.0.2 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.2 1.7.0 1.7.1 1.8.0 1.8.1 1.9.0 2.0.0 2.0.1 2.1.1 2.2.1 2.3.1 2.4.0 2.5.0 2.5.1 2.6.0 2.7.0 2.8.0 2.9.0 3.0.1 3.0.2 3.0.3 3.1.0 3.10.0 3.11.0 3.11.1 3.2.0 3.2.1 3.3.0 3.4.0 3.5.0 3.5.1 3.5.2 3.6.1 3.7.0 3.8.0 3.8.2 3.9.0 4.0.1 4.1.0 4.1.1 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.8.0 trunk 0.10.0 0.10.1 0.11.1 0.11.2 0.3.1 0.3.2 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.5.2 0.6 0.7 0.8 0.8.2 0.8.3 0.8.4 0.8.5 0.8.6 0.8.7 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5
wp-mail-smtp / vendor / woocommerce / action-scheduler / classes / ActionScheduler_ListTable.php
wp-mail-smtp / vendor / woocommerce / action-scheduler / classes Last commit date
WP_CLI 2 years ago abstracts 2 years ago actions 2 years ago data-stores 2 years ago migration 2 years ago schedules 2 years ago schema 2 years ago ActionScheduler_ActionClaim.php 2 years ago ActionScheduler_ActionFactory.php 2 years ago ActionScheduler_AdminView.php 2 years ago ActionScheduler_AsyncRequest_QueueRunner.php 2 years ago ActionScheduler_Compatibility.php 2 years ago ActionScheduler_DataController.php 2 years ago ActionScheduler_DateTime.php 2 years ago ActionScheduler_Exception.php 2 years ago ActionScheduler_FatalErrorMonitor.php 2 years ago ActionScheduler_InvalidActionException.php 2 years ago ActionScheduler_ListTable.php 2 years ago ActionScheduler_LogEntry.php 2 years ago ActionScheduler_NullLogEntry.php 2 years ago ActionScheduler_OptionLock.php 2 years ago ActionScheduler_QueueCleaner.php 2 years ago ActionScheduler_QueueRunner.php 2 years ago ActionScheduler_Versions.php 2 years ago ActionScheduler_WPCommentCleaner.php 2 years ago ActionScheduler_wcSystemStatus.php 2 years ago
ActionScheduler_ListTable.php
658 lines
1 <?php
2
3 /**
4 * Implements the admin view of the actions.
5 * @codeCoverageIgnore
6 */
7 class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
8
9 /**
10 * The package name.
11 *
12 * @var string
13 */
14 protected $package = 'action-scheduler';
15
16 /**
17 * Columns to show (name => label).
18 *
19 * @var array
20 */
21 protected $columns = array();
22
23 /**
24 * Actions (name => label).
25 *
26 * @var array
27 */
28 protected $row_actions = array();
29
30 /**
31 * The active data stores
32 *
33 * @var ActionScheduler_Store
34 */
35 protected $store;
36
37 /**
38 * A logger to use for getting action logs to display
39 *
40 * @var ActionScheduler_Logger
41 */
42 protected $logger;
43
44 /**
45 * A ActionScheduler_QueueRunner runner instance (or child class)
46 *
47 * @var ActionScheduler_QueueRunner
48 */
49 protected $runner;
50
51 /**
52 * Bulk actions. The key of the array is the method name of the implementation:
53 *
54 * 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
80 * @param ActionScheduler_Logger $logger
81 * @param ActionScheduler_QueueRunner $runner
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' ) ) ) {
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
229 for ( $time_period_index = 0, $periods_included = 0, $seconds_remaining = $interval; $time_period_index < count( self::$time_periods ) && $seconds_remaining > 0 && $periods_included < $periods_to_include; $time_period_index++ ) {
230
231 $periods_in_interval = floor( $seconds_remaining / self::$time_periods[ $time_period_index ]['seconds'] );
232
233 if ( $periods_in_interval > 0 ) {
234 if ( ! empty( $output ) ) {
235 $output .= ' ';
236 }
237 $output .= sprintf( _n( self::$time_periods[ $time_period_index ]['names'][0], self::$time_periods[ $time_period_index ]['names'][1], $periods_in_interval, 'action-scheduler' ), $periods_in_interval );
238 $seconds_remaining -= $periods_in_interval * self::$time_periods[ $time_period_index ]['seconds'];
239 $periods_included++;
240 }
241 }
242
243 return $output;
244 }
245
246 /**
247 * Returns the recurrence of an action or 'Non-repeating'. The output is human readable.
248 *
249 * @param ActionScheduler_Action $action
250 *
251 * @return string
252 */
253 protected function get_recurrence( $action ) {
254 $schedule = $action->get_schedule();
255 if ( $schedule->is_recurring() && method_exists( $schedule, 'get_recurrence' ) ) {
256 $recurrence = $schedule->get_recurrence();
257
258 if ( is_numeric( $recurrence ) ) {
259 /* translators: %s: time interval */
260 return sprintf( __( 'Every %s', 'action-scheduler' ), self::human_interval( $recurrence ) );
261 } else {
262 return $recurrence;
263 }
264 }
265
266 return __( 'Non-repeating', 'action-scheduler' );
267 }
268
269 /**
270 * Serializes the argument of an action to render it in a human friendly format.
271 *
272 * @param array $row The array representation of the current row of the table
273 *
274 * @return string
275 */
276 public function column_args( array $row ) {
277 if ( empty( $row['args'] ) ) {
278 return apply_filters( 'action_scheduler_list_table_column_args', '', $row );
279 }
280
281 $row_html = '<ul>';
282 foreach ( $row['args'] as $key => $value ) {
283 $row_html .= sprintf( '<li><code>%s => %s</code></li>', esc_html( var_export( $key, true ) ), esc_html( var_export( $value, true ) ) );
284 }
285 $row_html .= '</ul>';
286
287 return apply_filters( 'action_scheduler_list_table_column_args', $row_html, $row );
288 }
289
290 /**
291 * Prints the logs entries inline. We do so to avoid loading Javascript and other hacks to show it in a modal.
292 *
293 * @param array $row Action array.
294 * @return string
295 */
296 public function column_log_entries( array $row ) {
297
298 $log_entries_html = '<ol>';
299
300 $timezone = new DateTimezone( 'UTC' );
301
302 foreach ( $row['log_entries'] as $log_entry ) {
303 $log_entries_html .= $this->get_log_entry_html( $log_entry, $timezone );
304 }
305
306 $log_entries_html .= '</ol>';
307
308 return $log_entries_html;
309 }
310
311 /**
312 * Prints the logs entries inline. We do so to avoid loading Javascript and other hacks to show it in a modal.
313 *
314 * @param ActionScheduler_LogEntry $log_entry
315 * @param DateTimezone $timezone
316 * @return string
317 */
318 protected function get_log_entry_html( ActionScheduler_LogEntry $log_entry, DateTimezone $timezone ) {
319 $date = $log_entry->get_date();
320 $date->setTimezone( $timezone );
321 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() ) );
322 }
323
324 /**
325 * Only display row actions for pending actions.
326 *
327 * @param array $row Row to render
328 * @param string $column_name Current row
329 *
330 * @return string
331 */
332 protected function maybe_render_actions( $row, $column_name ) {
333 if ( 'pending' === strtolower( $row[ 'status_name' ] ) ) {
334 return parent::maybe_render_actions( $row, $column_name );
335 }
336
337 return '';
338 }
339
340 /**
341 * Renders admin notifications
342 *
343 * Notifications:
344 * 1. When the maximum number of tasks are being executed simultaneously.
345 * 2. Notifications when a task is manually executed.
346 * 3. Tables are missing.
347 */
348 public function display_admin_notices() {
349 global $wpdb;
350
351 if ( ( is_a( $this->store, 'ActionScheduler_HybridStore' ) || is_a( $this->store, 'ActionScheduler_DBStore' ) ) && apply_filters( 'action_scheduler_enable_recreate_data_store', true ) ) {
352 $table_list = array(
353 'actionscheduler_actions',
354 'actionscheduler_logs',
355 'actionscheduler_groups',
356 'actionscheduler_claims',
357 );
358
359 $found_tables = $wpdb->get_col( "SHOW TABLES LIKE '{$wpdb->prefix}actionscheduler%'" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
360 foreach ( $table_list as $table_name ) {
361 if ( ! in_array( $wpdb->prefix . $table_name, $found_tables ) ) {
362 $this->admin_notices[] = array(
363 'class' => 'error',
364 'message' => __( 'It appears one or more database tables were missing. Attempting to re-create the missing table(s).' , 'action-scheduler' ),
365 );
366 $this->recreate_tables();
367 parent::display_admin_notices();
368
369 return;
370 }
371 }
372 }
373
374 if ( $this->runner->has_maximum_concurrent_batches() ) {
375 $claim_count = $this->store->get_claim_count();
376 $this->admin_notices[] = array(
377 'class' => 'updated',
378 'message' => sprintf(
379 /* translators: %s: amount of claims */
380 _n(
381 'Maximum simultaneous queues already in progress (%s queue). No additional queues will begin processing until the current queues are complete.',
382 'Maximum simultaneous queues already in progress (%s queues). No additional queues will begin processing until the current queues are complete.',
383 $claim_count,
384 'action-scheduler'
385 ),
386 $claim_count
387 ),
388 );
389 } elseif ( $this->store->has_pending_actions_due() ) {
390
391 $async_request_lock_expiration = ActionScheduler::lock()->get_expiration( 'async-request-runner' );
392
393 // No lock set or lock expired
394 if ( false === $async_request_lock_expiration || $async_request_lock_expiration < time() ) {
395 $in_progress_url = add_query_arg( 'status', 'in-progress', remove_query_arg( 'status' ) );
396 /* translators: %s: process URL */
397 $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 ) );
398 } else {
399 /* translators: %d: seconds */
400 $async_request_message = sprintf( __( 'The next queue will begin processing in approximately %d seconds.', 'action-scheduler' ), $async_request_lock_expiration - time() );
401 }
402
403 $this->admin_notices[] = array(
404 'class' => 'notice notice-info',
405 'message' => $async_request_message,
406 );
407 }
408
409 $notification = get_transient( 'action_scheduler_admin_notice' );
410
411 if ( is_array( $notification ) ) {
412 delete_transient( 'action_scheduler_admin_notice' );
413
414 $action = $this->store->fetch_action( $notification['action_id'] );
415 $action_hook_html = '<strong><code>' . $action->get_hook() . '</code></strong>';
416 if ( 1 == $notification['success'] ) {
417 $class = 'updated';
418 switch ( $notification['row_action_type'] ) {
419 case 'run' :
420 /* translators: %s: action HTML */
421 $action_message_html = sprintf( __( 'Successfully executed action: %s', 'action-scheduler' ), $action_hook_html );
422 break;
423 case 'cancel' :
424 /* translators: %s: action HTML */
425 $action_message_html = sprintf( __( 'Successfully canceled action: %s', 'action-scheduler' ), $action_hook_html );
426 break;
427 default :
428 /* translators: %s: action HTML */
429 $action_message_html = sprintf( __( 'Successfully processed change for action: %s', 'action-scheduler' ), $action_hook_html );
430 break;
431 }
432 } else {
433 $class = 'error';
434 /* translators: 1: action HTML 2: action ID 3: error message */
435 $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'] ) );
436 }
437
438 $action_message_html = apply_filters( 'action_scheduler_admin_notice_html', $action_message_html, $action, $notification );
439
440 $this->admin_notices[] = array(
441 'class' => $class,
442 'message' => $action_message_html,
443 );
444 }
445
446 parent::display_admin_notices();
447 }
448
449 /**
450 * Prints the scheduled date in a human friendly format.
451 *
452 * @param array $row The array representation of the current row of the table
453 *
454 * @return string
455 */
456 public function column_schedule( $row ) {
457 return $this->get_schedule_display_string( $row['schedule'] );
458 }
459
460 /**
461 * Get the scheduled date in a human friendly format.
462 *
463 * @param ActionScheduler_Schedule $schedule
464 * @return string
465 */
466 protected function get_schedule_display_string( ActionScheduler_Schedule $schedule ) {
467
468 $schedule_display_string = '';
469
470 if ( is_a( $schedule, 'ActionScheduler_NullSchedule' ) ) {
471 return __( 'async', 'action-scheduler' );
472 }
473
474 if ( ! method_exists( $schedule, 'get_date' ) || ! $schedule->get_date() ) {
475 return '0000-00-00 00:00:00';
476 }
477
478 $next_timestamp = $schedule->get_date()->getTimestamp();
479
480 $schedule_display_string .= $schedule->get_date()->format( 'Y-m-d H:i:s O' );
481 $schedule_display_string .= '<br/>';
482
483 if ( gmdate( 'U' ) > $next_timestamp ) {
484 /* translators: %s: date interval */
485 $schedule_display_string .= sprintf( __( ' (%s ago)', 'action-scheduler' ), self::human_interval( gmdate( 'U' ) - $next_timestamp ) );
486 } else {
487 /* translators: %s: date interval */
488 $schedule_display_string .= sprintf( __( ' (%s)', 'action-scheduler' ), self::human_interval( $next_timestamp - gmdate( 'U' ) ) );
489 }
490
491 return $schedule_display_string;
492 }
493
494 /**
495 * Bulk delete
496 *
497 * Deletes actions based on their ID. This is the handler for the bulk delete. It assumes the data
498 * properly validated by the callee and it will delete the actions without any extra validation.
499 *
500 * @param array $ids
501 * @param string $ids_sql Inherited and unused
502 */
503 protected function bulk_delete( array $ids, $ids_sql ) {
504 foreach ( $ids as $id ) {
505 $this->store->delete_action( $id );
506 }
507 }
508
509 /**
510 * Implements the logic behind running an action. ActionScheduler_Abstract_ListTable validates the request and their
511 * parameters are valid.
512 *
513 * @param int $action_id
514 */
515 protected function row_action_cancel( $action_id ) {
516 $this->process_row_action( $action_id, 'cancel' );
517 }
518
519 /**
520 * Implements the logic behind running an action. ActionScheduler_Abstract_ListTable validates the request and their
521 * parameters are valid.
522 *
523 * @param int $action_id
524 */
525 protected function row_action_run( $action_id ) {
526 $this->process_row_action( $action_id, 'run' );
527 }
528
529 /**
530 * Force the data store schema updates.
531 */
532 protected function recreate_tables() {
533 if ( is_a( $this->store, 'ActionScheduler_HybridStore' ) ) {
534 $store = $this->store;
535 } else {
536 $store = new ActionScheduler_HybridStore();
537 }
538 add_action( 'action_scheduler/created_table', array( $store, 'set_autoincrement' ), 10, 2 );
539
540 $store_schema = new ActionScheduler_StoreSchema();
541 $logger_schema = new ActionScheduler_LoggerSchema();
542 $store_schema->register_tables( true );
543 $logger_schema->register_tables( true );
544
545 remove_action( 'action_scheduler/created_table', array( $store, 'set_autoincrement' ), 10 );
546 }
547 /**
548 * Implements the logic behind processing an action once an action link is clicked on the list table.
549 *
550 * @param int $action_id
551 * @param string $row_action_type The type of action to perform on the action.
552 */
553 protected function process_row_action( $action_id, $row_action_type ) {
554 try {
555 switch ( $row_action_type ) {
556 case 'run' :
557 $this->runner->process_action( $action_id, 'Admin List Table' );
558 break;
559 case 'cancel' :
560 $this->store->cancel_action( $action_id );
561 break;
562 }
563 $success = 1;
564 $error_message = '';
565 } catch ( Exception $e ) {
566 $success = 0;
567 $error_message = $e->getMessage();
568 }
569
570 set_transient( 'action_scheduler_admin_notice', compact( 'action_id', 'success', 'error_message', 'row_action_type' ), 30 );
571 }
572
573 /**
574 * {@inheritDoc}
575 */
576 public function prepare_items() {
577 $this->prepare_column_headers();
578
579 $per_page = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
580
581 $query = array(
582 'per_page' => $per_page,
583 'offset' => $this->get_items_offset(),
584 'status' => $this->get_request_status(),
585 'orderby' => $this->get_request_orderby(),
586 'order' => $this->get_request_order(),
587 'search' => $this->get_request_search_query(),
588 );
589
590 /**
591 * Change query arguments to query for past-due actions.
592 * Past-due actions have the 'pending' status and are in the past.
593 * This is needed because registering 'past-due' as a status is overkill.
594 */
595 if ( 'past-due' === $this->get_request_status() ) {
596 $query['status'] = ActionScheduler_Store::STATUS_PENDING;
597 $query['date'] = as_get_datetime_object();
598 }
599
600 $this->items = array();
601
602 $total_items = $this->store->query_actions( $query, 'count' );
603
604 $status_labels = $this->store->get_status_labels();
605
606 foreach ( $this->store->query_actions( $query ) as $action_id ) {
607 try {
608 $action = $this->store->fetch_action( $action_id );
609 } catch ( Exception $e ) {
610 continue;
611 }
612 if ( is_a( $action, 'ActionScheduler_NullAction' ) ) {
613 continue;
614 }
615 $this->items[ $action_id ] = array(
616 'ID' => $action_id,
617 'hook' => $action->get_hook(),
618 'status_name' => $this->store->get_status( $action_id ),
619 'status' => $status_labels[ $this->store->get_status( $action_id ) ],
620 'args' => $action->get_args(),
621 'group' => $action->get_group(),
622 'log_entries' => $this->logger->get_logs( $action_id ),
623 'claim_id' => $this->store->get_claim_id( $action_id ),
624 'recurrence' => $this->get_recurrence( $action ),
625 'schedule' => $action->get_schedule(),
626 );
627 }
628
629 $this->set_pagination_args( array(
630 'total_items' => $total_items,
631 'per_page' => $per_page,
632 'total_pages' => ceil( $total_items / $per_page ),
633 ) );
634 }
635
636 /**
637 * Prints the available statuses so the user can click to filter.
638 */
639 protected function display_filter_by_status() {
640 $this->status_counts = $this->store->action_counts() + $this->store->extra_action_counts();
641 parent::display_filter_by_status();
642 }
643
644 /**
645 * Get the text to display in the search box on the list table.
646 */
647 protected function get_search_box_button_text() {
648 return __( 'Search hook, args and claim ID', 'action-scheduler' );
649 }
650
651 /**
652 * {@inheritDoc}
653 */
654 protected function get_per_page_option_name() {
655 return str_replace( '-', '_', $this->screen->id ) . '_per_page';
656 }
657 }
658