true, 'show_in_menu' => 'tools.php', 'show_in_admin_bar' => false, )); } /** * Customise the post status related views displayed on the Scheduled Actions administration screen. * * @param array $views An associative array of views and view labels which can be used to filter the 'scheduled-action' posts displayed on the Scheduled Actions administration screen. * @return array $views An associative array of views and view labels which can be used to filter the 'scheduled-action' posts displayed on the Scheduled Actions administration screen. */ public function list_table_views( $views ) { foreach ( $views as $view_key => $view ) { if ( 'publish' == $view_key ) { $views[ $view_key ] = str_replace( __( 'Published', 'action-scheduler' ), __( 'Complete', 'action-scheduler' ), $view ); break; } } return $views; } /** * Do not include the "Edit" action for the Scheduled Actions administration screen. * * Hooked to the 'bulk_actions-edit-action-scheduler' filter. * * @param array $actions An associative array of actions which can be performed on the 'scheduled-action' post type. * @return array $actions An associative array of actions which can be performed on the 'scheduled-action' post type. */ public function bulk_actions( $actions ) { if ( isset( $actions['edit'] ) ) { unset( $actions['edit'] ); } return $actions; } /** * Completely customer the columns displayed on the Scheduled Actions administration screen. * * Because we can't filter the content of the default title and date columns, we need to recreate our own * custom columns for displaying those post fields. For the column content, @see self::list_table_column_content(). * * @param array $columns An associative array of columns that are use for the table on the Scheduled Actions administration screen. * @return array $columns An associative array of columns that are use for the table on the Scheduled Actions administration screen. */ public function list_table_columns( $columns ) { $custom_columns = array( 'cb' => $columns['cb'], 'hook' => __( 'Hook', 'action-scheduler' ), // because we want to customise the inline actions 'status' => __( 'Status', 'action-scheduler' ), 'args' => __( 'Arguments', 'action-scheduler' ), 'taxonomy-action-group' => __( 'Group', 'action-scheduler' ), 'recurrence' => __( 'Recurrence', 'action-scheduler' ), 'scheduled' => __( 'Scheduled Date', 'action-scheduler' ), // because we want to customise how the date is displayed ); if ( isset( $_REQUEST['post_status'] ) ) { if ( in_array( $_REQUEST['post_status'], array( 'failed', 'in-progress' ) ) ) { $custom_columns['modified'] = __( 'Started', 'action-scheduler' ); } elseif ( 'publish' == $_REQUEST['post_status'] ) { $custom_columns['modified'] = __( 'Completed', 'action-scheduler' ); } } $custom_columns['claim'] = __( 'Claim ID', 'action-scheduler' ); $custom_columns['comments'] = __( 'Log', 'action-scheduler' ); return $custom_columns; } /** * Make our custom title & date columns use defaulting title & date sorting. * * @param array $columns An associative array of columns that can be used to sort the table on the Scheduled Actions administration screen. * @return array $columns An associative array of columns that can be used to sort the table on the Scheduled Actions administration screen. */ public static function list_table_sortable_columns( $columns ) { $columns['hook'] = 'title'; $columns['scheduled'] = array( 'date', true ); $columns['modified'] = 'modified'; $columns['claim'] = 'post_password'; return $columns; } /** * Print the content for our custom columns. * * @param string $column_name The key for the column for which we should output our content. * @param int $post_id The ID of the 'scheduled-action' post for which this row relates. * @return void */ public static function list_table_column_content( $column_name, $post_id ) { global $post; $action = ActionScheduler::store()->fetch_action( $post_id ); $action_title = ( 'trash' == $post->post_status ) ? $post->post_title : $action->get_hook(); $recurrence = ( 'trash' == $post->post_status ) ? 0 : $action->get_schedule(); $next_timestamp = as_get_datetime_object( $post->post_date_gmt )->format( 'U' ); $status = get_post_status( $post_id ); switch ( $column_name ) { case 'hook': echo $action_title; break; case 'status': if ( 'publish' == $status ) { _e( 'Complete', 'action-scheduler' ); } else { echo ucfirst( $status ); } break; case 'args': $action_args = ( 'trash' == $post->post_status ) ? $post->post_content : $action->get_args(); if ( is_array( $action_args ) ) { foreach( $action_args as $key => $value ) { printf( "%s => %s
", $key, $value ); } } break; case 'recurrence': if ( method_exists( $recurrence, 'interval_in_seconds' ) ) { echo self::human_interval( $recurrence->interval_in_seconds() ); } else { _e( 'Non-repeating', 'action-scheduler' ); } break; case 'scheduled': echo get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $next_timestamp ), 'Y-m-d H:i:s' ); if ( gmdate( 'U' ) > $next_timestamp ) { printf( __( ' (%s ago)', 'action-scheduler' ), human_time_diff( gmdate( 'U' ), $next_timestamp ) ); } else { echo ' (' . human_time_diff( gmdate( 'U' ), $next_timestamp ) . ')'; } break; case 'modified': echo get_post_modified_time( 'Y-m-d H:i:s' ); $modified_timestamp = get_post_modified_time( 'U', true ); if ( gmdate( 'U' ) > $modified_timestamp ) { printf( __( ' (%s ago)', 'action-scheduler' ), human_time_diff( gmdate( 'U' ), $modified_timestamp ) ); } else { echo ' (' . human_time_diff( gmdate( 'U' ), $modified_timestamp ) . ')'; } break; case 'claim': echo $post->post_password; break; } } /** * Hide the inline "Edit" action for all 'scheduled-action' posts. * * Hooked to the 'post_row_actions' filter. * * @param array $actions An associative array of actions which can be performed on the 'scheduled-action' post type. * @return array $actions An associative array of actions which can be performed on the 'scheduled-action' post type. */ public static function row_actions( $actions, $post ) { if ( ActionScheduler_wpPostStore::POST_TYPE == $post->post_type ) { if ( isset( $actions['edit'] ) ) { unset( $actions['edit'] ); } if ( isset( $actions['inline hide-if-no-js'] ) ) { unset( $actions['inline hide-if-no-js'] ); } if ( current_user_can( 'edit_post', $post->ID ) && ! in_array( $post->post_status, array( 'publish', 'in-progress', 'trash' ) ) ) { $actions['process'] = "" . __( 'Run', 'action-scheduler' ) . ""; } ksort( $actions ); } return $actions; } /** * Retrieve a URI to execute a scheduled action. * * @param int $action_id The ID for a 'scheduled-action' post. * @param string $operation To run the action (including trigger before/after hooks), log the execution and update the action's status, use 'process', to simply trigger the action, use 'execute'. Default 'execute'. * @return string The URL for running the action. */ private static function get_run_action_link( $action_id, $operation = 'process' ) { if ( !$post = get_post( $action_id ) ) return; $post_type_object = get_post_type_object( $post->post_type ); if ( ! $post_type_object ) return; if ( ! current_user_can( 'edit_post', $post->ID ) ) return; $execute_link = add_query_arg( array( 'action' => $operation, 'post_id' => $post->ID ), self::$admin_url ); return wp_nonce_url( $execute_link, "{$operation}-action_{$post->ID}" ); } /** * Run an action when triggered from the Action Scheduler administration screen. * * @codeCoverageIgnore */ public static function maybe_execute_action() { if ( ! isset( $_GET['action'] ) || 'process' != $_GET['action'] || ! isset( $_GET['post_id'] ) ){ return; } $action_id = absint( $_GET['post_id'] ); check_admin_referer( $_GET['action'] . '-action_' . $action_id ); try { ActionScheduler::runner()->process_action( $action_id ); $success = 1; } catch ( Exception $e ) { $success = 0; } wp_redirect( add_query_arg( array( 'executed' => $success, 'ids' => $action_id ), self::$admin_url ) ); exit(); } /** * Convert an interval of seconds into a two part human friendly string. * * The WordPress human_time_diff() function only calculates the time difference to one degree, meaning * even if an action is 1 day and 11 hours away, it will display "1 day". This funciton goes one step * further to display two degrees of accuracy. * * Based on Crontrol::interval() funciton by Edward Dale: https://wordpress.org/plugins/wp-crontrol/ * * @param int $interval A interval in seconds. * @return string A human friendly string representation of the interval. */ public static function admin_notices() { if ( self::is_admin_page() ) { if ( ActionScheduler_Store::instance()->get_claim_count() >= apply_filters( 'action_scheduler_queue_runner_concurrent_batches', 5 ) ) : ?>

get_claim_count() ); ?>

fetch_action( $_GET['ids'] ); $action_hook_html = '' . $action->get_hook() . ''; if ( 1 == $_GET['executed'] ) : ?>

query['orderby'] ) && 'post_password' == $query->query['orderby'] ) { $orderby = "$wpdb->posts.post_password " . $query->query['order']; } return $orderby; } /** * Filter search queries to allow searching by Claim ID (i.e. post_password). * * @param string $search MySQL search string. * @param WP_Query $query Instance of a WP_Query object * @return string MySQL search string. */ public function search_post_password( $search, $query ) { global $wpdb; if ( self::is_admin_page() && ! empty( $search ) ) { $search = ''; $searchand = ''; $n = ! empty( $query->query_vars['exact'] ) ? '' : '%'; foreach ( $query->query_vars['search_terms'] as $term ) { $term = $wpdb->esc_like( esc_sql( $term ) ); $search .= "{$searchand}(($wpdb->posts.post_title LIKE '{$n}{$term}{$n}') OR ($wpdb->posts.post_content LIKE '{$n}{$term}{$n}') OR ($wpdb->posts.post_password LIKE '{$n}{$term}{$n}'))"; $searchand = ' AND '; } if ( ! empty( $search ) ) { $search = " AND ({$search}) "; } } return $search; } /** * Change messages when a scheduled action is updated. * * @param array $messages * @return array */ public function post_updated_messages( $messages ) { global $post, $post_ID; $messages[ ActionScheduler_wpPostStore::POST_TYPE ] = array( 0 => '', // Unused. Messages start at index 1. 1 => __( 'Action updated.', 'action-scheduler' ), 2 => __( 'Custom field updated.', 'action-scheduler' ), 3 => __( 'Custom field deleted.', 'action-scheduler' ), 4 => __( 'Action updated.', 'action-scheduler' ), 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Action restored to revision from %s', 'action-scheduler' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false, 6 => __( 'Action scheduled.', 'action-scheduler' ), 7 => __( 'Action saved.', 'action-scheduler' ), 8 => __( 'Action submitted.', 'action-scheduler' ), 9 => sprintf( __( 'Action scheduled for: %1$s', 'action-scheduler' ), date_i18n( __( 'M j, Y @ G:i', 'action-scheduler' ), strtotime( $post->post_date ) ) ), 10 => __( 'Action draft updated.', 'action-scheduler' ), ); return $messages; } /** * Check if the current request is for the Schedul Actions administration screen. * * @return bool */ private static function is_admin_page() { if ( is_admin() && isset( $_GET['post_type'] ) && $_GET['post_type'] == ActionScheduler_wpPostStore::POST_TYPE ) { return true; } else { return false; } } }