plugin updates
This commit is contained in:
@@ -5,11 +5,11 @@
|
||||
* Description: A robust scheduling library for use in WordPress plugins.
|
||||
* Author: Automattic
|
||||
* Author URI: https://automattic.com/
|
||||
* Version: 3.8.1
|
||||
* Version: 3.8.2
|
||||
* License: GPLv3
|
||||
* Requires at least: 6.2
|
||||
* Tested up to: 6.5
|
||||
* Requires PHP: 5.6
|
||||
* Requires at least: 6.4
|
||||
* Tested up to: 6.6
|
||||
* Requires PHP: 7.0
|
||||
*
|
||||
* Copyright 2019 Automattic, Inc. (https://automattic.com/contact/)
|
||||
*
|
||||
@@ -29,29 +29,29 @@
|
||||
* @package ActionScheduler
|
||||
*/
|
||||
|
||||
if ( ! function_exists( 'action_scheduler_register_3_dot_8_dot_1' ) && function_exists( 'add_action' ) ) { // WRCS: DEFINED_VERSION.
|
||||
if ( ! function_exists( 'action_scheduler_register_3_dot_8_dot_2' ) && function_exists( 'add_action' ) ) { // WRCS: DEFINED_VERSION.
|
||||
|
||||
if ( ! class_exists( 'ActionScheduler_Versions', false ) ) {
|
||||
require_once __DIR__ . '/classes/ActionScheduler_Versions.php';
|
||||
add_action( 'plugins_loaded', array( 'ActionScheduler_Versions', 'initialize_latest_version' ), 1, 0 );
|
||||
}
|
||||
|
||||
add_action( 'plugins_loaded', 'action_scheduler_register_3_dot_8_dot_1', 0, 0 ); // WRCS: DEFINED_VERSION.
|
||||
add_action( 'plugins_loaded', 'action_scheduler_register_3_dot_8_dot_2', 0, 0 ); // WRCS: DEFINED_VERSION.
|
||||
|
||||
// phpcs:disable Generic.Functions.OpeningFunctionBraceKernighanRitchie.ContentAfterBrace
|
||||
/**
|
||||
* Registers this version of Action Scheduler.
|
||||
*/
|
||||
function action_scheduler_register_3_dot_8_dot_1() { // WRCS: DEFINED_VERSION.
|
||||
function action_scheduler_register_3_dot_8_dot_2() { // WRCS: DEFINED_VERSION.
|
||||
$versions = ActionScheduler_Versions::instance();
|
||||
$versions->register( '3.8.1', 'action_scheduler_initialize_3_dot_8_dot_1' ); // WRCS: DEFINED_VERSION.
|
||||
$versions->register( '3.8.2', 'action_scheduler_initialize_3_dot_8_dot_2' ); // WRCS: DEFINED_VERSION.
|
||||
}
|
||||
|
||||
// phpcs:disable Generic.Functions.OpeningFunctionBraceKernighanRitchie.ContentAfterBrace
|
||||
/**
|
||||
* Initializes this version of Action Scheduler.
|
||||
*/
|
||||
function action_scheduler_initialize_3_dot_8_dot_1() { // WRCS: DEFINED_VERSION.
|
||||
function action_scheduler_initialize_3_dot_8_dot_2() { // WRCS: DEFINED_VERSION.
|
||||
// A final safety check is required even here, because historic versions of Action Scheduler
|
||||
// followed a different pattern (in some unusual cases, we could reach this point and the
|
||||
// ActionScheduler class is already defined—so we need to guard against that).
|
||||
@@ -63,7 +63,7 @@ if ( ! function_exists( 'action_scheduler_register_3_dot_8_dot_1' ) && function_
|
||||
|
||||
// Support usage in themes - load this version if no plugin has loaded a version yet.
|
||||
if ( did_action( 'plugins_loaded' ) && ! doing_action( 'plugins_loaded' ) && ! class_exists( 'ActionScheduler', false ) ) {
|
||||
action_scheduler_initialize_3_dot_8_dot_1(); // WRCS: DEFINED_VERSION.
|
||||
action_scheduler_initialize_3_dot_8_dot_2(); // WRCS: DEFINED_VERSION.
|
||||
do_action( 'action_scheduler_pre_theme_init' );
|
||||
ActionScheduler_Versions::initialize_latest_version();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
*** Changelog ***
|
||||
|
||||
= 3.8.2 - 2024-09-12 =
|
||||
* Add missing parameter to the `pre_as_enqueue_async_action` hook.
|
||||
* Bump minimum PHP version to 7.0.
|
||||
* Bump minimum WordPress version to 6.4.
|
||||
* Make the batch size adjustable during processing.
|
||||
|
||||
= 3.8.1 - 2024-06-20 =
|
||||
* Fix typos.
|
||||
* Improve the messaging in our unidentified action exceptions.
|
||||
|
||||
@@ -4,20 +4,33 @@
|
||||
* Class ActionScheduler_ActionClaim
|
||||
*/
|
||||
class ActionScheduler_ActionClaim {
|
||||
/** @var string */
|
||||
private $id = '';
|
||||
/** @var int[] */
|
||||
private $action_ids = array();
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @param string $id Claim ID.
|
||||
* @param int[] $action_ids Action IDs.
|
||||
*/
|
||||
public function __construct( $id, array $action_ids ) {
|
||||
$this->id = $id;
|
||||
$this->action_ids = $action_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get claim ID.
|
||||
*/
|
||||
public function get_id() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get IDs of claimed actions.
|
||||
*/
|
||||
public function get_actions() {
|
||||
return $this->action_ids;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
*/
|
||||
class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
|
||||
|
||||
/** @var null|self */
|
||||
private static $admin_view = NULL;
|
||||
|
||||
/** @var string */
|
||||
private static $screen_id = 'tools_page_action-scheduler';
|
||||
|
||||
/** @var ActionScheduler_ListTable */
|
||||
@@ -28,6 +30,8 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function init() {
|
||||
@@ -45,6 +49,9 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print system status report.
|
||||
*/
|
||||
public function system_status_report() {
|
||||
$table = new ActionScheduler_wcSystemStatus( ActionScheduler::store() );
|
||||
$table->render();
|
||||
@@ -119,20 +126,20 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
|
||||
*/
|
||||
public function maybe_check_pastdue_actions() {
|
||||
|
||||
# Filter to prevent checking actions (ex: inappropriate user).
|
||||
// Filter to prevent checking actions (ex: inappropriate user).
|
||||
if ( ! apply_filters( 'action_scheduler_check_pastdue_actions', current_user_can( 'manage_options' ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
# Get last check transient.
|
||||
// Get last check transient.
|
||||
$last_check = get_transient( 'action_scheduler_last_pastdue_actions_check' );
|
||||
|
||||
# If transient exists, we're within interval, so bail.
|
||||
// If transient exists, we're within interval, so bail.
|
||||
if ( ! empty( $last_check ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
# Perform the check.
|
||||
// Perform the check.
|
||||
$this->check_pastdue_actions();
|
||||
}
|
||||
|
||||
@@ -143,9 +150,9 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
|
||||
*/
|
||||
protected function check_pastdue_actions() {
|
||||
|
||||
# Set thresholds.
|
||||
$threshold_seconds = ( int ) apply_filters( 'action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS );
|
||||
$threshold_min = ( int ) apply_filters( 'action_scheduler_pastdue_actions_min', 1 );
|
||||
// Set thresholds.
|
||||
$threshold_seconds = (int) apply_filters( 'action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS );
|
||||
$threshold_min = (int) apply_filters( 'action_scheduler_pastdue_actions_min', 1 );
|
||||
|
||||
// Set fallback value for past-due actions count.
|
||||
$num_pastdue_actions = 0;
|
||||
@@ -158,24 +165,24 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
|
||||
return;
|
||||
}
|
||||
|
||||
# Scheduled actions query arguments.
|
||||
// Scheduled actions query arguments.
|
||||
$query_args = array(
|
||||
'date' => as_get_datetime_object( time() - $threshold_seconds ),
|
||||
'status' => ActionScheduler_Store::STATUS_PENDING,
|
||||
'per_page' => $threshold_min,
|
||||
);
|
||||
|
||||
# If no third-party preempted, run default check.
|
||||
// If no third-party preempted, run default check.
|
||||
if ( is_null( $check ) ) {
|
||||
$store = ActionScheduler_Store::instance();
|
||||
$num_pastdue_actions = ( int ) $store->query_actions( $query_args, 'count' );
|
||||
$num_pastdue_actions = (int) $store->query_actions( $query_args, 'count' );
|
||||
|
||||
# Check if past-due actions count is greater than or equal to threshold.
|
||||
// Check if past-due actions count is greater than or equal to threshold.
|
||||
$check = ( $num_pastdue_actions >= $threshold_min );
|
||||
$check = ( bool ) apply_filters( 'action_scheduler_pastdue_actions_check', $check, $num_pastdue_actions, $threshold_seconds, $threshold_min );
|
||||
$check = (bool) apply_filters( 'action_scheduler_pastdue_actions_check', $check, $num_pastdue_actions, $threshold_seconds, $threshold_min );
|
||||
}
|
||||
|
||||
# If check failed, set transient and abort.
|
||||
// If check failed, set transient and abort.
|
||||
if ( ! boolval( $check ) ) {
|
||||
$interval = apply_filters( 'action_scheduler_pastdue_actions_check_interval', round( $threshold_seconds / 4 ), $threshold_seconds );
|
||||
set_transient( 'action_scheduler_last_pastdue_actions_check', time(), $interval );
|
||||
@@ -189,7 +196,7 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
|
||||
'order' => 'asc',
|
||||
), admin_url( 'tools.php' ) );
|
||||
|
||||
# Print notice.
|
||||
// Print notice.
|
||||
echo '<div class="notice notice-warning"><p>';
|
||||
printf(
|
||||
// translators: 1) is the number of affected actions, 2) is a link to an admin screen.
|
||||
@@ -204,7 +211,7 @@ class ActionScheduler_AdminView extends ActionScheduler_AdminView_Deprecated {
|
||||
);
|
||||
echo '</p></div>';
|
||||
|
||||
# Facilitate third-parties to evaluate and print notices.
|
||||
// Facilitate third-parties to evaluate and print notices.
|
||||
do_action( 'action_scheduler_pastdue_actions_extra_notices', $query_args );
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* ActionScheduler_AsyncRequest_QueueRunner
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
@@ -35,7 +32,9 @@ class ActionScheduler_AsyncRequest_QueueRunner extends WP_Async_Request {
|
||||
protected $action = 'async_request_queue_runner';
|
||||
|
||||
/**
|
||||
* Initiate new async request
|
||||
* Initiate new async request.
|
||||
*
|
||||
* @param ActionScheduler_Store $store Store object.
|
||||
*/
|
||||
public function __construct( ActionScheduler_Store $store ) {
|
||||
parent::__construct();
|
||||
@@ -49,7 +48,7 @@ class ActionScheduler_AsyncRequest_QueueRunner extends WP_Async_Request {
|
||||
* if there are still pending actions after completing a queue in this request.
|
||||
*/
|
||||
protected function handle() {
|
||||
do_action( 'action_scheduler_run_queue', 'Async Request' ); // run a queue in the same way as WP Cron, but declare the Async Request context
|
||||
do_action( 'action_scheduler_run_queue', 'Async Request' ); // run a queue in the same way as WP Cron, but declare the Async Request context.
|
||||
|
||||
$sleep_seconds = $this->get_sleep_seconds();
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ class ActionScheduler_DataController {
|
||||
$wp_object_cache->cache = array();
|
||||
|
||||
if ( is_callable( array( $wp_object_cache, '__remoteset' ) ) ) {
|
||||
call_user_func( array( $wp_object_cache, '__remoteset' ) ); // important
|
||||
call_user_func( array( $wp_object_cache, '__remoteset' ) ); // important!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class ActionScheduler_DateTime extends DateTime {
|
||||
*
|
||||
* This represents a fixed offset instead of a timezone setting.
|
||||
*
|
||||
* @param $offset
|
||||
* @param string|int $offset UTC offset value.
|
||||
*/
|
||||
public function setUtcOffset( $offset ) {
|
||||
$this->utcOffset = intval( $offset );
|
||||
@@ -54,7 +54,7 @@ class ActionScheduler_DateTime extends DateTime {
|
||||
/**
|
||||
* Set the TimeZone associated with the DateTime
|
||||
*
|
||||
* @param DateTimeZone $timezone
|
||||
* @param DateTimeZone $timezone Timezone object.
|
||||
*
|
||||
* @return static
|
||||
* @link http://php.net/manual/en/datetime.settimezone.php
|
||||
|
||||
@@ -8,12 +8,23 @@ class ActionScheduler_FatalErrorMonitor {
|
||||
private $claim = NULL;
|
||||
/** @var ActionScheduler_Store */
|
||||
private $store = NULL;
|
||||
/** @var int */
|
||||
private $action_id = 0;
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @param ActionScheduler_Store $store Action store.
|
||||
*/
|
||||
public function __construct( ActionScheduler_Store $store ) {
|
||||
$this->store = $store;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start monitoring.
|
||||
*
|
||||
* @param ActionScheduler_ActionClaim $claim Claimed actions.
|
||||
*/
|
||||
public function attach( ActionScheduler_ActionClaim $claim ) {
|
||||
$this->claim = $claim;
|
||||
add_action( 'shutdown', array( $this, 'handle_unexpected_shutdown' ) );
|
||||
@@ -23,6 +34,9 @@ class ActionScheduler_FatalErrorMonitor {
|
||||
add_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop monitoring.
|
||||
*/
|
||||
public function detach() {
|
||||
$this->claim = NULL;
|
||||
$this->untrack_action();
|
||||
@@ -33,16 +47,29 @@ class ActionScheduler_FatalErrorMonitor {
|
||||
remove_action( 'action_scheduler_failed_execution', array( $this, 'untrack_action' ), 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Track specified action.
|
||||
*
|
||||
* @param int $action_id Action ID to track.
|
||||
*/
|
||||
public function track_current_action( $action_id ) {
|
||||
$this->action_id = $action_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Un-track action.
|
||||
*/
|
||||
public function untrack_action() {
|
||||
$this->action_id = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle unexpected shutdown.
|
||||
*/
|
||||
public function handle_unexpected_shutdown() {
|
||||
if ( $error = error_get_last() ) {
|
||||
$error = error_get_last();
|
||||
|
||||
if ( $error ) {
|
||||
if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ) ) ) {
|
||||
if ( !empty($this->action_id) ) {
|
||||
$this->store->mark_failure( $this->action_id );
|
||||
|
||||
@@ -13,6 +13,7 @@ class ActionScheduler_InvalidActionException extends \InvalidArgumentException i
|
||||
* Create a new exception when the action's schedule cannot be fetched.
|
||||
*
|
||||
* @param string $action_id The action ID with bad args.
|
||||
* @param mixed $schedule Passed schedule.
|
||||
* @return static
|
||||
*/
|
||||
public static function from_schedule( $action_id, $schedule ) {
|
||||
@@ -32,6 +33,7 @@ class ActionScheduler_InvalidActionException extends \InvalidArgumentException i
|
||||
* @author Jeremy Pry
|
||||
*
|
||||
* @param string $action_id The action ID with bad args.
|
||||
* @param mixed $args Passed arguments.
|
||||
* @return static
|
||||
*/
|
||||
public static function from_decoding_args( $action_id, $args = array() ) {
|
||||
|
||||
@@ -76,9 +76,9 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
/**
|
||||
* Sets the current data store object into `store->action` and initialises the object.
|
||||
*
|
||||
* @param ActionScheduler_Store $store
|
||||
* @param ActionScheduler_Logger $logger
|
||||
* @param ActionScheduler_QueueRunner $runner
|
||||
* @param ActionScheduler_Store $store Store object.
|
||||
* @param ActionScheduler_Logger $logger Logger object.
|
||||
* @param ActionScheduler_QueueRunner $runner Runner object.
|
||||
*/
|
||||
public function __construct( ActionScheduler_Store $store, ActionScheduler_Logger $logger, ActionScheduler_QueueRunner $runner ) {
|
||||
|
||||
@@ -225,8 +225,9 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
}
|
||||
|
||||
$output = '';
|
||||
$num_time_periods = count( self::$time_periods );
|
||||
|
||||
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++ ) {
|
||||
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++ ) {
|
||||
|
||||
$periods_in_interval = floor( $seconds_remaining / self::$time_periods[ $time_period_index ]['seconds'] );
|
||||
|
||||
@@ -246,7 +247,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
/**
|
||||
* Returns the recurrence of an action or 'Non-repeating'. The output is human readable.
|
||||
*
|
||||
* @param ActionScheduler_Action $action
|
||||
* @param ActionScheduler_Action $action Action object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -269,7 +270,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
/**
|
||||
* Serializes the argument of an action to render it in a human friendly format.
|
||||
*
|
||||
* @param array $row The array representation of the current row of the table
|
||||
* @param array $row The array representation of the current row of the table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -311,8 +312,8 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
/**
|
||||
* Prints the logs entries inline. We do so to avoid loading Javascript and other hacks to show it in a modal.
|
||||
*
|
||||
* @param ActionScheduler_LogEntry $log_entry
|
||||
* @param DateTimezone $timezone
|
||||
* @param ActionScheduler_LogEntry $log_entry Log entry object.
|
||||
* @param DateTimezone $timezone Timestamp.
|
||||
* @return string
|
||||
*/
|
||||
protected function get_log_entry_html( ActionScheduler_LogEntry $log_entry, DateTimezone $timezone ) {
|
||||
@@ -324,8 +325,8 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
/**
|
||||
* Only display row actions for pending actions.
|
||||
*
|
||||
* @param array $row Row to render
|
||||
* @param string $column_name Current row
|
||||
* @param array $row Row to render.
|
||||
* @param string $column_name Current row.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -390,7 +391,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
|
||||
$async_request_lock_expiration = ActionScheduler::lock()->get_expiration( 'async-request-runner' );
|
||||
|
||||
// No lock set or lock expired
|
||||
// No lock set or lock expired.
|
||||
if ( false === $async_request_lock_expiration || $async_request_lock_expiration < time() ) {
|
||||
$in_progress_url = add_query_arg( 'status', 'in-progress', remove_query_arg( 'status' ) );
|
||||
/* translators: %s: process URL */
|
||||
@@ -449,7 +450,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
/**
|
||||
* Prints the scheduled date in a human friendly format.
|
||||
*
|
||||
* @param array $row The array representation of the current row of the table
|
||||
* @param array $row The array representation of the current row of the table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -460,7 +461,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
/**
|
||||
* Get the scheduled date in a human friendly format.
|
||||
*
|
||||
* @param ActionScheduler_Schedule $schedule
|
||||
* @param ActionScheduler_Schedule $schedule Action's schedule.
|
||||
* @return string
|
||||
*/
|
||||
protected function get_schedule_display_string( ActionScheduler_Schedule $schedule ) {
|
||||
@@ -492,13 +493,13 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk delete
|
||||
* Bulk delete.
|
||||
*
|
||||
* Deletes actions based on their ID. This is the handler for the bulk delete. It assumes the data
|
||||
* properly validated by the callee and it will delete the actions without any extra validation.
|
||||
*
|
||||
* @param array $ids
|
||||
* @param string $ids_sql Inherited and unused
|
||||
* @param int[] $ids Action IDs.
|
||||
* @param string $ids_sql Inherited and unused.
|
||||
*/
|
||||
protected function bulk_delete( array $ids, $ids_sql ) {
|
||||
foreach ( $ids as $id ) {
|
||||
@@ -523,7 +524,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
* Implements the logic behind running an action. ActionScheduler_Abstract_ListTable validates the request and their
|
||||
* parameters are valid.
|
||||
*
|
||||
* @param int $action_id
|
||||
* @param int $action_id Action ID.
|
||||
*/
|
||||
protected function row_action_cancel( $action_id ) {
|
||||
$this->process_row_action( $action_id, 'cancel' );
|
||||
@@ -533,7 +534,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
* Implements the logic behind running an action. ActionScheduler_Abstract_ListTable validates the request and their
|
||||
* parameters are valid.
|
||||
*
|
||||
* @param int $action_id
|
||||
* @param int $action_id Action ID.
|
||||
*/
|
||||
protected function row_action_run( $action_id ) {
|
||||
$this->process_row_action( $action_id, 'run' );
|
||||
@@ -560,7 +561,7 @@ class ActionScheduler_ListTable extends ActionScheduler_Abstract_ListTable {
|
||||
/**
|
||||
* Implements the logic behind processing an action once an action link is clicked on the list table.
|
||||
*
|
||||
* @param int $action_id
|
||||
* @param int $action_id Action ID.
|
||||
* @param string $row_action_type The type of action to perform on the action.
|
||||
*/
|
||||
protected function process_row_action( $action_id, $row_action_type ) {
|
||||
|
||||
@@ -23,13 +23,12 @@ class ActionScheduler_LogEntry {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param mixed $action_id Action ID
|
||||
* @param string $message Message
|
||||
* @param Datetime $date Datetime object with the time when this log entry was created. If this parameter is
|
||||
* not provided a new Datetime object (with current time) will be created.
|
||||
* @param mixed $action_id Action ID.
|
||||
* @param string $message Message.
|
||||
* @param Datetime $date Datetime object with the time when this log entry was created. If this parameter is
|
||||
* not provided a new Datetime object (with current time) will be created.
|
||||
*/
|
||||
public function __construct( $action_id, $message, $date = null ) {
|
||||
|
||||
/*
|
||||
* ActionScheduler_wpCommentLogger::get_entry() previously passed a 3rd param of $comment->comment_type
|
||||
* to ActionScheduler_LogEntry::__construct(), goodness knows why, and the Follow-up Emails plugin
|
||||
@@ -56,10 +55,16 @@ class ActionScheduler_LogEntry {
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get action ID of log entry.
|
||||
*/
|
||||
public function get_action_id() {
|
||||
return $this->action_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get log entry message.
|
||||
*/
|
||||
public function get_message() {
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,15 @@
|
||||
* Class ActionScheduler_NullLogEntry
|
||||
*/
|
||||
class ActionScheduler_NullLogEntry extends ActionScheduler_LogEntry {
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
* @param string $message Log entry.
|
||||
*/
|
||||
public function __construct( $action_id = '', $message = '' ) {
|
||||
// nothing to see here
|
||||
// nothing to see here.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -66,7 +66,6 @@ class ActionScheduler_QueueCleaner {
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filter the statuses when cleaning the queue.
|
||||
*
|
||||
@@ -83,7 +82,7 @@ class ActionScheduler_QueueCleaner {
|
||||
* @param string[] $statuses_to_purge List of action statuses to purge. Defaults to canceled, complete.
|
||||
* @param DateTime $cutoff_date Date limit for selecting actions. Defaults to 31 days ago.
|
||||
* @param int|null $batch_size Maximum number of actions per status to delete. Defaults to 20.
|
||||
* @param string $context Calling process context. Defaults to `old`.
|
||||
* @param string $context Calling process context. Defaults to `old`.
|
||||
* @return array Actions deleted.
|
||||
*/
|
||||
public function clean_actions( array $statuses_to_purge, DateTime $cutoff_date, $batch_size = null, $context = 'old' ) {
|
||||
@@ -111,8 +110,10 @@ class ActionScheduler_QueueCleaner {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $actions_to_delete List of action IDs to delete.
|
||||
* @param int $lifespan Minimum scheduled age in seconds of the actions being deleted.
|
||||
* Delete actions.
|
||||
*
|
||||
* @param int[] $actions_to_delete List of action IDs to delete.
|
||||
* @param int $lifespan Minimum scheduled age in seconds of the actions being deleted.
|
||||
* @param string $context Context of the delete request.
|
||||
* @return array Deleted action IDs.
|
||||
*/
|
||||
@@ -159,7 +160,7 @@ class ActionScheduler_QueueCleaner {
|
||||
if ( $timeout < 0 ) {
|
||||
return;
|
||||
}
|
||||
$cutoff = as_get_datetime_object($timeout.' seconds ago');
|
||||
$cutoff = as_get_datetime_object($timeout . ' seconds ago');
|
||||
$actions_to_reset = $this->store->query_actions( array(
|
||||
'status' => ActionScheduler_Store::STATUS_PENDING,
|
||||
'modified' => $cutoff,
|
||||
@@ -189,7 +190,7 @@ class ActionScheduler_QueueCleaner {
|
||||
if ( $timeout < 0 ) {
|
||||
return;
|
||||
}
|
||||
$cutoff = as_get_datetime_object($timeout.' seconds ago');
|
||||
$cutoff = as_get_datetime_object($timeout . ' seconds ago');
|
||||
$actions_to_reset = $this->store->query_actions( array(
|
||||
'status' => ActionScheduler_Store::STATUS_RUNNING,
|
||||
'modified' => $cutoff,
|
||||
|
||||
@@ -32,9 +32,10 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
|
||||
/**
|
||||
* ActionScheduler_QueueRunner constructor.
|
||||
*
|
||||
* @param ActionScheduler_Store $store
|
||||
* @param ActionScheduler_FatalErrorMonitor $monitor
|
||||
* @param ActionScheduler_QueueCleaner $cleaner
|
||||
* @param ActionScheduler_Store $store Store object.
|
||||
* @param ActionScheduler_FatalErrorMonitor $monitor Monitor object.
|
||||
* @param ActionScheduler_QueueCleaner $cleaner Cleaner object.
|
||||
* @param ActionScheduler_AsyncRequest_QueueRunner $async_request Async request runner object.
|
||||
*/
|
||||
public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null, ActionScheduler_AsyncRequest_QueueRunner $async_request = null ) {
|
||||
parent::__construct( $store, $monitor, $cleaner );
|
||||
@@ -53,7 +54,7 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
|
||||
|
||||
add_filter( 'cron_schedules', array( self::instance(), 'add_wp_cron_schedule' ) );
|
||||
|
||||
// Check for and remove any WP Cron hook scheduled by Action Scheduler < 3.0.0, which didn't include the $context param
|
||||
// Check for and remove any WP Cron hook scheduled by Action Scheduler < 3.0.0, which didn't include the $context param.
|
||||
$next_timestamp = wp_next_scheduled( self::WP_CRON_HOOK );
|
||||
if ( $next_timestamp ) {
|
||||
wp_unschedule_event( $next_timestamp, self::WP_CRON_HOOK );
|
||||
@@ -134,11 +135,11 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
|
||||
|
||||
$this->processed_actions_count = 0;
|
||||
if ( false === $this->has_maximum_concurrent_batches() ) {
|
||||
$batch_size = apply_filters( 'action_scheduler_queue_runner_batch_size', 25 );
|
||||
do {
|
||||
$batch_size = apply_filters( 'action_scheduler_queue_runner_batch_size', 25 );
|
||||
$processed_actions_in_batch = $this->do_batch( $batch_size, $context );
|
||||
$this->processed_actions_count += $processed_actions_in_batch;
|
||||
} while ( $processed_actions_in_batch > 0 && ! $this->batch_limits_exceeded( $this->processed_actions_count ) ); // keep going until we run out of actions, time, or memory
|
||||
} while ( $processed_actions_in_batch > 0 && ! $this->batch_limits_exceeded( $this->processed_actions_count ) ); // keep going until we run out of actions, time, or memory.
|
||||
}
|
||||
|
||||
do_action( 'action_scheduler_after_process_queue' );
|
||||
@@ -151,9 +152,9 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
|
||||
* Actions are processed by claiming a set of pending actions then processing each one until either the batch
|
||||
* size is completed, or memory or time limits are reached, defined by @see $this->batch_limits_exceeded().
|
||||
*
|
||||
* @param int $size The maximum number of actions to process in the batch.
|
||||
* @param int $size The maximum number of actions to process in the batch.
|
||||
* @param string $context Optional identifier for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
|
||||
* Generally, this should be capitalised and not localised as it's a proper noun.
|
||||
* Generally, this should be capitalised and not localised as it's a proper noun.
|
||||
* @return int The number of actions processed.
|
||||
*/
|
||||
protected function do_batch( $size = 100, $context = '' ) {
|
||||
@@ -162,7 +163,7 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
|
||||
$processed_actions = 0;
|
||||
|
||||
foreach ( $claim->get_actions() as $action_id ) {
|
||||
// bail if we lost the claim
|
||||
// bail if we lost the claim.
|
||||
if ( ! in_array( $action_id, $this->store->find_actions_by_claim_id( $claim->get_id() ) ) ) {
|
||||
break;
|
||||
}
|
||||
@@ -218,9 +219,15 @@ class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add schedule to WP cron.
|
||||
*
|
||||
* @param array<string, array<string, int|string>> $schedules Schedules.
|
||||
* @return array<string, array<string, int|string>>
|
||||
*/
|
||||
public function add_wp_cron_schedule( $schedules ) {
|
||||
$schedules['every_minute'] = array(
|
||||
'interval' => 60, // in seconds
|
||||
'interval' => 60, // in seconds.
|
||||
'display' => __( 'Every minute', 'woocommerce' ),
|
||||
);
|
||||
|
||||
|
||||
@@ -9,8 +9,15 @@ class ActionScheduler_Versions {
|
||||
*/
|
||||
private static $instance = NULL;
|
||||
|
||||
/** @var array<string, callable> */
|
||||
private $versions = array();
|
||||
|
||||
/**
|
||||
* Register version's callback.
|
||||
*
|
||||
* @param string $version_string Action Scheduler version.
|
||||
* @param callable $initialization_callback Callback to initialize the version.
|
||||
*/
|
||||
public function register( $version_string, $initialization_callback ) {
|
||||
if ( isset($this->versions[$version_string]) ) {
|
||||
return FALSE;
|
||||
@@ -19,10 +26,16 @@ class ActionScheduler_Versions {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all versions.
|
||||
*/
|
||||
public function get_versions() {
|
||||
return $this->versions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest version registered.
|
||||
*/
|
||||
public function latest_version() {
|
||||
$keys = array_keys($this->versions);
|
||||
if ( empty($keys) ) {
|
||||
@@ -32,6 +45,9 @@ class ActionScheduler_Versions {
|
||||
return end($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get callback for latest registered version.
|
||||
*/
|
||||
public function latest_version_callback() {
|
||||
$latest = $this->latest_version();
|
||||
if ( empty($latest) || !isset($this->versions[$latest]) ) {
|
||||
@@ -59,4 +75,3 @@ class ActionScheduler_Versions {
|
||||
call_user_func($self->latest_version_callback());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,10 @@ class ActionScheduler_WPCommentCleaner {
|
||||
|
||||
// While there are orphaned logs left in the comments table, we need to attach the callbacks which filter comment counts.
|
||||
add_action( 'pre_get_comments', array( self::$wp_comment_logger, 'filter_comment_queries' ), 10, 1 );
|
||||
add_action( 'wp_count_comments', array( self::$wp_comment_logger, 'filter_comment_count' ), 20, 2 ); // run after WC_Comments::wp_count_comments() to make sure we exclude order notes and action logs
|
||||
add_action( 'wp_count_comments', array( self::$wp_comment_logger, 'filter_comment_count' ), 20, 2 ); // run after WC_Comments::wp_count_comments() to make sure we exclude order notes and action logs.
|
||||
add_action( 'comment_feed_where', array( self::$wp_comment_logger, 'filter_comment_feed' ), 10, 2 );
|
||||
|
||||
// Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen
|
||||
// Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen.
|
||||
add_action( 'load-tools_page_action-scheduler', array( __CLASS__, 'register_admin_notice' ) );
|
||||
add_action( 'load-woocommerce_page_wc-status', array( __CLASS__, 'register_admin_notice' ) );
|
||||
}
|
||||
@@ -90,7 +90,7 @@ class ActionScheduler_WPCommentCleaner {
|
||||
public static function register_admin_notice() {
|
||||
add_action( 'admin_notices', array( __CLASS__, 'print_admin_notice' ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints details about the orphaned action logs and includes information on where to learn more.
|
||||
*/
|
||||
|
||||
@@ -79,7 +79,7 @@ class ActionScheduler_WPCLI_Clean_Command extends WP_CLI_Command {
|
||||
/**
|
||||
* Print WP CLI message about how many batches of actions were processed.
|
||||
*
|
||||
* @param int $batches_processed
|
||||
* @param int $batches_processed Number of batches processed.
|
||||
*/
|
||||
protected function print_total_batches( int $batches_processed ) {
|
||||
WP_CLI::log(
|
||||
@@ -111,7 +111,7 @@ class ActionScheduler_WPCLI_Clean_Command extends WP_CLI_Command {
|
||||
/**
|
||||
* Print a success message with the number of completed actions.
|
||||
*
|
||||
* @param int $actions_deleted
|
||||
* @param int $actions_deleted Number of deleted actions.
|
||||
*/
|
||||
protected function print_success( int $actions_deleted ) {
|
||||
WP_CLI::success(
|
||||
|
||||
@@ -21,11 +21,11 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
|
||||
/**
|
||||
* ActionScheduler_WPCLI_QueueRunner constructor.
|
||||
*
|
||||
* @param ActionScheduler_Store $store
|
||||
* @param ActionScheduler_FatalErrorMonitor $monitor
|
||||
* @param ActionScheduler_QueueCleaner $cleaner
|
||||
* @param ActionScheduler_Store $store Store object.
|
||||
* @param ActionScheduler_FatalErrorMonitor $monitor Monitor object.
|
||||
* @param ActionScheduler_QueueCleaner $cleaner Cleaner object.
|
||||
*
|
||||
* @throws Exception When this is not run within WP CLI
|
||||
* @throws Exception When this is not run within WP CLI.
|
||||
*/
|
||||
public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null ) {
|
||||
if ( ! ( defined( 'WP_CLI' ) && WP_CLI ) ) {
|
||||
@@ -131,7 +131,7 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
|
||||
*
|
||||
* @author Jeremy Pry
|
||||
*
|
||||
* @param $action_id
|
||||
* @param int $action_id Action ID.
|
||||
*/
|
||||
public function before_execute( $action_id ) {
|
||||
/* translators: %s refers to the action ID */
|
||||
@@ -143,11 +143,11 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
|
||||
*
|
||||
* @author Jeremy Pry
|
||||
*
|
||||
* @param int $action_id
|
||||
* @param int $action_id ActionID.
|
||||
* @param null|ActionScheduler_Action $action The instance of the action. Default to null for backward compatibility.
|
||||
*/
|
||||
public function after_execute( $action_id, $action = null ) {
|
||||
// backward compatibility
|
||||
// backward compatibility.
|
||||
if ( null === $action ) {
|
||||
$action = $this->store->fetch_action( $action_id );
|
||||
}
|
||||
@@ -160,8 +160,8 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
|
||||
*
|
||||
* @author Jeremy Pry
|
||||
*
|
||||
* @param int $action_id
|
||||
* @param Exception $exception
|
||||
* @param int $action_id Action ID.
|
||||
* @param Exception $exception Exception.
|
||||
* @throws \WP_CLI\ExitException With failure message.
|
||||
*/
|
||||
public function action_failed( $action_id, $exception ) {
|
||||
@@ -175,7 +175,7 @@ class ActionScheduler_WPCLI_QueueRunner extends ActionScheduler_Abstract_QueueRu
|
||||
/**
|
||||
* Sleep and help avoid hitting memory limit
|
||||
*
|
||||
* @param int $sleep_time Amount of seconds to sleep
|
||||
* @param int $sleep_time Amount of seconds to sleep.
|
||||
* @deprecated 3.0.0
|
||||
*/
|
||||
protected function stop_the_insanity( $sleep_time = 0 ) {
|
||||
|
||||
@@ -104,7 +104,7 @@ class ActionScheduler_WPCLI_Scheduler_command extends WP_CLI_Command {
|
||||
// Custom queue cleaner instance.
|
||||
$cleaner = new ActionScheduler_QueueCleaner( null, $clean );
|
||||
|
||||
// Get the queue runner instance
|
||||
// Get the queue runner instance.
|
||||
$runner = new ActionScheduler_WPCLI_QueueRunner( null, null, $cleaner );
|
||||
|
||||
// Determine how many tasks will be run in the first batch.
|
||||
@@ -143,7 +143,7 @@ class ActionScheduler_WPCLI_Scheduler_command extends WP_CLI_Command {
|
||||
*
|
||||
* @author Jeremy Pry
|
||||
*
|
||||
* @param int $total
|
||||
* @param int $total Number of actions found.
|
||||
*/
|
||||
protected function print_total_actions( $total ) {
|
||||
WP_CLI::log(
|
||||
@@ -160,7 +160,7 @@ class ActionScheduler_WPCLI_Scheduler_command extends WP_CLI_Command {
|
||||
*
|
||||
* @author Jeremy Pry
|
||||
*
|
||||
* @param int $batches_completed
|
||||
* @param int $batches_completed Number of completed batches.
|
||||
*/
|
||||
protected function print_total_batches( $batches_completed ) {
|
||||
WP_CLI::log(
|
||||
@@ -196,7 +196,7 @@ class ActionScheduler_WPCLI_Scheduler_command extends WP_CLI_Command {
|
||||
*
|
||||
* @author Jeremy Pry
|
||||
*
|
||||
* @param int $actions_completed
|
||||
* @param int $actions_completed Number of completed actions.
|
||||
*/
|
||||
protected function print_success( $actions_completed ) {
|
||||
WP_CLI::success(
|
||||
|
||||
@@ -93,7 +93,7 @@ class Migration_Command extends WP_CLI_Command {
|
||||
} while ( $actions_processed > 0 );
|
||||
|
||||
if ( ! $config->get_dry_run() ) {
|
||||
// let the scheduler know that there's nothing left to do
|
||||
// let the scheduler know that there's nothing left to do.
|
||||
$scheduler = new Scheduler();
|
||||
$scheduler->mark_complete();
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class ProgressBar {
|
||||
* @param integer $count Total number of ticks to be performed.
|
||||
* @param integer $interval Optional. The interval in milliseconds between updates. Default 100.
|
||||
*
|
||||
* @throws Exception When this is not run within WP CLI
|
||||
* @throws \Exception When this is not run within WP CLI.
|
||||
*/
|
||||
public function __construct( $message, $count, $interval = 100 ) {
|
||||
if ( ! ( defined( 'WP_CLI' ) && WP_CLI ) ) {
|
||||
|
||||
@@ -8,12 +8,16 @@ use Action_Scheduler\Migration\Controller;
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
abstract class ActionScheduler {
|
||||
/** @var string */
|
||||
private static $plugin_file = '';
|
||||
/** @var ActionScheduler_ActionFactory */
|
||||
private static $factory = NULL;
|
||||
/** @var bool */
|
||||
private static $data_store_initialized = false;
|
||||
|
||||
/**
|
||||
* Factory.
|
||||
*/
|
||||
public static function factory() {
|
||||
if ( !isset(self::$factory) ) {
|
||||
self::$factory = new ActionScheduler_ActionFactory();
|
||||
@@ -21,22 +25,37 @@ abstract class ActionScheduler {
|
||||
return self::$factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Store instance.
|
||||
*/
|
||||
public static function store() {
|
||||
return ActionScheduler_Store::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Lock instance.
|
||||
*/
|
||||
public static function lock() {
|
||||
return ActionScheduler_Lock::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Logger instance.
|
||||
*/
|
||||
public static function logger() {
|
||||
return ActionScheduler_Logger::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get QueueRunner instance.
|
||||
*/
|
||||
public static function runner() {
|
||||
return ActionScheduler_QueueRunner::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get AdminView instance.
|
||||
*/
|
||||
public static function admin_view() {
|
||||
return ActionScheduler_AdminView::instance();
|
||||
}
|
||||
@@ -44,13 +63,13 @@ abstract class ActionScheduler {
|
||||
/**
|
||||
* Get the absolute system path to the plugin directory, or a file therein
|
||||
* @static
|
||||
* @param string $path
|
||||
* @param string $path Path relative to plugin directory.
|
||||
* @return string
|
||||
*/
|
||||
public static function plugin_path( $path ) {
|
||||
$base = dirname(self::$plugin_file);
|
||||
if ( $path ) {
|
||||
return trailingslashit($base).$path;
|
||||
return trailingslashit($base) . $path;
|
||||
} else {
|
||||
return untrailingslashit($base);
|
||||
}
|
||||
@@ -59,13 +78,18 @@ abstract class ActionScheduler {
|
||||
/**
|
||||
* Get the absolute URL to the plugin directory, or a file therein
|
||||
* @static
|
||||
* @param string $path
|
||||
* @param string $path Path relative to plugin directory.
|
||||
* @return string
|
||||
*/
|
||||
public static function plugin_url( $path ) {
|
||||
return plugins_url($path, self::$plugin_file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Autoload.
|
||||
*
|
||||
* @param string $class Class name.
|
||||
*/
|
||||
public static function autoload( $class ) {
|
||||
$d = DIRECTORY_SEPARATOR;
|
||||
$classes_dir = self::plugin_path( 'classes' . $d );
|
||||
@@ -128,7 +152,7 @@ abstract class ActionScheduler {
|
||||
* Initialize the plugin
|
||||
*
|
||||
* @static
|
||||
* @param string $plugin_file
|
||||
* @param string $plugin_file Plugin file path.
|
||||
*/
|
||||
public static function init( $plugin_file ) {
|
||||
self::$plugin_file = $plugin_file;
|
||||
@@ -149,7 +173,8 @@ abstract class ActionScheduler {
|
||||
|
||||
// Ensure initialization on plugin activation.
|
||||
if ( ! did_action( 'init' ) ) {
|
||||
add_action( 'init', array( $admin_view, 'init' ), 0, 0 ); // run before $store::init()
|
||||
// phpcs:ignore Squiz.PHP.CommentedOutCode
|
||||
add_action( 'init', array( $admin_view, 'init' ), 0, 0 ); // run before $store::init().
|
||||
add_action( 'init', array( $store, 'init' ), 1, 0 );
|
||||
add_action( 'init', array( $logger, 'init' ), 1, 0 );
|
||||
add_action( 'init', array( $runner, 'init' ), 1, 0 );
|
||||
@@ -308,18 +333,33 @@ abstract class ActionScheduler {
|
||||
return isset( $cli_segments[ $segment ] ) && $cli_segments[ $segment ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone.
|
||||
*/
|
||||
final public function __clone() {
|
||||
trigger_error("Singleton. No cloning allowed!", E_USER_ERROR);
|
||||
trigger_error('Singleton. No cloning allowed!', E_USER_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wakeup.
|
||||
*/
|
||||
final public function __wakeup() {
|
||||
trigger_error("Singleton. No serialization allowed!", E_USER_ERROR);
|
||||
trigger_error('Singleton. No serialization allowed!', E_USER_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*/
|
||||
final private function __construct() {}
|
||||
|
||||
/** Deprecated **/
|
||||
|
||||
/**
|
||||
* Get DateTime object.
|
||||
*
|
||||
* @param null|string $when Date/time string.
|
||||
* @param string $timezone Timezone string.
|
||||
*/
|
||||
public static function get_datetime_object( $when = null, $timezone = 'UTC' ) {
|
||||
_deprecated_function( __METHOD__, '2.0', 'wcs_add_months()' );
|
||||
return as_get_datetime_object( $when, $timezone );
|
||||
|
||||
@@ -27,9 +27,9 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
|
||||
/**
|
||||
* ActionScheduler_Abstract_QueueRunner constructor.
|
||||
*
|
||||
* @param ActionScheduler_Store $store
|
||||
* @param ActionScheduler_FatalErrorMonitor $monitor
|
||||
* @param ActionScheduler_QueueCleaner $cleaner
|
||||
* @param ActionScheduler_Store $store Store object.
|
||||
* @param ActionScheduler_FatalErrorMonitor $monitor Monitor object.
|
||||
* @param ActionScheduler_QueueCleaner $cleaner Cleaner object.
|
||||
*/
|
||||
public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null ) {
|
||||
|
||||
@@ -43,9 +43,10 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
|
||||
/**
|
||||
* Process an individual action.
|
||||
*
|
||||
* @param int $action_id The action ID to process.
|
||||
* @param int $action_id The action ID to process.
|
||||
* @param string $context Optional identifier for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron'
|
||||
* Generally, this should be capitalised and not localised as it's a proper noun.
|
||||
* Generally, this should be capitalised and not localised as it's a proper noun.
|
||||
* @throws \Exception When error running action.
|
||||
*/
|
||||
public function process_action( $action_id, $context = '' ) {
|
||||
// Temporarily override the error handler while we process the current action.
|
||||
@@ -141,8 +142,8 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
|
||||
/**
|
||||
* Schedule the next instance of the action if necessary.
|
||||
*
|
||||
* @param ActionScheduler_Action $action
|
||||
* @param int $action_id
|
||||
* @param ActionScheduler_Action $action Action.
|
||||
* @param int $action_id Action ID.
|
||||
*/
|
||||
protected function schedule_next_instance( ActionScheduler_Action $action, $action_id ) {
|
||||
// If a recurring action has been consistently failing, we may wish to stop rescheduling it.
|
||||
@@ -256,7 +257,7 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
|
||||
|
||||
$time_limit = 30;
|
||||
|
||||
// Apply deprecated filter from deprecated get_maximum_execution_time() method
|
||||
// Apply deprecated filter from deprecated get_maximum_execution_time() method.
|
||||
if ( has_filter( 'action_scheduler_maximum_execution_time' ) ) {
|
||||
_deprecated_function( 'action_scheduler_maximum_execution_time', '2.1.1', 'action_scheduler_queue_runner_time_limit' );
|
||||
$time_limit = apply_filters( 'action_scheduler_maximum_execution_time', $time_limit );
|
||||
@@ -288,7 +289,7 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
|
||||
/**
|
||||
* Check if the host's max execution time is (likely) to be exceeded if processing more actions.
|
||||
*
|
||||
* @param int $processed_actions The number of actions processed so far - used to determine the likelihood of exceeding the time limit if processing another action
|
||||
* @param int $processed_actions The number of actions processed so far - used to determine the likelihood of exceeding the time limit if processing another action.
|
||||
* @return bool
|
||||
*/
|
||||
protected function time_likely_to_be_exceeded( $processed_actions ) {
|
||||
@@ -318,7 +319,7 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
|
||||
if ( function_exists( 'ini_get' ) ) {
|
||||
$memory_limit = ini_get( 'memory_limit' );
|
||||
} else {
|
||||
$memory_limit = '128M'; // Sensible default, and minimum required by WooCommerce
|
||||
$memory_limit = '128M'; // Sensible default, and minimum required by WooCommerce.
|
||||
}
|
||||
|
||||
if ( ! $memory_limit || -1 === $memory_limit || '-1' === $memory_limit ) {
|
||||
@@ -353,7 +354,7 @@ abstract class ActionScheduler_Abstract_QueueRunner extends ActionScheduler_Abst
|
||||
*
|
||||
* Based on WC_Background_Process::batch_limits_exceeded()
|
||||
*
|
||||
* @param int $processed_actions The number of actions processed so far - used to determine the likelihood of exceeding the time limit if processing another action
|
||||
* @param int $processed_actions The number of actions processed so far - used to determine the likelihood of exceeding the time limit if processing another action.
|
||||
* @return bool
|
||||
*/
|
||||
protected function batch_limits_exceeded( $processed_actions ) {
|
||||
|
||||
@@ -35,8 +35,8 @@ abstract class ActionScheduler_Abstract_RecurringSchedule extends ActionSchedule
|
||||
protected $recurrence;
|
||||
|
||||
/**
|
||||
* @param DateTime $date The date & time to run the action.
|
||||
* @param mixed $recurrence The data used to determine the schedule's recurrence.
|
||||
* @param DateTime $date The date & time to run the action.
|
||||
* @param mixed $recurrence The data used to determine the schedule's recurrence.
|
||||
* @param DateTime|null $first (Optional) The date & time the first instance of this interval schedule ran. Default null, meaning this is the first instance.
|
||||
*/
|
||||
public function __construct( DateTime $date, $recurrence, DateTime $first = null ) {
|
||||
|
||||
@@ -36,7 +36,7 @@ abstract class ActionScheduler_Abstract_Schedule extends ActionScheduler_Schedul
|
||||
/**
|
||||
* Calculate when the next instance of this schedule would run based on a given date & time.
|
||||
*
|
||||
* @param DateTime $after
|
||||
* @param DateTime $after Start timestamp.
|
||||
* @return DateTime
|
||||
*/
|
||||
abstract protected function calculate_next( DateTime $after );
|
||||
@@ -44,7 +44,7 @@ abstract class ActionScheduler_Abstract_Schedule extends ActionScheduler_Schedul
|
||||
/**
|
||||
* Get the next date & time when this schedule should run after a given date & time.
|
||||
*
|
||||
* @param DateTime $after
|
||||
* @param DateTime $after Start timestamp.
|
||||
* @return DateTime|null
|
||||
*/
|
||||
public function get_next( DateTime $after ) {
|
||||
@@ -76,6 +76,9 @@ abstract class ActionScheduler_Abstract_Schedule extends ActionScheduler_Schedul
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wakeup.
|
||||
*/
|
||||
public function __wakeup() {
|
||||
$this->scheduled_date = as_get_datetime_object( $this->scheduled_timestamp );
|
||||
unset( $this->scheduled_timestamp );
|
||||
|
||||
@@ -43,14 +43,14 @@ abstract class ActionScheduler_Abstract_Schema {
|
||||
public function register_tables( $force_update = false ) {
|
||||
global $wpdb;
|
||||
|
||||
// make WP aware of our tables
|
||||
// make WP aware of our tables.
|
||||
foreach ( $this->tables as $table ) {
|
||||
$wpdb->tables[] = $table;
|
||||
$name = $this->get_full_table_name( $table );
|
||||
$wpdb->$table = $name;
|
||||
}
|
||||
|
||||
// create the tables
|
||||
// create the tables.
|
||||
if ( $this->schema_update_required() || $force_update ) {
|
||||
foreach ( $this->tables as $table ) {
|
||||
/**
|
||||
@@ -67,7 +67,9 @@ abstract class ActionScheduler_Abstract_Schema {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $table The name of the table
|
||||
* Get table definition.
|
||||
*
|
||||
* @param string $table The name of the table.
|
||||
*
|
||||
* @return string The CREATE TABLE statement, suitable for passing to dbDelta
|
||||
*/
|
||||
@@ -84,7 +86,7 @@ abstract class ActionScheduler_Abstract_Schema {
|
||||
$option_name = 'schema-' . static::class;
|
||||
$this->db_version = get_option( $option_name, 0 );
|
||||
|
||||
// Check for schema option stored by the Action Scheduler Custom Tables plugin in case site has migrated from that plugin with an older schema
|
||||
// Check for schema option stored by the Action Scheduler Custom Tables plugin in case site has migrated from that plugin with an older schema.
|
||||
if ( 0 === $this->db_version ) {
|
||||
|
||||
$plugin_option_name = 'schema-';
|
||||
@@ -115,7 +117,7 @@ abstract class ActionScheduler_Abstract_Schema {
|
||||
private function mark_schema_update_complete() {
|
||||
$option_name = 'schema-' . static::class;
|
||||
|
||||
// work around race conditions and ensure that our option updates
|
||||
// work around race conditions and ensure that our option updates.
|
||||
$value_to_save = (string) $this->schema_version . '.0.' . time();
|
||||
|
||||
update_option( $option_name, $value_to_save );
|
||||
@@ -124,7 +126,7 @@ abstract class ActionScheduler_Abstract_Schema {
|
||||
/**
|
||||
* Update the schema for the given table
|
||||
*
|
||||
* @param string $table The name of the table to update
|
||||
* @param string $table The name of the table to update.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -142,7 +144,9 @@ abstract class ActionScheduler_Abstract_Schema {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $table
|
||||
* Get full table name.
|
||||
*
|
||||
* @param string $table Table name.
|
||||
*
|
||||
* @return string The full name of the table, including the
|
||||
* table prefix for the current blog
|
||||
|
||||
@@ -5,9 +5,13 @@
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
abstract class ActionScheduler_Logger {
|
||||
|
||||
/** @var null|self */
|
||||
private static $logger = NULL;
|
||||
|
||||
/**
|
||||
* Get instance.
|
||||
*
|
||||
* @return ActionScheduler_Logger
|
||||
*/
|
||||
public static function instance() {
|
||||
@@ -19,23 +23,29 @@ abstract class ActionScheduler_Logger {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* @param string $message
|
||||
* @param DateTime $date
|
||||
* Create log entry.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
* @param string $message Log message.
|
||||
* @param DateTime $date Log date.
|
||||
*
|
||||
* @return string The log entry ID
|
||||
*/
|
||||
abstract public function log( $action_id, $message, DateTime $date = NULL );
|
||||
|
||||
/**
|
||||
* @param string $entry_id
|
||||
* Get action's log entry.
|
||||
*
|
||||
* @param string $entry_id Entry ID.
|
||||
*
|
||||
* @return ActionScheduler_LogEntry
|
||||
*/
|
||||
abstract public function get_entry( $entry_id );
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Get action's logs.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
*
|
||||
* @return ActionScheduler_LogEntry[]
|
||||
*/
|
||||
@@ -43,6 +53,8 @@ abstract class ActionScheduler_Logger {
|
||||
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function init() {
|
||||
@@ -60,22 +72,44 @@ abstract class ActionScheduler_Logger {
|
||||
add_action( 'action_scheduler_bulk_cancel_actions', array( $this, 'bulk_log_cancel_actions' ), 10, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register callback for storing action.
|
||||
*/
|
||||
public function hook_stored_action() {
|
||||
add_action( 'action_scheduler_stored_action', array( $this, 'log_stored_action' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Unhook callback for storing action.
|
||||
*/
|
||||
public function unhook_stored_action() {
|
||||
remove_action( 'action_scheduler_stored_action', array( $this, 'log_stored_action' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log action stored.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
*/
|
||||
public function log_stored_action( $action_id ) {
|
||||
$this->log( $action_id, __( 'action created', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log action cancellation.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
*/
|
||||
public function log_canceled_action( $action_id ) {
|
||||
$this->log( $action_id, __( 'action canceled', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log action start.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
* @param string $context Action execution context.
|
||||
*/
|
||||
public function log_started_action( $action_id, $context = '' ) {
|
||||
if ( ! empty( $context ) ) {
|
||||
/* translators: %s: context */
|
||||
@@ -86,6 +120,13 @@ abstract class ActionScheduler_Logger {
|
||||
$this->log( $action_id, $message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log action completion.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
* @param null|ActionScheduler_Action $action Action.
|
||||
* @param string $context Action exeuction context.
|
||||
*/
|
||||
public function log_completed_action( $action_id, $action = NULL, $context = '' ) {
|
||||
if ( ! empty( $context ) ) {
|
||||
/* translators: %s: context */
|
||||
@@ -96,6 +137,13 @@ abstract class ActionScheduler_Logger {
|
||||
$this->log( $action_id, $message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log action failure.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
* @param Exception $exception Exception.
|
||||
* @param string $context Action execution context.
|
||||
*/
|
||||
public function log_failed_action( $action_id, Exception $exception, $context = '' ) {
|
||||
if ( ! empty( $context ) ) {
|
||||
/* translators: 1: context 2: exception message */
|
||||
@@ -107,11 +155,23 @@ abstract class ActionScheduler_Logger {
|
||||
$this->log( $action_id, $message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log action timeout.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
* @param string $timeout Timeout.
|
||||
*/
|
||||
public function log_timed_out_action( $action_id, $timeout ) {
|
||||
/* translators: %s: amount of time */
|
||||
$this->log( $action_id, sprintf( __( 'action marked as failed after %s seconds. Unknown error occurred. Check server, PHP and database error logs to diagnose cause.', 'woocommerce' ), $timeout ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log unexpected shutdown.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
* @param mixed[] $error Error.
|
||||
*/
|
||||
public function log_unexpected_shutdown( $action_id, $error ) {
|
||||
if ( ! empty( $error ) ) {
|
||||
/* translators: 1: error message 2: filename 3: line */
|
||||
@@ -119,10 +179,21 @@ abstract class ActionScheduler_Logger {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log action reset.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
*/
|
||||
public function log_reset_action( $action_id ) {
|
||||
$this->log( $action_id, __( 'action reset', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log ignored action.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
* @param string $context Action execution context.
|
||||
*/
|
||||
public function log_ignored_action( $action_id, $context = '' ) {
|
||||
if ( ! empty( $context ) ) {
|
||||
/* translators: %s: context */
|
||||
@@ -134,10 +205,10 @@ abstract class ActionScheduler_Logger {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* @param Exception|NULL $exception The exception which occurred when fetching the action. NULL by default for backward compatibility.
|
||||
* Log the failure of fetching the action.
|
||||
*
|
||||
* @return ActionScheduler_LogEntry[]
|
||||
* @param string $action_id Action ID.
|
||||
* @param null|Exception $exception The exception which occurred when fetching the action. NULL by default for backward compatibility.
|
||||
*/
|
||||
public function log_failed_fetch_action( $action_id, Exception $exception = NULL ) {
|
||||
|
||||
@@ -151,6 +222,12 @@ abstract class ActionScheduler_Logger {
|
||||
$this->log( $action_id, $log_message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the failure of scheduling the action's next instance.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
* @param Exception $exception Exception object.
|
||||
*/
|
||||
public function log_failed_schedule_next_instance( $action_id, Exception $exception ) {
|
||||
/* translators: %s: exception message */
|
||||
$this->log( $action_id, sprintf( __( 'There was a failure scheduling the next instance of this action: %s', 'woocommerce' ), $exception->getMessage() ) );
|
||||
|
||||
@@ -19,17 +19,19 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
|
||||
protected static $max_args_length = 191;
|
||||
|
||||
/**
|
||||
* @param ActionScheduler_Action $action
|
||||
* @param DateTime $scheduled_date Optional Date of the first instance
|
||||
* to store. Otherwise uses the first date of the action's
|
||||
* schedule.
|
||||
* @param ActionScheduler_Action $action Action to save.
|
||||
* @param null|DateTime $scheduled_date Optional Date of the first instance
|
||||
* to store. Otherwise uses the first date of the action's
|
||||
* schedule.
|
||||
*
|
||||
* @return int The action ID
|
||||
*/
|
||||
abstract public function save_action( ActionScheduler_Action $action, DateTime $scheduled_date = NULL );
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Get action.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
*
|
||||
* @return ActionScheduler_Action
|
||||
*/
|
||||
@@ -141,7 +143,7 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
|
||||
public function extra_action_counts() {
|
||||
$extra_actions = array();
|
||||
|
||||
$pastdue_action_counts = ( int ) $this->query_actions( array(
|
||||
$pastdue_action_counts = (int) $this->query_actions( array(
|
||||
'status' => self::STATUS_PENDING,
|
||||
'date' => as_get_datetime_object(),
|
||||
), 'count' );
|
||||
@@ -160,17 +162,23 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Cancel action.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
*/
|
||||
abstract public function cancel_action( $action_id );
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Delete action.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
*/
|
||||
abstract public function delete_action( $action_id );
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Get action's schedule or run timestamp.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
*
|
||||
* @return DateTime The date the action is schedule to run, or the date that it ran.
|
||||
*/
|
||||
@@ -178,7 +186,9 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
|
||||
|
||||
|
||||
/**
|
||||
* @param int $max_actions
|
||||
* Make a claim.
|
||||
*
|
||||
* @param int $max_actions Maximum number of actions to claim.
|
||||
* @param DateTime $before_date Claim only actions schedule before the given date. Defaults to now.
|
||||
* @param array $hooks Claim only actions with a hook or hooks.
|
||||
* @param string $group Claim only actions in the given group.
|
||||
@@ -188,56 +198,75 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
|
||||
abstract public function stake_claim( $max_actions = 10, DateTime $before_date = null, $hooks = array(), $group = '' );
|
||||
|
||||
/**
|
||||
* Get claim count.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
abstract public function get_claim_count();
|
||||
|
||||
/**
|
||||
* @param ActionScheduler_ActionClaim $claim
|
||||
* Release the claim.
|
||||
*
|
||||
* @param ActionScheduler_ActionClaim $claim Claim object.
|
||||
*/
|
||||
abstract public function release_claim( ActionScheduler_ActionClaim $claim );
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Un-claim the action.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
*/
|
||||
abstract public function unclaim_action( $action_id );
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Mark action as failed.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
*/
|
||||
abstract public function mark_failure( $action_id );
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Log action's execution.
|
||||
*
|
||||
* @param string $action_id Actoin ID.
|
||||
*/
|
||||
abstract public function log_execution( $action_id );
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Mark action as complete.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
*/
|
||||
abstract public function mark_complete( $action_id );
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Get action's status.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
* @return string
|
||||
*/
|
||||
abstract public function get_status( $action_id );
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Get action's claim ID.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function get_claim_id( $action_id );
|
||||
|
||||
/**
|
||||
* @param string $claim_id
|
||||
* Find actions by claim ID.
|
||||
*
|
||||
* @param string $claim_id Claim ID.
|
||||
* @return array
|
||||
*/
|
||||
abstract public function find_actions_by_claim_id( $claim_id );
|
||||
|
||||
/**
|
||||
* @param string $comparison_operator
|
||||
* Validate SQL operator.
|
||||
*
|
||||
* @param string $comparison_operator Operator.
|
||||
* @return string
|
||||
*/
|
||||
protected function validate_sql_comparator( $comparison_operator ) {
|
||||
@@ -250,8 +279,8 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
|
||||
/**
|
||||
* Get the time MySQL formatted date/time string for an action's (next) scheduled date.
|
||||
*
|
||||
* @param ActionScheduler_Action $action
|
||||
* @param DateTime $scheduled_date (optional)
|
||||
* @param ActionScheduler_Action $action Action.
|
||||
* @param null|DateTime $scheduled_date Action's schedule date (optional).
|
||||
* @return string
|
||||
*/
|
||||
protected function get_scheduled_date_string( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
|
||||
@@ -267,8 +296,8 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
|
||||
/**
|
||||
* Get the time MySQL formatted date/time string for an action's (next) scheduled date.
|
||||
*
|
||||
* @param ActionScheduler_Action $action
|
||||
* @param DateTime $scheduled_date (optional)
|
||||
* @param ActionScheduler_Action $action Action.
|
||||
* @param null|DateTime $scheduled_date Action's scheduled date (optional).
|
||||
* @return string
|
||||
*/
|
||||
protected function get_scheduled_date_string_local( ActionScheduler_Action $action, DateTime $scheduled_date = NULL ) {
|
||||
@@ -386,7 +415,7 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $action_ids List of action IDs.
|
||||
* @param int[] $action_ids List of action IDs.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -399,7 +428,9 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* Get status labels.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function get_status_labels() {
|
||||
return array(
|
||||
@@ -414,14 +445,12 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
|
||||
/**
|
||||
* Check if there are any pending scheduled actions due to run.
|
||||
*
|
||||
* @param ActionScheduler_Action $action
|
||||
* @param DateTime $scheduled_date (optional)
|
||||
* @return string
|
||||
*/
|
||||
public function has_pending_actions_due() {
|
||||
$pending_actions = $this->query_actions( array(
|
||||
'date' => as_get_datetime_object(),
|
||||
'status' => ActionScheduler_Store::STATUS_PENDING,
|
||||
'status' => self::STATUS_PENDING,
|
||||
'orderby' => 'none',
|
||||
) );
|
||||
|
||||
@@ -435,6 +464,8 @@ abstract class ActionScheduler_Store extends ActionScheduler_Store_Deprecated {
|
||||
|
||||
/**
|
||||
* Callable function to mark an action as migrated optionally overridden in derived classes.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
*/
|
||||
public function mark_migrated( $action_id ) {}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* Class ActionScheduler_TimezoneHelper
|
||||
*/
|
||||
abstract class ActionScheduler_TimezoneHelper {
|
||||
|
||||
/** @var null|DateTimeZone */
|
||||
private static $local_timezone = NULL;
|
||||
|
||||
/**
|
||||
@@ -12,12 +14,12 @@ abstract class ActionScheduler_TimezoneHelper {
|
||||
*
|
||||
* @since 2.1.0
|
||||
*
|
||||
* @param DateTime $date
|
||||
* @param DateTime $date Timestamp.
|
||||
* @return ActionScheduler_DateTime
|
||||
*/
|
||||
public static function set_local_timezone( DateTime $date ) {
|
||||
|
||||
// Accept a DateTime for easier backward compatibility, even though we require methods on ActionScheduler_DateTime
|
||||
// Accept a DateTime for easier backward compatibility, even though we require methods on ActionScheduler_DateTime.
|
||||
if ( ! is_a( $date, 'ActionScheduler_DateTime' ) ) {
|
||||
$date = as_get_datetime_object( $date->format( 'U' ) );
|
||||
}
|
||||
@@ -42,6 +44,7 @@ abstract class ActionScheduler_TimezoneHelper {
|
||||
* timezone.
|
||||
*
|
||||
* @since 2.1.0
|
||||
* @param bool $reset Unused.
|
||||
* @return string PHP timezone string for the site or empty if no timezone string is available.
|
||||
*/
|
||||
protected static function get_local_timezone_string( $reset = false ) {
|
||||
@@ -75,7 +78,7 @@ abstract class ActionScheduler_TimezoneHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// No timezone string
|
||||
// No timezone string.
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -97,6 +100,9 @@ abstract class ActionScheduler_TimezoneHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get local timezone.
|
||||
*
|
||||
* @param bool $reset Toggle to discard stored value.
|
||||
* @deprecated 2.1.0
|
||||
*/
|
||||
public static function get_local_timezone( $reset = FALSE ) {
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
* Class ActionScheduler_Action
|
||||
*/
|
||||
class ActionScheduler_Action {
|
||||
/** @var string */
|
||||
protected $hook = '';
|
||||
/** @var array<string, mixed> */
|
||||
protected $args = array();
|
||||
/** @var ActionScheduler_Schedule */
|
||||
protected $schedule = NULL;
|
||||
/** @var string */
|
||||
protected $group = '';
|
||||
|
||||
/**
|
||||
@@ -23,6 +26,14 @@ class ActionScheduler_Action {
|
||||
*/
|
||||
protected $priority = 10;
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @param string $hook Action's hook.
|
||||
* @param mixed[] $args Action's arguments.
|
||||
* @param null|ActionScheduler_Schedule $schedule Action's schedule.
|
||||
* @param string $group Action's group.
|
||||
*/
|
||||
public function __construct( $hook, array $args = array(), ActionScheduler_Schedule $schedule = NULL, $group = '' ) {
|
||||
$schedule = empty( $schedule ) ? new ActionScheduler_NullSchedule() : $schedule;
|
||||
$this->set_hook($hook);
|
||||
@@ -57,16 +68,26 @@ class ActionScheduler_Action {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $hook
|
||||
* Set action's hook.
|
||||
*
|
||||
* @param string $hook Action's hook.
|
||||
*/
|
||||
protected function set_hook( $hook ) {
|
||||
$this->hook = $hook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get action's hook.
|
||||
*/
|
||||
public function get_hook() {
|
||||
return $this->hook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set action's schedule.
|
||||
*
|
||||
* @param ActionScheduler_Schedule $schedule Action's schedule.
|
||||
*/
|
||||
protected function set_schedule( ActionScheduler_Schedule $schedule ) {
|
||||
$this->schedule = $schedule;
|
||||
}
|
||||
@@ -78,16 +99,26 @@ class ActionScheduler_Action {
|
||||
return $this->schedule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set action's args.
|
||||
*
|
||||
* @param mixed[] $args Action's arguments.
|
||||
*/
|
||||
protected function set_args( array $args ) {
|
||||
$this->args = $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get action's args.
|
||||
*/
|
||||
public function get_args() {
|
||||
return $this->args;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $group
|
||||
* Section action's group.
|
||||
*
|
||||
* @param string $group Action's group.
|
||||
*/
|
||||
protected function set_group( $group ) {
|
||||
$this->group = $group;
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
class ActionScheduler_CanceledAction extends ActionScheduler_FinishedAction {
|
||||
|
||||
/**
|
||||
* @param string $hook
|
||||
* @param array $args
|
||||
* @param ActionScheduler_Schedule $schedule
|
||||
* @param string $group
|
||||
* Construct.
|
||||
*
|
||||
* @param string $hook Action's hook.
|
||||
* @param array $args Action's arguments.
|
||||
* @param null|ActionScheduler_Schedule $schedule Action's schedule.
|
||||
* @param string $group Action's group.
|
||||
*/
|
||||
public function __construct( $hook, array $args = array(), ActionScheduler_Schedule $schedule = null, $group = '' ) {
|
||||
parent::__construct( $hook, $args, $schedule, $group );
|
||||
|
||||
@@ -5,12 +5,17 @@
|
||||
*/
|
||||
class ActionScheduler_FinishedAction extends ActionScheduler_Action {
|
||||
|
||||
/**
|
||||
* Execute action.
|
||||
*/
|
||||
public function execute() {
|
||||
// don't execute
|
||||
// don't execute.
|
||||
}
|
||||
|
||||
/**
|
||||
* Get finished state.
|
||||
*/
|
||||
public function is_finished() {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,21 @@
|
||||
*/
|
||||
class ActionScheduler_NullAction extends ActionScheduler_Action {
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @param string $hook Action hook.
|
||||
* @param mixed[] $args Action arguments.
|
||||
* @param null|ActionScheduler_Schedule $schedule Action schedule.
|
||||
*/
|
||||
public function __construct( $hook = '', array $args = array(), ActionScheduler_Schedule $schedule = NULL ) {
|
||||
$this->set_schedule( new ActionScheduler_NullSchedule() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute action.
|
||||
*/
|
||||
public function execute() {
|
||||
// don't execute
|
||||
// don't execute.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ class ActionScheduler_DBStore extends ActionScheduler_Store {
|
||||
* @param bool $unique Whether the action should be unique.
|
||||
*
|
||||
* @return int Action ID.
|
||||
* @throws RuntimeException Throws exception when saving the action fails.
|
||||
* @throws \RuntimeException Throws exception when saving the action fails.
|
||||
*/
|
||||
private function save_action_to_db( ActionScheduler_Action $action, DateTime $date = null, $unique = false ) {
|
||||
global $wpdb;
|
||||
@@ -388,7 +388,8 @@ AND `group_id` = %d
|
||||
* @param string $select_or_count Whether the SQL should select and return the IDs or just the row count.
|
||||
*
|
||||
* @return string SQL statement already properly escaped.
|
||||
* @throws InvalidArgumentException If the query is invalid.
|
||||
* @throws \InvalidArgumentException If the query is invalid.
|
||||
* @throws \RuntimeException When "unknown partial args matching value".
|
||||
*/
|
||||
protected function get_query_actions_sql( array $query, $select_or_count = 'select' ) {
|
||||
|
||||
@@ -399,7 +400,7 @@ AND `group_id` = %d
|
||||
$query = wp_parse_args( $query, array(
|
||||
'hook' => '',
|
||||
'args' => null,
|
||||
'partial_args_matching' => 'off', // can be 'like' or 'json'
|
||||
'partial_args_matching' => 'off', // can be 'like' or 'json'.
|
||||
'date' => null,
|
||||
'date_compare' => '<=',
|
||||
'modified' => null,
|
||||
@@ -435,15 +436,15 @@ AND `group_id` = %d
|
||||
$sql .= " LEFT JOIN {$wpdb->actionscheduler_groups} g ON g.group_id=a.group_id";
|
||||
}
|
||||
|
||||
$sql .= " WHERE 1=1";
|
||||
$sql .= ' WHERE 1=1';
|
||||
|
||||
if ( ! empty( $query['group'] ) ) {
|
||||
$sql .= " AND g.slug=%s";
|
||||
$sql .= ' AND g.slug=%s';
|
||||
$sql_params[] = $query['group'];
|
||||
}
|
||||
|
||||
if ( ! empty( $query['hook'] ) ) {
|
||||
$sql .= " AND a.hook=%s";
|
||||
$sql .= ' AND a.hook=%s';
|
||||
$sql_params[] = $query['hook'];
|
||||
}
|
||||
|
||||
@@ -472,8 +473,8 @@ AND `group_id` = %d
|
||||
$value_type
|
||||
) );
|
||||
}
|
||||
$sql .= ' AND JSON_EXTRACT(a.args, %s)='.$placeholder;
|
||||
$sql_params[] = '$.'.$key;
|
||||
$sql .= ' AND JSON_EXTRACT(a.args, %s)=' . $placeholder;
|
||||
$sql_params[] = '$.' . $key;
|
||||
$sql_params[] = $value;
|
||||
}
|
||||
break;
|
||||
@@ -485,7 +486,7 @@ AND `group_id` = %d
|
||||
}
|
||||
break;
|
||||
case 'off':
|
||||
$sql .= " AND a.args=%s";
|
||||
$sql .= ' AND a.args=%s';
|
||||
$sql_params[] = $this->get_args_for_query( $query['args'] );
|
||||
break;
|
||||
default:
|
||||
@@ -823,7 +824,7 @@ AND `group_id` = %d
|
||||
* Set a claim filter.
|
||||
*
|
||||
* @param string $filter_name Claim filter name.
|
||||
* @param mixed $filter_values Values to filter.
|
||||
* @param mixed $filter_values Values to filter.
|
||||
* @return void
|
||||
*/
|
||||
public function set_claim_filter( $filter_name, $filter_values ) {
|
||||
@@ -1017,6 +1018,7 @@ AND `group_id` = %d
|
||||
* Release actions from a claim and delete the claim.
|
||||
*
|
||||
* @param ActionScheduler_ActionClaim $claim Claim object.
|
||||
* @throws \RuntimeException When unable to release actions from claim.
|
||||
*/
|
||||
public function release_claim( ActionScheduler_ActionClaim $claim ) {
|
||||
/** @var \wpdb $wpdb */
|
||||
|
||||
@@ -15,8 +15,11 @@ use Action_Scheduler\Migration\Controller;
|
||||
class ActionScheduler_HybridStore extends Store {
|
||||
const DEMARKATION_OPTION = 'action_scheduler_hybrid_store_demarkation';
|
||||
|
||||
/** @var ActionScheduler_Store */
|
||||
private $primary_store;
|
||||
/** @var ActionScheduler_Store */
|
||||
private $secondary_store;
|
||||
/** @var Action_Scheduler\Migration\Runner */
|
||||
private $migration_runner;
|
||||
|
||||
/**
|
||||
@@ -64,8 +67,8 @@ class ActionScheduler_HybridStore extends Store {
|
||||
* value to be one higher than the posts table to ensure that
|
||||
* there are no ID collisions.
|
||||
*
|
||||
* @param string $table_name
|
||||
* @param string $table_suffix
|
||||
* @param string $table_name Table name.
|
||||
* @param string $table_suffix Suffix of table name.
|
||||
*
|
||||
* @return void
|
||||
* @codeCoverageIgnore
|
||||
@@ -78,7 +81,7 @@ class ActionScheduler_HybridStore extends Store {
|
||||
/** @var \wpdb $wpdb */
|
||||
global $wpdb;
|
||||
/**
|
||||
* A default date of '0000-00-00 00:00:00' is invalid in MySQL 5.7 when configured with
|
||||
* A default date of '0000-00-00 00:00:00' is invalid in MySQL 5.7 when configured with
|
||||
* sql_mode including both STRICT_TRANS_TABLES and NO_ZERO_DATE.
|
||||
*/
|
||||
$default_date = new DateTime( 'tomorrow' );
|
||||
@@ -135,8 +138,8 @@ class ActionScheduler_HybridStore extends Store {
|
||||
* After it migrates, the secondary store will logically contain
|
||||
* the next matching action, so return the result thence.
|
||||
*
|
||||
* @param string $hook
|
||||
* @param array $params
|
||||
* @param string $hook Action's hook.
|
||||
* @param array $params Action's arguments.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -154,7 +157,7 @@ class ActionScheduler_HybridStore extends Store {
|
||||
* If any are found, migrate them immediately. Then the secondary
|
||||
* store will contain the canonical results.
|
||||
*
|
||||
* @param array $query
|
||||
* @param array $query Query arguments.
|
||||
* @param string $query_type Whether to select or count the results. Default, select.
|
||||
*
|
||||
* @return int[]
|
||||
@@ -203,8 +206,10 @@ class ActionScheduler_HybridStore extends Store {
|
||||
* migrate them immediately, then ask the primary store for the
|
||||
* canonical claim.
|
||||
*
|
||||
* @param int $max_actions
|
||||
* @param DateTime|null $before_date
|
||||
* @param int $max_actions Maximum number of actions to claim.
|
||||
* @param null|DateTime $before_date Latest timestamp of actions to claim.
|
||||
* @param string[] $hooks Hook of actions to claim.
|
||||
* @param string $group Group of actions to claim.
|
||||
*
|
||||
* @return ActionScheduler_ActionClaim
|
||||
*/
|
||||
@@ -376,10 +381,12 @@ class ActionScheduler_HybridStore extends Store {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
/**
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* All claim-related functions should operate solely
|
||||
* on the primary store.
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the claim count from the table data store.
|
||||
|
||||
@@ -8,9 +8,11 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
const TYPE = 'action_log';
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* @param string $message
|
||||
* @param DateTime $date
|
||||
* Create log entry.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
* @param string $message Action log's message.
|
||||
* @param DateTime $date Action log's timestamp.
|
||||
*
|
||||
* @return string The log entry ID
|
||||
*/
|
||||
@@ -24,6 +26,13 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
return $comment_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create comment.
|
||||
*
|
||||
* @param int $action_id Action ID.
|
||||
* @param string $message Action log's message.
|
||||
* @param DateTime $date Action log entry's timestamp.
|
||||
*/
|
||||
protected function create_wp_comment( $action_id, $message, DateTime $date ) {
|
||||
|
||||
$comment_date_gmt = $date->format('Y-m-d H:i:s');
|
||||
@@ -41,7 +50,9 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $entry_id
|
||||
* Get single log entry for action.
|
||||
*
|
||||
* @param string $entry_id Entry ID.
|
||||
*
|
||||
* @return ActionScheduler_LogEntry
|
||||
*/
|
||||
@@ -57,7 +68,9 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action_id
|
||||
* Get action's logs.
|
||||
*
|
||||
* @param string $action_id Action ID.
|
||||
*
|
||||
* @return ActionScheduler_LogEntry[]
|
||||
*/
|
||||
@@ -83,6 +96,11 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get comment.
|
||||
*
|
||||
* @param int $comment_id Comment ID.
|
||||
*/
|
||||
protected function get_comment( $comment_id ) {
|
||||
return get_comment( $comment_id );
|
||||
}
|
||||
@@ -90,12 +108,14 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
|
||||
|
||||
/**
|
||||
* @param WP_Comment_Query $query
|
||||
* Filter comment queries.
|
||||
*
|
||||
* @param WP_Comment_Query $query Comment query object.
|
||||
*/
|
||||
public function filter_comment_queries( $query ) {
|
||||
foreach ( array('ID', 'parent', 'post_author', 'post_name', 'post_parent', 'type', 'post_type', 'post_id', 'post_ID') as $key ) {
|
||||
if ( !empty($query->query_vars[$key]) ) {
|
||||
return; // don't slow down queries that wouldn't include action_log comments anyway
|
||||
return; // don't slow down queries that wouldn't include action_log comments anyway.
|
||||
}
|
||||
}
|
||||
$query->query_vars['action_log_filter'] = TRUE;
|
||||
@@ -103,8 +123,10 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $clauses
|
||||
* @param WP_Comment_Query $query
|
||||
* Filter comment queries.
|
||||
*
|
||||
* @param array $clauses Query's clauses.
|
||||
* @param WP_Comment_Query $query Query object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@@ -119,8 +141,8 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
* Make sure Action Scheduler logs are excluded from comment feeds, which use WP_Query, not
|
||||
* the WP_Comment_Query class handled by @see self::filter_comment_queries().
|
||||
*
|
||||
* @param string $where
|
||||
* @param WP_Query $query
|
||||
* @param string $where Query's `where` clause.
|
||||
* @param WP_Query $query Query object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -144,8 +166,8 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
/**
|
||||
* Remove action log entries from wp_count_comments()
|
||||
*
|
||||
* @param array $stats
|
||||
* @param int $post_id
|
||||
* @param array $stats Comment count.
|
||||
* @param int $post_id Post ID.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
@@ -179,7 +201,7 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
$approved = array( '0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed' );
|
||||
|
||||
foreach ( (array) $count as $row ) {
|
||||
// Don't count post-trashed toward totals
|
||||
// Don't count post-trashed toward totals.
|
||||
if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] ) {
|
||||
$total += $row['num_comments'];
|
||||
}
|
||||
@@ -213,6 +235,8 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function init() {
|
||||
@@ -222,17 +246,24 @@ class ActionScheduler_wpCommentLogger extends ActionScheduler_Logger {
|
||||
parent::init();
|
||||
|
||||
add_action( 'pre_get_comments', array( $this, 'filter_comment_queries' ), 10, 1 );
|
||||
add_action( 'wp_count_comments', array( $this, 'filter_comment_count' ), 20, 2 ); // run after WC_Comments::wp_count_comments() to make sure we exclude order notes and action logs
|
||||
add_action( 'wp_count_comments', array( $this, 'filter_comment_count' ), 20, 2 ); // run after WC_Comments::wp_count_comments() to make sure we exclude order notes and action logs.
|
||||
add_action( 'comment_feed_where', array( $this, 'filter_comment_feed' ), 10, 2 );
|
||||
|
||||
// Delete comments count cache whenever there is a new comment or a comment status changes
|
||||
// Delete comments count cache whenever there is a new comment or a comment status changes.
|
||||
add_action( 'wp_insert_comment', array( $this, 'delete_comment_count_cache' ) );
|
||||
add_action( 'wp_set_comment_status', array( $this, 'delete_comment_count_cache' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Defer comment counting.
|
||||
*/
|
||||
public function disable_comment_counting() {
|
||||
wp_defer_comment_counting(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable comment counting.
|
||||
*/
|
||||
public function enable_comment_counting() {
|
||||
wp_defer_comment_counting(false);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ActionScheduler_wpPostStore_PostStatusRegistrar {
|
||||
|
||||
/**
|
||||
* Registrar.
|
||||
*/
|
||||
public function register() {
|
||||
register_post_status( ActionScheduler_Store::STATUS_RUNNING, array_merge( $this->post_status_args(), $this->post_status_running_labels() ) );
|
||||
register_post_status( ActionScheduler_Store::STATUS_FAILED, array_merge( $this->post_status_args(), $this->post_status_failed_labels() ) );
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ActionScheduler_wpPostStore_PostTypeRegistrar {
|
||||
/**
|
||||
* Registrar.
|
||||
*/
|
||||
public function register() {
|
||||
register_post_type( ActionScheduler_wpPostStore::POST_TYPE, $this->post_type_args() );
|
||||
}
|
||||
@@ -47,4 +50,3 @@ class ActionScheduler_wpPostStore_PostTypeRegistrar {
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,17 @@
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ActionScheduler_wpPostStore_TaxonomyRegistrar {
|
||||
|
||||
/**
|
||||
* Registrar.
|
||||
*/
|
||||
public function register() {
|
||||
register_taxonomy( ActionScheduler_wpPostStore::GROUP_TAXONOMY, ActionScheduler_wpPostStore::POST_TYPE, $this->taxonomy_args() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get taxonomy arguments.
|
||||
*/
|
||||
protected function taxonomy_args() {
|
||||
$args = array(
|
||||
'label' => __( 'Action Group', 'woocommerce' ),
|
||||
@@ -23,4 +30,3 @@ class ActionScheduler_wpPostStore_TaxonomyRegistrar {
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,21 +13,21 @@ namespace Action_Scheduler\Migration;
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class ActionMigrator {
|
||||
/** var ActionScheduler_Store */
|
||||
/** @var ActionScheduler_Store */
|
||||
private $source;
|
||||
|
||||
/** var ActionScheduler_Store */
|
||||
/** @var ActionScheduler_Store */
|
||||
private $destination;
|
||||
|
||||
/** var LogMigrator */
|
||||
/** @var LogMigrator */
|
||||
private $log_migrator;
|
||||
|
||||
/**
|
||||
* ActionMigrator constructor.
|
||||
*
|
||||
* @param ActionScheduler_Store $source_store Source store object.
|
||||
* @param ActionScheduler_Store $destination_store Destination store object.
|
||||
* @param LogMigrator $log_migrator Log migrator object.
|
||||
* @param \ActionScheduler_Store $source_store Source store object.
|
||||
* @param \ActionScheduler_Store $destination_store Destination store object.
|
||||
* @param LogMigrator $log_migrator Log migrator object.
|
||||
*/
|
||||
public function __construct( \ActionScheduler_Store $source_store, \ActionScheduler_Store $destination_store, LogMigrator $log_migrator ) {
|
||||
$this->source = $source_store;
|
||||
@@ -41,6 +41,7 @@ class ActionMigrator {
|
||||
* @param int $source_action_id Action ID.
|
||||
*
|
||||
* @return int 0|new action ID
|
||||
* @throws \RuntimeException When unable to delete action from the source store.
|
||||
*/
|
||||
public function migrate( $source_action_id ) {
|
||||
try {
|
||||
@@ -52,13 +53,13 @@ class ActionMigrator {
|
||||
}
|
||||
|
||||
if ( is_null( $action ) || empty( $status ) || ! $action->get_schedule()->get_date() ) {
|
||||
// null action or empty status means the fetch operation failed or the action didn't exist
|
||||
// null schedule means it's missing vital data
|
||||
// delete it and move on
|
||||
// null action or empty status means the fetch operation failed or the action didn't exist.
|
||||
// null schedule means it's missing vital data.
|
||||
// delete it and move on.
|
||||
try {
|
||||
$this->source->delete_action( $source_action_id );
|
||||
} catch ( \Exception $e ) {
|
||||
// nothing to do, it didn't exist in the first place
|
||||
// nothing to do, it didn't exist in the first place.
|
||||
}
|
||||
do_action( 'action_scheduler/no_action_to_migrate', $source_action_id, $this->source, $this->destination );
|
||||
|
||||
@@ -67,14 +68,14 @@ class ActionMigrator {
|
||||
|
||||
try {
|
||||
|
||||
// Make sure the last attempt date is set correctly for completed and failed actions
|
||||
// Make sure the last attempt date is set correctly for completed and failed actions.
|
||||
$last_attempt_date = ( $status !== \ActionScheduler_Store::STATUS_PENDING ) ? $this->source->get_date( $source_action_id ) : null;
|
||||
|
||||
$destination_action_id = $this->destination->save_action( $action, null, $last_attempt_date );
|
||||
} catch ( \Exception $e ) {
|
||||
do_action( 'action_scheduler/migrate_action_failed', $source_action_id, $this->source, $this->destination );
|
||||
|
||||
return 0; // could not save the action in the new store
|
||||
return 0; // could not save the action in the new store.
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -99,7 +100,7 @@ class ActionMigrator {
|
||||
|
||||
return $destination_action_id;
|
||||
} catch ( \Exception $e ) {
|
||||
// could not delete from the old store
|
||||
// could not delete from the old store.
|
||||
$this->source->mark_migrated( $source_action_id );
|
||||
do_action( 'action_scheduler/migrate_action_incomplete', $source_action_id, $destination_action_id, $this->source, $this->destination );
|
||||
do_action( 'action_scheduler/migrated_action', $source_action_id, $destination_action_id, $this->source, $this->destination );
|
||||
|
||||
@@ -16,9 +16,9 @@ class ActionScheduler_DBStoreMigrator extends ActionScheduler_DBStore {
|
||||
* it can't have been attempted yet, but migrated completed actions will have an attempted date, so we need to save
|
||||
* that when first saving the action.
|
||||
*
|
||||
* @param ActionScheduler_Action $action
|
||||
* @param \DateTime $scheduled_date Optional date of the first instance to store.
|
||||
* @param \DateTime $last_attempt_date Optional date the action was last attempted.
|
||||
* @param ActionScheduler_Action $action Action to migrate.
|
||||
* @param null|\DateTime $scheduled_date Optional date of the first instance to store.
|
||||
* @param null|\DateTime $last_attempt_date Optional date the action was last attempted.
|
||||
*
|
||||
* @return string The action ID
|
||||
* @throws \RuntimeException When the action is not saved.
|
||||
|
||||
@@ -16,7 +16,7 @@ use ActionScheduler_Store as Store;
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class BatchFetcher {
|
||||
/** var ActionScheduler_Store */
|
||||
/** @var ActionScheduler_Store */
|
||||
private $store;
|
||||
|
||||
/**
|
||||
@@ -31,7 +31,7 @@ class BatchFetcher {
|
||||
/**
|
||||
* Retrieve a list of actions.
|
||||
*
|
||||
* @param int $count The number of actions to retrieve
|
||||
* @param int $count The number of actions to retrieve.
|
||||
*
|
||||
* @return int[] A list of action IDs
|
||||
*/
|
||||
@@ -69,7 +69,7 @@ class BatchFetcher {
|
||||
Store::STATUS_CANCELED,
|
||||
Store::STATUS_COMPLETE,
|
||||
Store::STATUS_RUNNING,
|
||||
'', // any other unanticipated status
|
||||
'', // any other unanticipated status.
|
||||
];
|
||||
|
||||
foreach ( $priorities as $status ) {
|
||||
@@ -83,4 +83,4 @@ class BatchFetcher {
|
||||
], $args );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ class Config {
|
||||
* Get the configured source store.
|
||||
*
|
||||
* @return ActionScheduler_Store
|
||||
* @throws \RuntimeException When source store is not configured.
|
||||
*/
|
||||
public function get_source_store() {
|
||||
if ( empty( $this->source_store ) ) {
|
||||
@@ -68,6 +69,7 @@ class Config {
|
||||
* Get the configured source logger.
|
||||
*
|
||||
* @return ActionScheduler_Logger
|
||||
* @throws \RuntimeException When source logger is not configured.
|
||||
*/
|
||||
public function get_source_logger() {
|
||||
if ( empty( $this->source_logger ) ) {
|
||||
@@ -80,7 +82,7 @@ class Config {
|
||||
/**
|
||||
* Set the configured source logger.
|
||||
*
|
||||
* @param ActionScheduler_Logger $logger
|
||||
* @param ActionScheduler_Logger $logger Logger object.
|
||||
*/
|
||||
public function set_source_logger( Logger $logger ) {
|
||||
$this->source_logger = $logger;
|
||||
@@ -90,6 +92,7 @@ class Config {
|
||||
* Get the configured destination store.
|
||||
*
|
||||
* @return ActionScheduler_Store
|
||||
* @throws \RuntimeException When destination store is not configured.
|
||||
*/
|
||||
public function get_destination_store() {
|
||||
if ( empty( $this->destination_store ) ) {
|
||||
@@ -102,7 +105,7 @@ class Config {
|
||||
/**
|
||||
* Set the configured destination store.
|
||||
*
|
||||
* @param ActionScheduler_Store $store
|
||||
* @param ActionScheduler_Store $store Action store object.
|
||||
*/
|
||||
public function set_destination_store( Store $store ) {
|
||||
$this->destination_store = $store;
|
||||
@@ -112,6 +115,7 @@ class Config {
|
||||
* Get the configured destination logger.
|
||||
*
|
||||
* @return ActionScheduler_Logger
|
||||
* @throws \RuntimeException When destination logger is not configured.
|
||||
*/
|
||||
public function get_destination_logger() {
|
||||
if ( empty( $this->destination_logger ) ) {
|
||||
@@ -124,7 +128,7 @@ class Config {
|
||||
/**
|
||||
* Set the configured destination logger.
|
||||
*
|
||||
* @param ActionScheduler_Logger $logger
|
||||
* @param ActionScheduler_Logger $logger Logger object.
|
||||
*/
|
||||
public function set_destination_logger( Logger $logger ) {
|
||||
$this->destination_logger = $logger;
|
||||
@@ -142,7 +146,7 @@ class Config {
|
||||
/**
|
||||
* Set flag indicating whether it's a dry run.
|
||||
*
|
||||
* @param bool $dry_run
|
||||
* @param bool $dry_run Dry run toggle.
|
||||
*/
|
||||
public function set_dry_run( $dry_run ) {
|
||||
$this->dry_run = (bool) $dry_run;
|
||||
@@ -160,7 +164,7 @@ class Config {
|
||||
/**
|
||||
* Set progress bar object.
|
||||
*
|
||||
* @param ActionScheduler\WPCLI\ProgressBar $progress_bar
|
||||
* @param ActionScheduler\WPCLI\ProgressBar $progress_bar Progress bar object.
|
||||
*/
|
||||
public function set_progress_bar( ProgressBar $progress_bar ) {
|
||||
$this->progress_bar = $progress_bar;
|
||||
|
||||
@@ -19,6 +19,7 @@ use Action_Scheduler\WP_CLI\ProgressBar;
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class Controller {
|
||||
/** @var self */
|
||||
private static $instance;
|
||||
|
||||
/** @var Action_Scheduler\Migration\Scheduler */
|
||||
@@ -171,7 +172,7 @@ class Controller {
|
||||
add_action( 'init', array( $this, 'maybe_hook_migration' ) );
|
||||
add_action( 'wp_loaded', array( $this, 'schedule_migration' ) );
|
||||
|
||||
// Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen
|
||||
// Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen.
|
||||
add_action( 'load-tools_page_action-scheduler', array( $this, 'hook_admin_notices' ), 10, 0 );
|
||||
add_action( 'load-woocommerce_page_wc-status', array( $this, 'hook_admin_notices' ), 10, 0 );
|
||||
}
|
||||
|
||||
@@ -18,6 +18,6 @@ class DryRun_LogMigrator extends LogMigrator {
|
||||
* @param int $destination_action_id Destination logger object.
|
||||
*/
|
||||
public function migrate( $source_action_id, $destination_action_id ) {
|
||||
// no-op
|
||||
// no-op.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@ class ActionScheduler_CanceledSchedule extends ActionScheduler_SimpleSchedule {
|
||||
|
||||
/**
|
||||
* Deprecated property @see $this->__wakeup() for details.
|
||||
**/
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
private $timestamp = NULL;
|
||||
|
||||
/**
|
||||
* @param DateTime $after
|
||||
* @param DateTime $after Timestamp.
|
||||
*
|
||||
* @return DateTime|null
|
||||
*/
|
||||
@@ -23,7 +25,7 @@ class ActionScheduler_CanceledSchedule extends ActionScheduler_SimpleSchedule {
|
||||
* Cancelled actions should never have a next schedule, even if get_next()
|
||||
* is called with $after < $this->scheduled_date.
|
||||
*
|
||||
* @param DateTime $after
|
||||
* @param DateTime $after Timestamp.
|
||||
* @return DateTime|null
|
||||
*/
|
||||
public function get_next( DateTime $after ) {
|
||||
|
||||
@@ -7,21 +7,25 @@ class ActionScheduler_CronSchedule extends ActionScheduler_Abstract_RecurringSch
|
||||
|
||||
/**
|
||||
* Deprecated property @see $this->__wakeup() for details.
|
||||
**/
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
private $start_timestamp = NULL;
|
||||
|
||||
/**
|
||||
* Deprecated property @see $this->__wakeup() for details.
|
||||
**/
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
private $cron = NULL;
|
||||
|
||||
/**
|
||||
* Wrapper for parent constructor to accept a cron expression string and map it to a CronExpression for this
|
||||
* objects $recurrence property.
|
||||
*
|
||||
* @param DateTime $start The date & time to run the action at or after. If $start aligns with the CronSchedule passed via $recurrence, it will be used. If it does not align, the first matching date after it will be used.
|
||||
* @param DateTime $start The date & time to run the action at or after. If $start aligns with the CronSchedule passed via $recurrence, it will be used. If it does not align, the first matching date after it will be used.
|
||||
* @param CronExpression|string $recurrence The CronExpression used to calculate the schedule's next instance.
|
||||
* @param DateTime|null $first (Optional) The date & time the first instance of this interval schedule ran. Default null, meaning this is the first instance.
|
||||
* @param DateTime|null $first (Optional) The date & time the first instance of this interval schedule ran. Default null, meaning this is the first instance.
|
||||
*/
|
||||
public function __construct( DateTime $start, $recurrence, DateTime $first = null ) {
|
||||
if ( ! is_a( $recurrence, 'CronExpression' ) ) {
|
||||
@@ -41,7 +45,7 @@ class ActionScheduler_CronSchedule extends ActionScheduler_Abstract_RecurringSch
|
||||
* Calculate when an instance of this schedule would start based on a given
|
||||
* date & time using its the CronExpression.
|
||||
*
|
||||
* @param DateTime $after
|
||||
* @param DateTime $after Timestamp.
|
||||
* @return DateTime
|
||||
*/
|
||||
protected function calculate_next( DateTime $after ) {
|
||||
|
||||
@@ -7,19 +7,23 @@ class ActionScheduler_IntervalSchedule extends ActionScheduler_Abstract_Recurrin
|
||||
|
||||
/**
|
||||
* Deprecated property @see $this->__wakeup() for details.
|
||||
**/
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
private $start_timestamp = NULL;
|
||||
|
||||
/**
|
||||
* Deprecated property @see $this->__wakeup() for details.
|
||||
**/
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
private $interval_in_seconds = NULL;
|
||||
|
||||
/**
|
||||
* Calculate when this schedule should start after a given date & time using
|
||||
* the number of seconds between recurrences.
|
||||
*
|
||||
* @param DateTime $after
|
||||
* @param DateTime $after Timestamp.
|
||||
* @return DateTime
|
||||
*/
|
||||
protected function calculate_next( DateTime $after ) {
|
||||
|
||||
@@ -11,7 +11,7 @@ class ActionScheduler_NullSchedule extends ActionScheduler_SimpleSchedule {
|
||||
/**
|
||||
* Make the $date param optional and default to null.
|
||||
*
|
||||
* @param null $date The date & time to run the action.
|
||||
* @param null|DateTime $date The date & time to run the action.
|
||||
*/
|
||||
public function __construct( DateTime $date = null ) {
|
||||
$this->scheduled_date = null;
|
||||
@@ -25,6 +25,9 @@ class ActionScheduler_NullSchedule extends ActionScheduler_SimpleSchedule {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wakeup.
|
||||
*/
|
||||
public function __wakeup() {
|
||||
$this->scheduled_date = null;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
interface ActionScheduler_Schedule {
|
||||
/**
|
||||
* @param DateTime $after
|
||||
* @param null|DateTime $after Timestamp.
|
||||
* @return DateTime|null
|
||||
*/
|
||||
public function next( DateTime $after = NULL );
|
||||
@@ -15,4 +15,3 @@ interface ActionScheduler_Schedule {
|
||||
*/
|
||||
public function is_recurring();
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@ class ActionScheduler_SimpleSchedule extends ActionScheduler_Abstract_Schedule {
|
||||
|
||||
/**
|
||||
* Deprecated property @see $this->__wakeup() for details.
|
||||
**/
|
||||
*
|
||||
* @var null|DateTime
|
||||
*/
|
||||
private $timestamp = NULL;
|
||||
|
||||
/**
|
||||
* @param DateTime $after
|
||||
* @param DateTime $after Timestamp.
|
||||
*
|
||||
* @return DateTime|null
|
||||
*/
|
||||
|
||||
@@ -15,6 +15,9 @@ class ActionScheduler_LoggerSchema extends ActionScheduler_Abstract_Schema {
|
||||
*/
|
||||
protected $schema_version = 3;
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->tables = [
|
||||
self::LOG_TABLE,
|
||||
@@ -28,6 +31,11 @@ class ActionScheduler_LoggerSchema extends ActionScheduler_Abstract_Schema {
|
||||
add_action( 'action_scheduler_before_schema_update', array( $this, 'update_schema_3_0' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table definition.
|
||||
*
|
||||
* @param string $table Table name.
|
||||
*/
|
||||
protected function get_table_definition( $table ) {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->$table;
|
||||
|
||||
@@ -18,6 +18,9 @@ class ActionScheduler_StoreSchema extends ActionScheduler_Abstract_Schema {
|
||||
*/
|
||||
protected $schema_version = 7;
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->tables = [
|
||||
self::ACTIONS_TABLE,
|
||||
@@ -33,10 +36,16 @@ class ActionScheduler_StoreSchema extends ActionScheduler_Abstract_Schema {
|
||||
add_action( 'action_scheduler_before_schema_update', array( $this, 'update_schema_5_0' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table definition.
|
||||
*
|
||||
* @param string $table Table name.
|
||||
*/
|
||||
protected function get_table_definition( $table ) {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->$table;
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
// phpcs:ignore Squiz.PHP.CommentedOutCode
|
||||
$max_index_length = 191; // @see wp_get_db_schema()
|
||||
$hook_status_scheduled_date_gmt_max_index_length = $max_index_length - 20 - 8; // - status, - scheduled_date_gmt
|
||||
$default_date = self::DEFAULT_DATE;
|
||||
|
||||
@@ -35,8 +35,9 @@ function as_enqueue_async_action( $hook, $args = array(), $group = '', $unique =
|
||||
* @param array $args Action arguments.
|
||||
* @param string $group Action group.
|
||||
* @param int $priority Action priority.
|
||||
* @param bool $unique Unique action.
|
||||
*/
|
||||
$pre = apply_filters( 'pre_as_enqueue_async_action', null, $hook, $args, $group, $priority );
|
||||
$pre = apply_filters( 'pre_as_enqueue_async_action', null, $hook, $args, $group, $priority, $unique );
|
||||
if ( null !== $pre ) {
|
||||
return is_int( $pre ) ? $pre : 0;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
=== Action Scheduler ===
|
||||
Contributors: Automattic, wpmuguru, claudiosanches, peterfabian1000, vedjain, jamosova, obliviousharmony, konamiman, sadowski, royho, barryhughes-1
|
||||
Tags: scheduler, cron
|
||||
Stable tag: 3.8.1
|
||||
Stable tag: 3.8.2
|
||||
License: GPLv3
|
||||
Requires at least: 6.3
|
||||
Tested up to: 6.5
|
||||
Requires at least: 6.4
|
||||
Tested up to: 6.6
|
||||
Requires PHP: 7.0
|
||||
|
||||
Action Scheduler - Job Queue for WordPress
|
||||
@@ -47,6 +47,12 @@ Collaboration is cool. We'd love to work with you to improve Action Scheduler. [
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 3.8.2 - 2024-09-12 =
|
||||
* Add missing parameter to the `pre_as_enqueue_async_action` hook.
|
||||
* Bump minimum PHP version to 7.0.
|
||||
* Bump minimum WordPress version to 6.4.
|
||||
* Make the batch size adjustable during processing.
|
||||
|
||||
= 3.8.1 - 2024-06-20 =
|
||||
* Fix typos.
|
||||
* Improve the messaging in our unidentified action exceptions.
|
||||
|
||||
Reference in New Issue
Block a user