PluginProbe ʕ •ᴥ•ʔ
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 2.12.1
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v2.12.1
2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 0.0.8 0.0.9 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.1.0 1.1.1 1.1.2 1.10.0 1.10.1 1.11.0 1.12.0 1.12.1 1.12.2 1.12.3 1.13.0 1.13.1 1.13.2 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.5.0 1.5.1 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.8.0 1.9.0 1.9.1 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.2.0 2.2.1 2.2.2 2.3.0 2.4.0 2.5.0 2.5.2 2.6.0
sureforms / inc / lib / action-scheduler / classes / ActionScheduler_ListTable.php
sureforms / inc / lib / action-scheduler / classes Last commit date
WP_CLI 2 years ago abstracts 5 months 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
674 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 *
55 * bulk_<key>(array $ids, string $sql_in).
56 *
57 * See the comments in the parent class for further details
58 *
59 * @var array
60 */
61 protected $bulk_actions = array();
62
63 /**
64 * Flag variable to render our notifications, if any, once.
65 *
66 * @var bool
67 */
68 protected static $did_notification = false;
69
70 /**
71 * Array of seconds for common time periods, like week or month, alongside an internationalised string representation, i.e. "Day" or "Days"
72 *
73 * @var array
74 */
75 private static $time_periods;
76
77 /**
78 * Sets the current data store object into `store->action` and initialises the object.
79 *
80 * @param ActionScheduler_Store $store
81 * @param ActionScheduler_Logger $logger
82 * @param ActionScheduler_QueueRunner $runner
83 */
84 public function __construct( ActionScheduler_Store $store, ActionScheduler_Logger $logger, ActionScheduler_QueueRunner $runner ) {
85
86 $this->store = $store;
87 $this->logger = $logger;
88 $this->runner = $runner;
89
90 $this->table_header = __( 'Scheduled Actions', 'action-scheduler' );
91
92 $this->bulk_actions = array(
93 'delete' => __( 'Delete', 'action-scheduler' ),
94 );
95
96 $this->columns = array(
97 'hook' => __( 'Hook', 'action-scheduler' ),
98 'status' => __( 'Status', 'action-scheduler' ),
99 'args' => __( 'Arguments', 'action-scheduler' ),
100 'group' => __( 'Group', 'action-scheduler' ),
101 'recurrence' => __( 'Recurrence', 'action-scheduler' ),
102 'schedule' => __( 'Scheduled Date', 'action-scheduler' ),
103 'log_entries' => __( 'Log', 'action-scheduler' ),
104 );
105
106 $this->sort_by = array(
107 'schedule',
108 'hook',
109 'group',
110 );
111
112 $this->search_by = array(
113 'hook',
114 'args',
115 'claim_id',
116 );
117
118 $request_status = $this->get_request_status();
119
120 if ( empty( $request_status ) ) {
121 $this->sort_by[] = 'status';
122 } elseif ( in_array( $request_status, array( 'in-progress', 'failed' ) ) ) {
123 $this->columns += array( 'claim_id' => __( 'Claim ID', 'action-scheduler' ) );
124 $this->sort_by[] = 'claim_id';
125 }
126
127 $this->row_actions = array(
128 'hook' => array(
129 'run' => array(
130 'name' => __( 'Run', 'action-scheduler' ),
131 'desc' => __( 'Process the action now as if it were run as part of a queue', 'action-scheduler' ),
132 ),
133 'cancel' => array(
134 'name' => __( 'Cancel', 'action-scheduler' ),
135 'desc' => __( 'Cancel the action now to avoid it being run in future', 'action-scheduler' ),
136 'class' => 'cancel trash',
137 ),
138 ),
139 );
140
141 self::$time_periods = array(
142 array(
143 'seconds' => YEAR_IN_SECONDS,
144 /* translators: %s: amount of time */
145 'names' => _n_noop( '%s year', '%s years', 'action-scheduler' ),
146 ),
147 array(
148 'seconds' => MONTH_IN_SECONDS,
149 /* translators: %s: amount of time */
150 'names' => _n_noop( '%s month', '%s months', 'action-scheduler' ),
151 ),
152 array(
153 'seconds' => WEEK_IN_SECONDS,
154 /* translators: %s: amount of time */
155 'names' => _n_noop( '%s week', '%s weeks', 'action-scheduler' ),
156 ),
157 array(
158 'seconds' => DAY_IN_SECONDS,
159 /* translators: %s: amount of time */
160 'names' => _n_noop( '%s day', '%s days', 'action-scheduler' ),
161 ),
162 array(
163 'seconds' => HOUR_IN_SECONDS,
164 /* translators: %s: amount of time */
165 'names' => _n_noop( '%s hour', '%s hours', 'action-scheduler' ),
166 ),
167 array(
168 'seconds' => MINUTE_IN_SECONDS,
169 /* translators: %s: amount of time */
170 'names' => _n_noop( '%s minute', '%s minutes', 'action-scheduler' ),
171 ),
172 array(
173 'seconds' => 1,
174 /* translators: %s: amount of time */
175 'names' => _n_noop( '%s second', '%s seconds', 'action-scheduler' ),
176 ),
177 );
178
179 parent::__construct(
180 array(
181 'singular' => 'action-scheduler',
182 'plural' => 'action-scheduler',
183 'ajax' => false,
184 )
185 );
186
187 add_screen_option(
188 'per_page',
189 array(
190 'default' => $this->items_per_page,
191 )
192 );
193
194 add_filter( 'set_screen_option_' . $this->get_per_page_option_name(), array( $this, 'set_items_per_page_option' ), 10, 3 );
195 set_screen_options();
196 }
197
198 /**
199 * Handles setting the items_per_page option for this screen.
200 *
201 * @param mixed $status Default false (to skip saving the current option).
202 * @param string $option Screen option name.
203 * @param int $value Screen option value.
204 * @return int
205 */
206 public function set_items_per_page_option( $status, $option, $value ) {
207 return $value;
208 }
209 /**
210 * Convert an interval of seconds into a two part human friendly string.
211 *
212 * The WordPress human_time_diff() function only calculates the time difference to one degree, meaning
213 * even if an action is 1 day and 11 hours away, it will display "1 day". This function goes one step
214 * further to display two degrees of accuracy.
215 *
216 * Inspired by the Crontrol::interval() function by Edward Dale: https://wordpress.org/plugins/wp-crontrol/
217 *
218 * @param int $interval A interval in seconds.
219 * @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.
220 * @return string A human friendly string representation of the interval.
221 */
222 private static function human_interval( $interval, $periods_to_include = 2 ) {
223
224 if ( $interval <= 0 ) {
225 return __( 'Now!', 'action-scheduler' );
226 }
227
228 $output = '';
229
230 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++ ) {
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( _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 );
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
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 ) ) );
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
316 * @param DateTimezone $timezone
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 ) ) {
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 if ( 1 == $notification['success'] ) {
418 $class = 'updated';
419 switch ( $notification['row_action_type'] ) {
420 case 'run':
421 /* translators: %s: action HTML */
422 $action_message_html = sprintf( __( 'Successfully executed action: %s', 'action-scheduler' ), $action_hook_html );
423 break;
424 case 'cancel':
425 /* translators: %s: action HTML */
426 $action_message_html = sprintf( __( 'Successfully canceled action: %s', 'action-scheduler' ), $action_hook_html );
427 break;
428 default:
429 /* translators: %s: action HTML */
430 $action_message_html = sprintf( __( 'Successfully processed change for action: %s', 'action-scheduler' ), $action_hook_html );
431 break;
432 }
433 } else {
434 $class = 'error';
435 /* translators: 1: action HTML 2: action ID 3: error message */
436 $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'] ) );
437 }
438
439 $action_message_html = apply_filters( 'action_scheduler_admin_notice_html', $action_message_html, $action, $notification );
440
441 $this->admin_notices[] = array(
442 'class' => $class,
443 'message' => $action_message_html,
444 );
445 }
446
447 parent::display_admin_notices();
448 }
449
450 /**
451 * Prints the scheduled date in a human friendly format.
452 *
453 * @param array $row The array representation of the current row of the table
454 *
455 * @return string
456 */
457 public function column_schedule( $row ) {
458 return $this->get_schedule_display_string( $row['schedule'] );
459 }
460
461 /**
462 * Get the scheduled date in a human friendly format.
463 *
464 * @param ActionScheduler_Schedule $schedule
465 * @return string
466 */
467 protected function get_schedule_display_string( ActionScheduler_Schedule $schedule ) {
468
469 $schedule_display_string = '';
470
471 if ( is_a( $schedule, 'ActionScheduler_NullSchedule' ) ) {
472 return __( 'async', 'action-scheduler' );
473 }
474
475 if ( ! method_exists( $schedule, 'get_date' ) || ! $schedule->get_date() ) {
476 return '0000-00-00 00:00:00';
477 }
478
479 $next_timestamp = $schedule->get_date()->getTimestamp();
480
481 $schedule_display_string .= $schedule->get_date()->format( 'Y-m-d H:i:s O' );
482 $schedule_display_string .= '<br/>';
483
484 if ( gmdate( 'U' ) > $next_timestamp ) {
485 /* translators: %s: date interval */
486 $schedule_display_string .= sprintf( __( ' (%s ago)', 'action-scheduler' ), self::human_interval( gmdate( 'U' ) - $next_timestamp ) );
487 } else {
488 /* translators: %s: date interval */
489 $schedule_display_string .= sprintf( __( ' (%s)', 'action-scheduler' ), self::human_interval( $next_timestamp - gmdate( 'U' ) ) );
490 }
491
492 return $schedule_display_string;
493 }
494
495 /**
496 * Bulk delete
497 *
498 * Deletes actions based on their ID. This is the handler for the bulk delete. It assumes the data
499 * properly validated by the callee and it will delete the actions without any extra validation.
500 *
501 * @param array $ids
502 * @param string $ids_sql Inherited and unused
503 */
504 protected function bulk_delete( array $ids, $ids_sql ) {
505 foreach ( $ids as $id ) {
506 try {
507 $this->store->delete_action( $id );
508 } catch ( Exception $e ) {
509 // A possible reason for an exception would include a scenario where the same action is deleted by a
510 // concurrent request.
511 error_log(
512 sprintf(
513 /* translators: 1: action ID 2: exception message. */
514 __( 'Action Scheduler was unable to delete action %1$d. Reason: %2$s', 'action-scheduler' ),
515 $id,
516 $e->getMessage()
517 )
518 );
519 }
520 }
521 }
522
523 /**
524 * Implements the logic behind running an action. ActionScheduler_Abstract_ListTable validates the request and their
525 * parameters are valid.
526 *
527 * @param int $action_id
528 */
529 protected function row_action_cancel( $action_id ) {
530 $this->process_row_action( $action_id, 'cancel' );
531 }
532
533 /**
534 * Implements the logic behind running an action. ActionScheduler_Abstract_ListTable validates the request and their
535 * parameters are valid.
536 *
537 * @param int $action_id
538 */
539 protected function row_action_run( $action_id ) {
540 $this->process_row_action( $action_id, 'run' );
541 }
542
543 /**
544 * Force the data store schema updates.
545 */
546 protected function recreate_tables() {
547 if ( is_a( $this->store, 'ActionScheduler_HybridStore' ) ) {
548 $store = $this->store;
549 } else {
550 $store = new ActionScheduler_HybridStore();
551 }
552 add_action( 'action_scheduler/created_table', array( $store, 'set_autoincrement' ), 10, 2 );
553
554 $store_schema = new ActionScheduler_StoreSchema();
555 $logger_schema = new ActionScheduler_LoggerSchema();
556 $store_schema->register_tables( true );
557 $logger_schema->register_tables( true );
558
559 remove_action( 'action_scheduler/created_table', array( $store, 'set_autoincrement' ), 10 );
560 }
561 /**
562 * Implements the logic behind processing an action once an action link is clicked on the list table.
563 *
564 * @param int $action_id
565 * @param string $row_action_type The type of action to perform on the action.
566 */
567 protected function process_row_action( $action_id, $row_action_type ) {
568 try {
569 switch ( $row_action_type ) {
570 case 'run':
571 $this->runner->process_action( $action_id, 'Admin List Table' );
572 break;
573 case 'cancel':
574 $this->store->cancel_action( $action_id );
575 break;
576 }
577 $success = 1;
578 $error_message = '';
579 } catch ( Exception $e ) {
580 $success = 0;
581 $error_message = $e->getMessage();
582 }
583
584 set_transient( 'action_scheduler_admin_notice', compact( 'action_id', 'success', 'error_message', 'row_action_type' ), 30 );
585 }
586
587 /**
588 * {@inheritDoc}
589 */
590 public function prepare_items() {
591 $this->prepare_column_headers();
592
593 $per_page = $this->get_items_per_page( $this->get_per_page_option_name(), $this->items_per_page );
594
595 $query = array(
596 'per_page' => $per_page,
597 'offset' => $this->get_items_offset(),
598 'status' => $this->get_request_status(),
599 'orderby' => $this->get_request_orderby(),
600 'order' => $this->get_request_order(),
601 'search' => $this->get_request_search_query(),
602 );
603
604 /**
605 * Change query arguments to query for past-due actions.
606 * Past-due actions have the 'pending' status and are in the past.
607 * This is needed because registering 'past-due' as a status is overkill.
608 */
609 if ( 'past-due' === $this->get_request_status() ) {
610 $query['status'] = ActionScheduler_Store::STATUS_PENDING;
611 $query['date'] = as_get_datetime_object();
612 }
613
614 $this->items = array();
615
616 $total_items = $this->store->query_actions( $query, 'count' );
617
618 $status_labels = $this->store->get_status_labels();
619
620 foreach ( $this->store->query_actions( $query ) as $action_id ) {
621 try {
622 $action = $this->store->fetch_action( $action_id );
623 } catch ( Exception $e ) {
624 continue;
625 }
626 if ( is_a( $action, 'ActionScheduler_NullAction' ) ) {
627 continue;
628 }
629 $this->items[ $action_id ] = array(
630 'ID' => $action_id,
631 'hook' => $action->get_hook(),
632 'status_name' => $this->store->get_status( $action_id ),
633 'status' => $status_labels[ $this->store->get_status( $action_id ) ],
634 'args' => $action->get_args(),
635 'group' => $action->get_group(),
636 'log_entries' => $this->logger->get_logs( $action_id ),
637 'claim_id' => $this->store->get_claim_id( $action_id ),
638 'recurrence' => $this->get_recurrence( $action ),
639 'schedule' => $action->get_schedule(),
640 );
641 }
642
643 $this->set_pagination_args(
644 array(
645 'total_items' => $total_items,
646 'per_page' => $per_page,
647 'total_pages' => ceil( $total_items / $per_page ),
648 )
649 );
650 }
651
652 /**
653 * Prints the available statuses so the user can click to filter.
654 */
655 protected function display_filter_by_status() {
656 $this->status_counts = $this->store->action_counts() + $this->store->extra_action_counts();
657 parent::display_filter_by_status();
658 }
659
660 /**
661 * Get the text to display in the search box on the list table.
662 */
663 protected function get_search_box_button_text() {
664 return __( 'Search hook, args and claim ID', 'action-scheduler' );
665 }
666
667 /**
668 * {@inheritDoc}
669 */
670 protected function get_per_page_option_name() {
671 return str_replace( '-', '_', $this->screen->id ) . '_per_page';
672 }
673 }
674