Skip to content

Commit

Permalink
this fixes MinnPost#247 by updating action scheduler
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanstegall committed Mar 14, 2019
1 parent cd1f274 commit 59faee5
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 33 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"php": ">=5.5",
"pippinsplugins/wp-logging": "dev-master",
"developerforce/force.com-toolkit-for-php": "^1.0@dev",
"prospress/action-scheduler": "^2.2.0"
"prospress/action-scheduler": "^2.2.1"
},
"require-dev": {
"phpunit/phpunit": "^5.0 || ^4.8.10"
Expand Down
21 changes: 11 additions & 10 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions vendor/composer/installed.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,17 @@
},
{
"name": "prospress/action-scheduler",
"version": "2.2.0",
"version_normalized": "2.2.0.0",
"version": "v2.2.1",
"version_normalized": "2.2.1.0",
"source": {
"type": "git",
"url": "https://github.com/prospress/action-scheduler.git",
"reference": "641337c7e28ab4be6856483d4ec436ec0063e414"
"reference": "93a09f51569fe6f2e230dfb1387995617fad4d08"
},
"require-dev": {
"wp-cli/wp-cli": "^1.3"
},
"time": "2019-01-31T04:16:52+00:00",
"time": "2019-03-13T14:11:48+00:00",
"type": "wordpress-plugin",
"installation-source": "source",
"license": [
Expand Down
12 changes: 6 additions & 6 deletions vendor/prospress/action-scheduler/action-scheduler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Description: A robust scheduling library for use in WordPress plugins.
* Author: Prospress
* Author URI: http://prospress.com/
* Version: 2.2.0
* Version: 2.2.1
* License: GPLv3
*
* Copyright 2018 Prospress, Inc. (email : [email protected])
Expand All @@ -25,21 +25,21 @@
*
*/

if ( ! function_exists( 'action_scheduler_register_2_dot_2_dot_0' ) ) {
if ( ! function_exists( 'action_scheduler_register_2_dot_2_dot_1' ) ) {

if ( ! class_exists( 'ActionScheduler_Versions' ) ) {
require_once( 'classes/ActionScheduler_Versions.php' );
add_action( 'plugins_loaded', array( 'ActionScheduler_Versions', 'initialize_latest_version' ), 1, 0 );
}

add_action( 'plugins_loaded', 'action_scheduler_register_2_dot_2_dot_0', 0, 0 );
add_action( 'plugins_loaded', 'action_scheduler_register_2_dot_2_dot_1', 0, 0 );

function action_scheduler_register_2_dot_2_dot_0() {
function action_scheduler_register_2_dot_2_dot_1() {
$versions = ActionScheduler_Versions::instance();
$versions->register( '2.2.0', 'action_scheduler_initialize_2_dot_2_dot_0' );
$versions->register( '2.2.1', 'action_scheduler_initialize_2_dot_2_dot_1' );
}

function action_scheduler_initialize_2_dot_2_dot_0() {
function action_scheduler_initialize_2_dot_2_dot_1() {
require_once( 'classes/ActionScheduler.php' );
ActionScheduler::init( __FILE__ );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ public function process_action( $action_id ) {
$this->store->mark_failure( $action_id );
do_action( 'action_scheduler_failed_execution', $action_id, $e );
}
$this->schedule_next_instance( $action );

if ( isset( $action ) && is_a( $action, 'ActionScheduler_Action' ) ) {
$this->schedule_next_instance( $action );
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,18 @@ public function init() {

if ( class_exists( 'WooCommerce' ) ) {
add_action( 'woocommerce_admin_status_content_action-scheduler', array( $this, 'render_admin_ui' ) );
add_action( 'woocommerce_system_status_report', array( $this, 'system_status_report' ) );
add_filter( 'woocommerce_admin_status_tabs', array( $this, 'register_system_status_tab' ) );
}

add_action( 'admin_menu', array( $this, 'register_menu' ) );
}
}

public function system_status_report() {
$table = new ActionScheduler_wcSystemStatus( ActionScheduler::store() );
$table->print();
}

/**
* Registers action-scheduler into WooCommerce > System status.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php

/**
* Class ActionScheduler_wcSystemStatus
*/
class ActionScheduler_wcSystemStatus {

/**
* The active data stores
*
* @var ActionScheduler_Store
*/
protected $store;

function __construct( $store ) {
$this->store = $store;
}

/**
* Display action data, including number of actions grouped by status and the oldest & newest action in each status.
*
* Helpful to identify issues, like a clogged queue.
*/
public function print() {
$action_counts = $this->store->action_counts();
$status_labels = $this->store->get_status_labels();
$oldest_and_newest = $this->get_oldest_and_newest( array_keys( $status_labels ) );

$this->get_template( $status_labels, $action_counts, $oldest_and_newest );
}

/**
* Get oldest and newest scheduled dates for a given set of statuses.
*
* @param array $status_keys Set of statuses to find oldest & newest action for.
* @return array
*/
protected function get_oldest_and_newest( $status_keys ) {

$oldest_and_newest = array();

foreach ( $status_keys as $status ) {
$oldest_and_newest[ $status ] = array(
'oldest' => '&ndash;',
'newest' => '&ndash;',
);

if ( 'in-progress' === $status ) {
continue;
}

$oldest_and_newest[ $status ]['oldest'] = $this->get_action_status_date( $status, 'oldest' );
$oldest_and_newest[ $status ]['newest'] = $this->get_action_status_date( $status, 'newest' );
}

return $oldest_and_newest;
}

/**
* Get oldest or newest scheduled date for a given status.
*
* @param string $status Action status label/name string.
* @param string $date_type Oldest or Newest.
* @return DateTime
*/
protected function get_action_status_date( $status, $date_type = 'oldest' ) {

$order = 'oldest' === $date_type ? 'ASC' : 'DESC';

$action = $this->store->query_actions( array(
'claimed' => false,
'status' => $status,
'per_page' => 1,
'order' => $order,
) );

if ( ! empty( $action ) ) {
$date_object = $this->store->get_date( $action[0] );
$action_date = $date_object->format( 'Y-m-d H:i:s O' );
} else {
$action_date = '&ndash;';
}

return $action_date;
}

/**
* Get oldest or newest scheduled date for a given status.
*
* @param array $status_labels Set of statuses to find oldest & newest action for.
* @param array $action_counts Number of actions grouped by status.
* @param array $oldest_and_newest Date of the oldest and newest action with each status.
*/
protected function get_template( $status_labels, $action_counts, $oldest_and_newest ) {
?>

<table class="wc_status_table widefat" cellspacing="0">
<thead>
<tr>
<th colspan="5" data-export-label="Action Scheduler"><h2><?php esc_html_e( 'Action Scheduler', 'action-scheduler' ); ?><?php echo wc_help_tip( esc_html__( 'This section shows scheduled action counts.', 'action-scheduler' ) ); ?></h2></th>
</tr>
<tr>
<td><strong><?php esc_html_e( 'Action Status', 'action-scheduler' ); ?></strong></td>
<td class="help">&nbsp;</td>
<td><strong><?php esc_html_e( 'Count', 'action-scheduler' ); ?></strong></td>
<td><strong><?php esc_html_e( 'Oldest Scheduled Date', 'action-scheduler' ); ?></strong></td>
<td><strong><?php esc_html_e( 'Newest Scheduled Date', 'action-scheduler' ); ?></strong></td>
</tr>
</thead>
<tbody>
<?php
foreach ( $action_counts as $status => $count ) {
// WC uses the 3rd column for export, so we need to display more data in that (hidden when viewed as part of the table) and add an empty 2nd column.
printf(
'<tr><td>%1$s</td><td>&nbsp;</td><td>%2$s<span style="display: none;">, Oldest: %3$s, Newest: %4$s</span></td><td>%3$s</td><td>%4$s</td></tr>',
esc_html( $status_labels[ $status ] ),
number_format_i18n( $count ),
$oldest_and_newest[ $status ]['oldest'],
$oldest_and_newest[ $status ]['newest']
);
}
?>
</tbody>
</table>

<?php
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ protected function make_action_from_post( $post ) {
}

$schedule = get_post_meta( $post->ID, self::SCHEDULE_META_KEY, true );
if ( empty($schedule) ) {
if ( empty( $schedule ) || ! is_a( $schedule, 'ActionScheduler_Schedule' ) ) {
$schedule = new ActionScheduler_NullSchedule();
}
$group = wp_get_object_terms( $post->ID, self::GROUP_TAXONOMY, array('fields' => 'names') );
Expand Down Expand Up @@ -626,16 +626,9 @@ protected function get_actions_by_group( $group, $limit, DateTime $date ) {
'ID' => 'ASC',
),
'date_query' => array(
'column' => 'post_date',
array(
'compare' => '<=',
'year' => $date->format( 'Y' ),
'month' => $date->format( 'n' ),
'day' => $date->format( 'j' ),
'hour' => $date->format( 'G' ),
'minute' => $date->format( 'i' ),
'second' => $date->format( 's' ),
),
'column' => 'post_date_gmt',
'before' => $date->format( 'Y-m-d H:i' ),
'inclusive' => true,
),
'tax_query' => array(
array(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,57 @@ public function test_changing_batch_count_limit() {
public function return_6() {
return 6;
}

public function test_store_fetch_action_failure_schedule_next_instance() {
$random = md5( rand() );
$schedule = new ActionScheduler_IntervalSchedule( as_get_datetime_object( '12 hours ago' ), DAY_IN_SECONDS );
$action = new ActionScheduler_Action( $random, array(), $schedule );
$action_id = ActionScheduler::store()->save_action( $action );

// Set up a mock store that will throw an exception when fetching actions.
$store = $this
->getMockBuilder( 'ActionScheduler_wpPostStore' )
->setMethods( array( 'fetch_action' ) )
->getMock();
$store
->method( 'fetch_action' )
->with( $action_id )
->will( $this->throwException( new Exception() ) );

// Set up a mock queue runner to verify that schedule_next_instance()
// isn't called for an undefined $action.
$runner = $this
->getMockBuilder( 'ActionScheduler_QueueRunner' )
->setConstructorArgs( array( $store ) )
->setMethods( array( 'schedule_next_instance' ) )
->getMock();
$runner
->expects( $this->never() )
->method( 'schedule_next_instance' );

$runner->run();

// Set up a mock store that will throw an exception when fetching actions.
$store2 = $this
->getMockBuilder( 'ActionScheduler_wpPostStore' )
->setMethods( array( 'fetch_action' ) )
->getMock();
$store2
->method( 'fetch_action' )
->with( $action_id )
->willReturn( null );

// Set up a mock queue runner to verify that schedule_next_instance()
// isn't called for an undefined $action.
$runner2 = $this
->getMockBuilder( 'ActionScheduler_QueueRunner' )
->setConstructorArgs( array( $store ) )
->setMethods( array( 'schedule_next_instance' ) )
->getMock();
$runner2
->expects( $this->never() )
->method( 'schedule_next_instance' );

$runner2->run();
}
}

0 comments on commit 59faee5

Please sign in to comment.