@@ -4,8 +4,8 @@ |
||
4 | 4 | * Class ActionScheduler_NullLogEntry |
5 | 5 | */ |
6 | 6 | class ActionScheduler_NullLogEntry extends ActionScheduler_LogEntry { |
7 | - public function __construct( $action_id = '', $message = '' ) { |
|
8 | - // nothing to see here |
|
9 | - } |
|
7 | + public function __construct( $action_id = '', $message = '' ) { |
|
8 | + // nothing to see here |
|
9 | + } |
|
10 | 10 | } |
11 | - |
|
12 | 11 | \ No newline at end of file |
12 | + |
|
13 | 13 | \ No newline at end of file |
@@ -5,151 +5,151 @@ |
||
5 | 5 | */ |
6 | 6 | class ActionScheduler_QueueCleaner { |
7 | 7 | |
8 | - /** @var int */ |
|
9 | - protected $batch_size; |
|
10 | - |
|
11 | - /** @var ActionScheduler_Store */ |
|
12 | - private $store = null; |
|
13 | - |
|
14 | - /** |
|
15 | - * 31 days in seconds. |
|
16 | - * |
|
17 | - * @var int |
|
18 | - */ |
|
19 | - private $month_in_seconds = 2678400; |
|
20 | - |
|
21 | - /** |
|
22 | - * ActionScheduler_QueueCleaner constructor. |
|
23 | - * |
|
24 | - * @param ActionScheduler_Store $store The store instance. |
|
25 | - * @param int $batch_size The batch size. |
|
26 | - */ |
|
27 | - public function __construct( ActionScheduler_Store $store = null, $batch_size = 20 ) { |
|
28 | - $this->store = $store ? $store : ActionScheduler_Store::instance(); |
|
29 | - $this->batch_size = $batch_size; |
|
30 | - } |
|
31 | - |
|
32 | - public function delete_old_actions() { |
|
33 | - $lifespan = apply_filters( 'action_scheduler_retention_period', $this->month_in_seconds ); |
|
34 | - $cutoff = as_get_datetime_object($lifespan.' seconds ago'); |
|
35 | - |
|
36 | - $statuses_to_purge = array( |
|
37 | - ActionScheduler_Store::STATUS_COMPLETE, |
|
38 | - ActionScheduler_Store::STATUS_CANCELED, |
|
39 | - ); |
|
40 | - |
|
41 | - foreach ( $statuses_to_purge as $status ) { |
|
42 | - $actions_to_delete = $this->store->query_actions( array( |
|
43 | - 'status' => $status, |
|
44 | - 'modified' => $cutoff, |
|
45 | - 'modified_compare' => '<=', |
|
46 | - 'per_page' => $this->get_batch_size(), |
|
47 | - ) ); |
|
48 | - |
|
49 | - foreach ( $actions_to_delete as $action_id ) { |
|
50 | - try { |
|
51 | - $this->store->delete_action( $action_id ); |
|
52 | - } catch ( Exception $e ) { |
|
53 | - |
|
54 | - /** |
|
55 | - * Notify 3rd party code of exceptions when deleting a completed action older than the retention period |
|
56 | - * |
|
57 | - * This hook provides a way for 3rd party code to log or otherwise handle exceptions relating to their |
|
58 | - * actions. |
|
59 | - * |
|
60 | - * @since 2.0.0 |
|
61 | - * |
|
62 | - * @param int $action_id The scheduled actions ID in the data store |
|
63 | - * @param Exception $e The exception thrown when attempting to delete the action from the data store |
|
64 | - * @param int $lifespan The retention period, in seconds, for old actions |
|
65 | - * @param int $count_of_actions_to_delete The number of old actions being deleted in this batch |
|
66 | - */ |
|
67 | - do_action( 'action_scheduler_failed_old_action_deletion', $action_id, $e, $lifespan, count( $actions_to_delete ) ); |
|
68 | - } |
|
69 | - } |
|
70 | - } |
|
71 | - } |
|
72 | - |
|
73 | - /** |
|
74 | - * Unclaim pending actions that have not been run within a given time limit. |
|
75 | - * |
|
76 | - * When called by ActionScheduler_Abstract_QueueRunner::run_cleanup(), the time limit passed |
|
77 | - * as a parameter is 10x the time limit used for queue processing. |
|
78 | - * |
|
79 | - * @param int $time_limit The number of seconds to allow a queue to run before unclaiming its pending actions. Default 300 (5 minutes). |
|
80 | - */ |
|
81 | - public function reset_timeouts( $time_limit = 300 ) { |
|
82 | - $timeout = apply_filters( 'action_scheduler_timeout_period', $time_limit ); |
|
83 | - if ( $timeout < 0 ) { |
|
84 | - return; |
|
85 | - } |
|
86 | - $cutoff = as_get_datetime_object($timeout.' seconds ago'); |
|
87 | - $actions_to_reset = $this->store->query_actions( array( |
|
88 | - 'status' => ActionScheduler_Store::STATUS_PENDING, |
|
89 | - 'modified' => $cutoff, |
|
90 | - 'modified_compare' => '<=', |
|
91 | - 'claimed' => true, |
|
92 | - 'per_page' => $this->get_batch_size(), |
|
93 | - ) ); |
|
94 | - |
|
95 | - foreach ( $actions_to_reset as $action_id ) { |
|
96 | - $this->store->unclaim_action( $action_id ); |
|
97 | - do_action( 'action_scheduler_reset_action', $action_id ); |
|
98 | - } |
|
99 | - } |
|
100 | - |
|
101 | - /** |
|
102 | - * Mark actions that have been running for more than a given time limit as failed, based on |
|
103 | - * the assumption some uncatachable and unloggable fatal error occurred during processing. |
|
104 | - * |
|
105 | - * When called by ActionScheduler_Abstract_QueueRunner::run_cleanup(), the time limit passed |
|
106 | - * as a parameter is 10x the time limit used for queue processing. |
|
107 | - * |
|
108 | - * @param int $time_limit The number of seconds to allow an action to run before it is considered to have failed. Default 300 (5 minutes). |
|
109 | - */ |
|
110 | - public function mark_failures( $time_limit = 300 ) { |
|
111 | - $timeout = apply_filters( 'action_scheduler_failure_period', $time_limit ); |
|
112 | - if ( $timeout < 0 ) { |
|
113 | - return; |
|
114 | - } |
|
115 | - $cutoff = as_get_datetime_object($timeout.' seconds ago'); |
|
116 | - $actions_to_reset = $this->store->query_actions( array( |
|
117 | - 'status' => ActionScheduler_Store::STATUS_RUNNING, |
|
118 | - 'modified' => $cutoff, |
|
119 | - 'modified_compare' => '<=', |
|
120 | - 'per_page' => $this->get_batch_size(), |
|
121 | - ) ); |
|
122 | - |
|
123 | - foreach ( $actions_to_reset as $action_id ) { |
|
124 | - $this->store->mark_failure( $action_id ); |
|
125 | - do_action( 'action_scheduler_failed_action', $action_id, $timeout ); |
|
126 | - } |
|
127 | - } |
|
128 | - |
|
129 | - /** |
|
130 | - * Do all of the cleaning actions. |
|
131 | - * |
|
132 | - * @param int $time_limit The number of seconds to use as the timeout and failure period. Default 300 (5 minutes). |
|
133 | - * @author Jeremy Pry |
|
134 | - */ |
|
135 | - public function clean( $time_limit = 300 ) { |
|
136 | - $this->delete_old_actions(); |
|
137 | - $this->reset_timeouts( $time_limit ); |
|
138 | - $this->mark_failures( $time_limit ); |
|
139 | - } |
|
140 | - |
|
141 | - /** |
|
142 | - * Get the batch size for cleaning the queue. |
|
143 | - * |
|
144 | - * @author Jeremy Pry |
|
145 | - * @return int |
|
146 | - */ |
|
147 | - protected function get_batch_size() { |
|
148 | - /** |
|
149 | - * Filter the batch size when cleaning the queue. |
|
150 | - * |
|
151 | - * @param int $batch_size The number of actions to clean in one batch. |
|
152 | - */ |
|
153 | - return absint( apply_filters( 'action_scheduler_cleanup_batch_size', $this->batch_size ) ); |
|
154 | - } |
|
8 | + /** @var int */ |
|
9 | + protected $batch_size; |
|
10 | + |
|
11 | + /** @var ActionScheduler_Store */ |
|
12 | + private $store = null; |
|
13 | + |
|
14 | + /** |
|
15 | + * 31 days in seconds. |
|
16 | + * |
|
17 | + * @var int |
|
18 | + */ |
|
19 | + private $month_in_seconds = 2678400; |
|
20 | + |
|
21 | + /** |
|
22 | + * ActionScheduler_QueueCleaner constructor. |
|
23 | + * |
|
24 | + * @param ActionScheduler_Store $store The store instance. |
|
25 | + * @param int $batch_size The batch size. |
|
26 | + */ |
|
27 | + public function __construct( ActionScheduler_Store $store = null, $batch_size = 20 ) { |
|
28 | + $this->store = $store ? $store : ActionScheduler_Store::instance(); |
|
29 | + $this->batch_size = $batch_size; |
|
30 | + } |
|
31 | + |
|
32 | + public function delete_old_actions() { |
|
33 | + $lifespan = apply_filters( 'action_scheduler_retention_period', $this->month_in_seconds ); |
|
34 | + $cutoff = as_get_datetime_object($lifespan.' seconds ago'); |
|
35 | + |
|
36 | + $statuses_to_purge = array( |
|
37 | + ActionScheduler_Store::STATUS_COMPLETE, |
|
38 | + ActionScheduler_Store::STATUS_CANCELED, |
|
39 | + ); |
|
40 | + |
|
41 | + foreach ( $statuses_to_purge as $status ) { |
|
42 | + $actions_to_delete = $this->store->query_actions( array( |
|
43 | + 'status' => $status, |
|
44 | + 'modified' => $cutoff, |
|
45 | + 'modified_compare' => '<=', |
|
46 | + 'per_page' => $this->get_batch_size(), |
|
47 | + ) ); |
|
48 | + |
|
49 | + foreach ( $actions_to_delete as $action_id ) { |
|
50 | + try { |
|
51 | + $this->store->delete_action( $action_id ); |
|
52 | + } catch ( Exception $e ) { |
|
53 | + |
|
54 | + /** |
|
55 | + * Notify 3rd party code of exceptions when deleting a completed action older than the retention period |
|
56 | + * |
|
57 | + * This hook provides a way for 3rd party code to log or otherwise handle exceptions relating to their |
|
58 | + * actions. |
|
59 | + * |
|
60 | + * @since 2.0.0 |
|
61 | + * |
|
62 | + * @param int $action_id The scheduled actions ID in the data store |
|
63 | + * @param Exception $e The exception thrown when attempting to delete the action from the data store |
|
64 | + * @param int $lifespan The retention period, in seconds, for old actions |
|
65 | + * @param int $count_of_actions_to_delete The number of old actions being deleted in this batch |
|
66 | + */ |
|
67 | + do_action( 'action_scheduler_failed_old_action_deletion', $action_id, $e, $lifespan, count( $actions_to_delete ) ); |
|
68 | + } |
|
69 | + } |
|
70 | + } |
|
71 | + } |
|
72 | + |
|
73 | + /** |
|
74 | + * Unclaim pending actions that have not been run within a given time limit. |
|
75 | + * |
|
76 | + * When called by ActionScheduler_Abstract_QueueRunner::run_cleanup(), the time limit passed |
|
77 | + * as a parameter is 10x the time limit used for queue processing. |
|
78 | + * |
|
79 | + * @param int $time_limit The number of seconds to allow a queue to run before unclaiming its pending actions. Default 300 (5 minutes). |
|
80 | + */ |
|
81 | + public function reset_timeouts( $time_limit = 300 ) { |
|
82 | + $timeout = apply_filters( 'action_scheduler_timeout_period', $time_limit ); |
|
83 | + if ( $timeout < 0 ) { |
|
84 | + return; |
|
85 | + } |
|
86 | + $cutoff = as_get_datetime_object($timeout.' seconds ago'); |
|
87 | + $actions_to_reset = $this->store->query_actions( array( |
|
88 | + 'status' => ActionScheduler_Store::STATUS_PENDING, |
|
89 | + 'modified' => $cutoff, |
|
90 | + 'modified_compare' => '<=', |
|
91 | + 'claimed' => true, |
|
92 | + 'per_page' => $this->get_batch_size(), |
|
93 | + ) ); |
|
94 | + |
|
95 | + foreach ( $actions_to_reset as $action_id ) { |
|
96 | + $this->store->unclaim_action( $action_id ); |
|
97 | + do_action( 'action_scheduler_reset_action', $action_id ); |
|
98 | + } |
|
99 | + } |
|
100 | + |
|
101 | + /** |
|
102 | + * Mark actions that have been running for more than a given time limit as failed, based on |
|
103 | + * the assumption some uncatachable and unloggable fatal error occurred during processing. |
|
104 | + * |
|
105 | + * When called by ActionScheduler_Abstract_QueueRunner::run_cleanup(), the time limit passed |
|
106 | + * as a parameter is 10x the time limit used for queue processing. |
|
107 | + * |
|
108 | + * @param int $time_limit The number of seconds to allow an action to run before it is considered to have failed. Default 300 (5 minutes). |
|
109 | + */ |
|
110 | + public function mark_failures( $time_limit = 300 ) { |
|
111 | + $timeout = apply_filters( 'action_scheduler_failure_period', $time_limit ); |
|
112 | + if ( $timeout < 0 ) { |
|
113 | + return; |
|
114 | + } |
|
115 | + $cutoff = as_get_datetime_object($timeout.' seconds ago'); |
|
116 | + $actions_to_reset = $this->store->query_actions( array( |
|
117 | + 'status' => ActionScheduler_Store::STATUS_RUNNING, |
|
118 | + 'modified' => $cutoff, |
|
119 | + 'modified_compare' => '<=', |
|
120 | + 'per_page' => $this->get_batch_size(), |
|
121 | + ) ); |
|
122 | + |
|
123 | + foreach ( $actions_to_reset as $action_id ) { |
|
124 | + $this->store->mark_failure( $action_id ); |
|
125 | + do_action( 'action_scheduler_failed_action', $action_id, $timeout ); |
|
126 | + } |
|
127 | + } |
|
128 | + |
|
129 | + /** |
|
130 | + * Do all of the cleaning actions. |
|
131 | + * |
|
132 | + * @param int $time_limit The number of seconds to use as the timeout and failure period. Default 300 (5 minutes). |
|
133 | + * @author Jeremy Pry |
|
134 | + */ |
|
135 | + public function clean( $time_limit = 300 ) { |
|
136 | + $this->delete_old_actions(); |
|
137 | + $this->reset_timeouts( $time_limit ); |
|
138 | + $this->mark_failures( $time_limit ); |
|
139 | + } |
|
140 | + |
|
141 | + /** |
|
142 | + * Get the batch size for cleaning the queue. |
|
143 | + * |
|
144 | + * @author Jeremy Pry |
|
145 | + * @return int |
|
146 | + */ |
|
147 | + protected function get_batch_size() { |
|
148 | + /** |
|
149 | + * Filter the batch size when cleaning the queue. |
|
150 | + * |
|
151 | + * @param int $batch_size The number of actions to clean in one batch. |
|
152 | + */ |
|
153 | + return absint( apply_filters( 'action_scheduler_cleanup_batch_size', $this->batch_size ) ); |
|
154 | + } |
|
155 | 155 | } |
@@ -9,41 +9,41 @@ |
||
9 | 9 | */ |
10 | 10 | class ActionScheduler_OptionLock extends ActionScheduler_Lock { |
11 | 11 | |
12 | - /** |
|
13 | - * Set a lock using options for a given amount of time (60 seconds by default). |
|
14 | - * |
|
15 | - * Using an autoloaded option avoids running database queries or other resource intensive tasks |
|
16 | - * on frequently triggered hooks, like 'init' or 'shutdown'. |
|
17 | - * |
|
18 | - * For example, ActionScheduler_QueueRunner->maybe_dispatch_async_request() uses a lock to avoid |
|
19 | - * calling ActionScheduler_QueueRunner->has_maximum_concurrent_batches() every time the 'shutdown', |
|
20 | - * hook is triggered, because that method calls ActionScheduler_QueueRunner->store->get_claim_count() |
|
21 | - * to find the current number of claims in the database. |
|
22 | - * |
|
23 | - * @param string $lock_type A string to identify different lock types. |
|
24 | - * @bool True if lock value has changed, false if not or if set failed. |
|
25 | - */ |
|
26 | - public function set( $lock_type ) { |
|
27 | - return update_option( $this->get_key( $lock_type ), time() + $this->get_duration( $lock_type ) ); |
|
28 | - } |
|
12 | + /** |
|
13 | + * Set a lock using options for a given amount of time (60 seconds by default). |
|
14 | + * |
|
15 | + * Using an autoloaded option avoids running database queries or other resource intensive tasks |
|
16 | + * on frequently triggered hooks, like 'init' or 'shutdown'. |
|
17 | + * |
|
18 | + * For example, ActionScheduler_QueueRunner->maybe_dispatch_async_request() uses a lock to avoid |
|
19 | + * calling ActionScheduler_QueueRunner->has_maximum_concurrent_batches() every time the 'shutdown', |
|
20 | + * hook is triggered, because that method calls ActionScheduler_QueueRunner->store->get_claim_count() |
|
21 | + * to find the current number of claims in the database. |
|
22 | + * |
|
23 | + * @param string $lock_type A string to identify different lock types. |
|
24 | + * @bool True if lock value has changed, false if not or if set failed. |
|
25 | + */ |
|
26 | + public function set( $lock_type ) { |
|
27 | + return update_option( $this->get_key( $lock_type ), time() + $this->get_duration( $lock_type ) ); |
|
28 | + } |
|
29 | 29 | |
30 | - /** |
|
31 | - * If a lock is set, return the timestamp it was set to expiry. |
|
32 | - * |
|
33 | - * @param string $lock_type A string to identify different lock types. |
|
34 | - * @return bool|int False if no lock is set, otherwise the timestamp for when the lock is set to expire. |
|
35 | - */ |
|
36 | - public function get_expiration( $lock_type ) { |
|
37 | - return get_option( $this->get_key( $lock_type ) ); |
|
38 | - } |
|
30 | + /** |
|
31 | + * If a lock is set, return the timestamp it was set to expiry. |
|
32 | + * |
|
33 | + * @param string $lock_type A string to identify different lock types. |
|
34 | + * @return bool|int False if no lock is set, otherwise the timestamp for when the lock is set to expire. |
|
35 | + */ |
|
36 | + public function get_expiration( $lock_type ) { |
|
37 | + return get_option( $this->get_key( $lock_type ) ); |
|
38 | + } |
|
39 | 39 | |
40 | - /** |
|
41 | - * Get the key to use for storing the lock in the transient |
|
42 | - * |
|
43 | - * @param string $lock_type A string to identify different lock types. |
|
44 | - * @return string |
|
45 | - */ |
|
46 | - protected function get_key( $lock_type ) { |
|
47 | - return sprintf( 'action_scheduler_lock_%s', $lock_type ); |
|
48 | - } |
|
40 | + /** |
|
41 | + * Get the key to use for storing the lock in the transient |
|
42 | + * |
|
43 | + * @param string $lock_type A string to identify different lock types. |
|
44 | + * @return string |
|
45 | + */ |
|
46 | + protected function get_key( $lock_type ) { |
|
47 | + return sprintf( 'action_scheduler_lock_%s', $lock_type ); |
|
48 | + } |
|
49 | 49 | } |
@@ -4,20 +4,20 @@ |
||
4 | 4 | * Class ActionScheduler_ActionClaim |
5 | 5 | */ |
6 | 6 | class ActionScheduler_ActionClaim { |
7 | - private $id = ''; |
|
8 | - private $action_ids = array(); |
|
7 | + private $id = ''; |
|
8 | + private $action_ids = array(); |
|
9 | 9 | |
10 | - public function __construct( $id, array $action_ids ) { |
|
11 | - $this->id = $id; |
|
12 | - $this->action_ids = $action_ids; |
|
13 | - } |
|
10 | + public function __construct( $id, array $action_ids ) { |
|
11 | + $this->id = $id; |
|
12 | + $this->action_ids = $action_ids; |
|
13 | + } |
|
14 | 14 | |
15 | - public function get_id() { |
|
16 | - return $this->id; |
|
17 | - } |
|
15 | + public function get_id() { |
|
16 | + return $this->id; |
|
17 | + } |
|
18 | 18 | |
19 | - public function get_actions() { |
|
20 | - return $this->action_ids; |
|
21 | - } |
|
19 | + public function get_actions() { |
|
20 | + return $this->action_ids; |
|
21 | + } |
|
22 | 22 | } |
23 | - |
|
24 | 23 | \ No newline at end of file |
24 | + |
|
25 | 25 | \ No newline at end of file |
@@ -4,195 +4,195 @@ |
||
4 | 4 | * Class ActionScheduler_QueueRunner |
5 | 5 | */ |
6 | 6 | class ActionScheduler_QueueRunner extends ActionScheduler_Abstract_QueueRunner { |
7 | - const WP_CRON_HOOK = 'action_scheduler_run_queue'; |
|
8 | - |
|
9 | - const WP_CRON_SCHEDULE = 'every_minute'; |
|
10 | - |
|
11 | - /** @var ActionScheduler_AsyncRequest_QueueRunner */ |
|
12 | - protected $async_request; |
|
13 | - |
|
14 | - /** @var ActionScheduler_QueueRunner */ |
|
15 | - private static $runner = null; |
|
16 | - |
|
17 | - /** |
|
18 | - * @return ActionScheduler_QueueRunner |
|
19 | - * @codeCoverageIgnore |
|
20 | - */ |
|
21 | - public static function instance() { |
|
22 | - if ( empty(self::$runner) ) { |
|
23 | - $class = apply_filters('action_scheduler_queue_runner_class', 'ActionScheduler_QueueRunner'); |
|
24 | - self::$runner = new $class(); |
|
25 | - } |
|
26 | - return self::$runner; |
|
27 | - } |
|
28 | - |
|
29 | - /** |
|
30 | - * ActionScheduler_QueueRunner constructor. |
|
31 | - * |
|
32 | - * @param ActionScheduler_Store $store |
|
33 | - * @param ActionScheduler_FatalErrorMonitor $monitor |
|
34 | - * @param ActionScheduler_QueueCleaner $cleaner |
|
35 | - */ |
|
36 | - public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null, ActionScheduler_AsyncRequest_QueueRunner $async_request = null ) { |
|
37 | - parent::__construct( $store, $monitor, $cleaner ); |
|
38 | - |
|
39 | - if ( is_null( $async_request ) ) { |
|
40 | - $async_request = new ActionScheduler_AsyncRequest_QueueRunner( $this->store ); |
|
41 | - } |
|
42 | - |
|
43 | - $this->async_request = $async_request; |
|
44 | - } |
|
45 | - |
|
46 | - /** |
|
47 | - * @codeCoverageIgnore |
|
48 | - */ |
|
49 | - public function init() { |
|
50 | - |
|
51 | - add_filter( 'cron_schedules', array( self::instance(), 'add_wp_cron_schedule' ) ); |
|
52 | - |
|
53 | - $cron_context = array( 'WP Cron' ); |
|
54 | - |
|
55 | - if ( ! wp_next_scheduled( self::WP_CRON_HOOK, $cron_context ) ) { |
|
56 | - |
|
57 | - // Check for and remove any WP Cron hook scheduled by Action Scheduler < 3.0.0, which didn't include the $context param |
|
58 | - $next_timestamp = wp_next_scheduled( self::WP_CRON_HOOK ); |
|
59 | - if ( $next_timestamp ) { |
|
60 | - wp_unschedule_event( $next_timestamp, self::WP_CRON_HOOK ); |
|
61 | - } |
|
62 | - |
|
63 | - $schedule = apply_filters( 'action_scheduler_run_schedule', self::WP_CRON_SCHEDULE ); |
|
64 | - wp_schedule_event( time(), $schedule, self::WP_CRON_HOOK, $cron_context ); |
|
65 | - } |
|
66 | - |
|
67 | - add_action( self::WP_CRON_HOOK, array( self::instance(), 'run' ) ); |
|
68 | - $this->hook_dispatch_async_request(); |
|
69 | - } |
|
70 | - |
|
71 | - /** |
|
72 | - * Hook check for dispatching an async request. |
|
73 | - */ |
|
74 | - public function hook_dispatch_async_request() { |
|
75 | - add_action( 'shutdown', array( $this, 'maybe_dispatch_async_request' ) ); |
|
76 | - } |
|
77 | - |
|
78 | - /** |
|
79 | - * Unhook check for dispatching an async request. |
|
80 | - */ |
|
81 | - public function unhook_dispatch_async_request() { |
|
82 | - remove_action( 'shutdown', array( $this, 'maybe_dispatch_async_request' ) ); |
|
83 | - } |
|
84 | - |
|
85 | - /** |
|
86 | - * Check if we should dispatch an async request to process actions. |
|
87 | - * |
|
88 | - * This method is attached to 'shutdown', so is called frequently. To avoid slowing down |
|
89 | - * the site, it mitigates the work performed in each request by: |
|
90 | - * 1. checking if it's in the admin context and then |
|
91 | - * 2. haven't run on the 'shutdown' hook within the lock time (60 seconds by default) |
|
92 | - * 3. haven't exceeded the number of allowed batches. |
|
93 | - * |
|
94 | - * The order of these checks is important, because they run from a check on a value: |
|
95 | - * 1. in memory - is_admin() maps to $GLOBALS or the WP_ADMIN constant |
|
96 | - * 2. in memory - transients use autoloaded options by default |
|
97 | - * 3. from a database query - has_maximum_concurrent_batches() run the query |
|
98 | - * $this->store->get_claim_count() to find the current number of claims in the DB. |
|
99 | - * |
|
100 | - * If all of these conditions are met, then we request an async runner check whether it |
|
101 | - * should dispatch a request to process pending actions. |
|
102 | - */ |
|
103 | - public function maybe_dispatch_async_request() { |
|
104 | - if ( is_admin() && ! ActionScheduler::lock()->is_locked( 'async-request-runner' ) ) { |
|
105 | - // Only start an async queue at most once every 60 seconds |
|
106 | - ActionScheduler::lock()->set( 'async-request-runner' ); |
|
107 | - $this->async_request->maybe_dispatch(); |
|
108 | - } |
|
109 | - } |
|
110 | - |
|
111 | - /** |
|
112 | - * Process actions in the queue. Attached to self::WP_CRON_HOOK i.e. 'action_scheduler_run_queue' |
|
113 | - * |
|
114 | - * The $context param of this method defaults to 'WP Cron', because prior to Action Scheduler 3.0.0 |
|
115 | - * that was the only context in which this method was run, and the self::WP_CRON_HOOK hook had no context |
|
116 | - * passed along with it. New code calling this method directly, or by triggering the self::WP_CRON_HOOK, |
|
117 | - * should set a context as the first parameter. For an example of this, refer to the code seen in |
|
118 | - * @see ActionScheduler_AsyncRequest_QueueRunner::handle() |
|
119 | - * |
|
120 | - * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron' |
|
121 | - * Generally, this should be capitalised and not localised as it's a proper noun. |
|
122 | - * @return int The number of actions processed. |
|
123 | - */ |
|
124 | - public function run( $context = 'WP Cron' ) { |
|
125 | - ActionScheduler_Compatibility::raise_memory_limit(); |
|
126 | - ActionScheduler_Compatibility::raise_time_limit( $this->get_time_limit() ); |
|
127 | - do_action( 'action_scheduler_before_process_queue' ); |
|
128 | - $this->run_cleanup(); |
|
129 | - $processed_actions = 0; |
|
130 | - if ( false === $this->has_maximum_concurrent_batches() ) { |
|
131 | - $batch_size = apply_filters( 'action_scheduler_queue_runner_batch_size', 25 ); |
|
132 | - do { |
|
133 | - $processed_actions_in_batch = $this->do_batch( $batch_size, $context ); |
|
134 | - $processed_actions += $processed_actions_in_batch; |
|
135 | - } while ( $processed_actions_in_batch > 0 && ! $this->batch_limits_exceeded( $processed_actions ) ); // keep going until we run out of actions, time, or memory |
|
136 | - } |
|
137 | - |
|
138 | - do_action( 'action_scheduler_after_process_queue' ); |
|
139 | - return $processed_actions; |
|
140 | - } |
|
141 | - |
|
142 | - /** |
|
143 | - * Process a batch of actions pending in the queue. |
|
144 | - * |
|
145 | - * Actions are processed by claiming a set of pending actions then processing each one until either the batch |
|
146 | - * size is completed, or memory or time limits are reached, defined by @see $this->batch_limits_exceeded(). |
|
147 | - * |
|
148 | - * @param int $size The maximum number of actions to process in the batch. |
|
149 | - * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron' |
|
150 | - * Generally, this should be capitalised and not localised as it's a proper noun. |
|
151 | - * @return int The number of actions processed. |
|
152 | - */ |
|
153 | - protected function do_batch( $size = 100, $context = '' ) { |
|
154 | - $claim = $this->store->stake_claim($size); |
|
155 | - $this->monitor->attach($claim); |
|
156 | - $processed_actions = 0; |
|
157 | - |
|
158 | - foreach ( $claim->get_actions() as $action_id ) { |
|
159 | - // bail if we lost the claim |
|
160 | - if ( ! in_array( $action_id, $this->store->find_actions_by_claim_id( $claim->get_id() ) ) ) { |
|
161 | - break; |
|
162 | - } |
|
163 | - $this->process_action( $action_id, $context ); |
|
164 | - $processed_actions++; |
|
165 | - |
|
166 | - if ( $this->batch_limits_exceeded( $processed_actions ) ) { |
|
167 | - break; |
|
168 | - } |
|
169 | - } |
|
170 | - $this->store->release_claim($claim); |
|
171 | - $this->monitor->detach(); |
|
172 | - $this->clear_caches(); |
|
173 | - return $processed_actions; |
|
174 | - } |
|
175 | - |
|
176 | - /** |
|
177 | - * Running large batches can eat up memory, as WP adds data to its object cache. |
|
178 | - * |
|
179 | - * If using a persistent object store, this has the side effect of flushing that |
|
180 | - * as well, so this is disabled by default. To enable: |
|
181 | - * |
|
182 | - * add_filter( 'action_scheduler_queue_runner_flush_cache', '__return_true' ); |
|
183 | - */ |
|
184 | - protected function clear_caches() { |
|
185 | - if ( ! wp_using_ext_object_cache() || apply_filters( 'action_scheduler_queue_runner_flush_cache', false ) ) { |
|
186 | - wp_cache_flush(); |
|
187 | - } |
|
188 | - } |
|
189 | - |
|
190 | - public function add_wp_cron_schedule( $schedules ) { |
|
191 | - $schedules['every_minute'] = array( |
|
192 | - 'interval' => 60, // in seconds |
|
193 | - 'display' => __( 'Every minute', 'action-scheduler' ), |
|
194 | - ); |
|
195 | - |
|
196 | - return $schedules; |
|
197 | - } |
|
7 | + const WP_CRON_HOOK = 'action_scheduler_run_queue'; |
|
8 | + |
|
9 | + const WP_CRON_SCHEDULE = 'every_minute'; |
|
10 | + |
|
11 | + /** @var ActionScheduler_AsyncRequest_QueueRunner */ |
|
12 | + protected $async_request; |
|
13 | + |
|
14 | + /** @var ActionScheduler_QueueRunner */ |
|
15 | + private static $runner = null; |
|
16 | + |
|
17 | + /** |
|
18 | + * @return ActionScheduler_QueueRunner |
|
19 | + * @codeCoverageIgnore |
|
20 | + */ |
|
21 | + public static function instance() { |
|
22 | + if ( empty(self::$runner) ) { |
|
23 | + $class = apply_filters('action_scheduler_queue_runner_class', 'ActionScheduler_QueueRunner'); |
|
24 | + self::$runner = new $class(); |
|
25 | + } |
|
26 | + return self::$runner; |
|
27 | + } |
|
28 | + |
|
29 | + /** |
|
30 | + * ActionScheduler_QueueRunner constructor. |
|
31 | + * |
|
32 | + * @param ActionScheduler_Store $store |
|
33 | + * @param ActionScheduler_FatalErrorMonitor $monitor |
|
34 | + * @param ActionScheduler_QueueCleaner $cleaner |
|
35 | + */ |
|
36 | + public function __construct( ActionScheduler_Store $store = null, ActionScheduler_FatalErrorMonitor $monitor = null, ActionScheduler_QueueCleaner $cleaner = null, ActionScheduler_AsyncRequest_QueueRunner $async_request = null ) { |
|
37 | + parent::__construct( $store, $monitor, $cleaner ); |
|
38 | + |
|
39 | + if ( is_null( $async_request ) ) { |
|
40 | + $async_request = new ActionScheduler_AsyncRequest_QueueRunner( $this->store ); |
|
41 | + } |
|
42 | + |
|
43 | + $this->async_request = $async_request; |
|
44 | + } |
|
45 | + |
|
46 | + /** |
|
47 | + * @codeCoverageIgnore |
|
48 | + */ |
|
49 | + public function init() { |
|
50 | + |
|
51 | + add_filter( 'cron_schedules', array( self::instance(), 'add_wp_cron_schedule' ) ); |
|
52 | + |
|
53 | + $cron_context = array( 'WP Cron' ); |
|
54 | + |
|
55 | + if ( ! wp_next_scheduled( self::WP_CRON_HOOK, $cron_context ) ) { |
|
56 | + |
|
57 | + // Check for and remove any WP Cron hook scheduled by Action Scheduler < 3.0.0, which didn't include the $context param |
|
58 | + $next_timestamp = wp_next_scheduled( self::WP_CRON_HOOK ); |
|
59 | + if ( $next_timestamp ) { |
|
60 | + wp_unschedule_event( $next_timestamp, self::WP_CRON_HOOK ); |
|
61 | + } |
|
62 | + |
|
63 | + $schedule = apply_filters( 'action_scheduler_run_schedule', self::WP_CRON_SCHEDULE ); |
|
64 | + wp_schedule_event( time(), $schedule, self::WP_CRON_HOOK, $cron_context ); |
|
65 | + } |
|
66 | + |
|
67 | + add_action( self::WP_CRON_HOOK, array( self::instance(), 'run' ) ); |
|
68 | + $this->hook_dispatch_async_request(); |
|
69 | + } |
|
70 | + |
|
71 | + /** |
|
72 | + * Hook check for dispatching an async request. |
|
73 | + */ |
|
74 | + public function hook_dispatch_async_request() { |
|
75 | + add_action( 'shutdown', array( $this, 'maybe_dispatch_async_request' ) ); |
|
76 | + } |
|
77 | + |
|
78 | + /** |
|
79 | + * Unhook check for dispatching an async request. |
|
80 | + */ |
|
81 | + public function unhook_dispatch_async_request() { |
|
82 | + remove_action( 'shutdown', array( $this, 'maybe_dispatch_async_request' ) ); |
|
83 | + } |
|
84 | + |
|
85 | + /** |
|
86 | + * Check if we should dispatch an async request to process actions. |
|
87 | + * |
|
88 | + * This method is attached to 'shutdown', so is called frequently. To avoid slowing down |
|
89 | + * the site, it mitigates the work performed in each request by: |
|
90 | + * 1. checking if it's in the admin context and then |
|
91 | + * 2. haven't run on the 'shutdown' hook within the lock time (60 seconds by default) |
|
92 | + * 3. haven't exceeded the number of allowed batches. |
|
93 | + * |
|
94 | + * The order of these checks is important, because they run from a check on a value: |
|
95 | + * 1. in memory - is_admin() maps to $GLOBALS or the WP_ADMIN constant |
|
96 | + * 2. in memory - transients use autoloaded options by default |
|
97 | + * 3. from a database query - has_maximum_concurrent_batches() run the query |
|
98 | + * $this->store->get_claim_count() to find the current number of claims in the DB. |
|
99 | + * |
|
100 | + * If all of these conditions are met, then we request an async runner check whether it |
|
101 | + * should dispatch a request to process pending actions. |
|
102 | + */ |
|
103 | + public function maybe_dispatch_async_request() { |
|
104 | + if ( is_admin() && ! ActionScheduler::lock()->is_locked( 'async-request-runner' ) ) { |
|
105 | + // Only start an async queue at most once every 60 seconds |
|
106 | + ActionScheduler::lock()->set( 'async-request-runner' ); |
|
107 | + $this->async_request->maybe_dispatch(); |
|
108 | + } |
|
109 | + } |
|
110 | + |
|
111 | + /** |
|
112 | + * Process actions in the queue. Attached to self::WP_CRON_HOOK i.e. 'action_scheduler_run_queue' |
|
113 | + * |
|
114 | + * The $context param of this method defaults to 'WP Cron', because prior to Action Scheduler 3.0.0 |
|
115 | + * that was the only context in which this method was run, and the self::WP_CRON_HOOK hook had no context |
|
116 | + * passed along with it. New code calling this method directly, or by triggering the self::WP_CRON_HOOK, |
|
117 | + * should set a context as the first parameter. For an example of this, refer to the code seen in |
|
118 | + * @see ActionScheduler_AsyncRequest_QueueRunner::handle() |
|
119 | + * |
|
120 | + * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron' |
|
121 | + * Generally, this should be capitalised and not localised as it's a proper noun. |
|
122 | + * @return int The number of actions processed. |
|
123 | + */ |
|
124 | + public function run( $context = 'WP Cron' ) { |
|
125 | + ActionScheduler_Compatibility::raise_memory_limit(); |
|
126 | + ActionScheduler_Compatibility::raise_time_limit( $this->get_time_limit() ); |
|
127 | + do_action( 'action_scheduler_before_process_queue' ); |
|
128 | + $this->run_cleanup(); |
|
129 | + $processed_actions = 0; |
|
130 | + if ( false === $this->has_maximum_concurrent_batches() ) { |
|
131 | + $batch_size = apply_filters( 'action_scheduler_queue_runner_batch_size', 25 ); |
|
132 | + do { |
|
133 | + $processed_actions_in_batch = $this->do_batch( $batch_size, $context ); |
|
134 | + $processed_actions += $processed_actions_in_batch; |
|
135 | + } while ( $processed_actions_in_batch > 0 && ! $this->batch_limits_exceeded( $processed_actions ) ); // keep going until we run out of actions, time, or memory |
|
136 | + } |
|
137 | + |
|
138 | + do_action( 'action_scheduler_after_process_queue' ); |
|
139 | + return $processed_actions; |
|
140 | + } |
|
141 | + |
|
142 | + /** |
|
143 | + * Process a batch of actions pending in the queue. |
|
144 | + * |
|
145 | + * Actions are processed by claiming a set of pending actions then processing each one until either the batch |
|
146 | + * size is completed, or memory or time limits are reached, defined by @see $this->batch_limits_exceeded(). |
|
147 | + * |
|
148 | + * @param int $size The maximum number of actions to process in the batch. |
|
149 | + * @param string $context Optional identifer for the context in which this action is being processed, e.g. 'WP CLI' or 'WP Cron' |
|
150 | + * Generally, this should be capitalised and not localised as it's a proper noun. |
|
151 | + * @return int The number of actions processed. |
|
152 | + */ |
|
153 | + protected function do_batch( $size = 100, $context = '' ) { |
|
154 | + $claim = $this->store->stake_claim($size); |
|
155 | + $this->monitor->attach($claim); |
|
156 | + $processed_actions = 0; |
|
157 | + |
|
158 | + foreach ( $claim->get_actions() as $action_id ) { |
|
159 | + // bail if we lost the claim |
|
160 | + if ( ! in_array( $action_id, $this->store->find_actions_by_claim_id( $claim->get_id() ) ) ) { |
|
161 | + break; |
|
162 | + } |
|
163 | + $this->process_action( $action_id, $context ); |
|
164 | + $processed_actions++; |
|
165 | + |
|
166 | + if ( $this->batch_limits_exceeded( $processed_actions ) ) { |
|
167 | + break; |
|
168 | + } |
|
169 | + } |
|
170 | + $this->store->release_claim($claim); |
|
171 | + $this->monitor->detach(); |
|
172 | + $this->clear_caches(); |
|
173 | + return $processed_actions; |
|
174 | + } |
|
175 | + |
|
176 | + /** |
|
177 | + * Running large batches can eat up memory, as WP adds data to its object cache. |
|
178 | + * |
|
179 | + * If using a persistent object store, this has the side effect of flushing that |
|
180 | + * as well, so this is disabled by default. To enable: |
|
181 | + * |
|
182 | + * add_filter( 'action_scheduler_queue_runner_flush_cache', '__return_true' ); |
|
183 | + */ |
|
184 | + protected function clear_caches() { |
|
185 | + if ( ! wp_using_ext_object_cache() || apply_filters( 'action_scheduler_queue_runner_flush_cache', false ) ) { |
|
186 | + wp_cache_flush(); |
|
187 | + } |
|
188 | + } |
|
189 | + |
|
190 | + public function add_wp_cron_schedule( $schedules ) { |
|
191 | + $schedules['every_minute'] = array( |
|
192 | + 'interval' => 60, // in seconds |
|
193 | + 'display' => __( 'Every minute', 'action-scheduler' ), |
|
194 | + ); |
|
195 | + |
|
196 | + return $schedules; |
|
197 | + } |
|
198 | 198 | } |
@@ -10,88 +10,88 @@ |
||
10 | 10 | */ |
11 | 11 | class ActionScheduler_AsyncRequest_QueueRunner extends WP_Async_Request { |
12 | 12 | |
13 | - /** |
|
14 | - * Data store for querying actions |
|
15 | - * |
|
16 | - * @var ActionScheduler_Store |
|
17 | - * @access protected |
|
18 | - */ |
|
19 | - protected $store; |
|
20 | - |
|
21 | - /** |
|
22 | - * Prefix for ajax hooks |
|
23 | - * |
|
24 | - * @var string |
|
25 | - * @access protected |
|
26 | - */ |
|
27 | - protected $prefix = 'as'; |
|
28 | - |
|
29 | - /** |
|
30 | - * Action for ajax hooks |
|
31 | - * |
|
32 | - * @var string |
|
33 | - * @access protected |
|
34 | - */ |
|
35 | - protected $action = 'async_request_queue_runner'; |
|
36 | - |
|
37 | - /** |
|
38 | - * Initiate new async request |
|
39 | - */ |
|
40 | - public function __construct( ActionScheduler_Store $store ) { |
|
41 | - parent::__construct(); |
|
42 | - $this->store = $store; |
|
43 | - } |
|
44 | - |
|
45 | - /** |
|
46 | - * Handle async requests |
|
47 | - * |
|
48 | - * Run a queue, and maybe dispatch another async request to run another queue |
|
49 | - * if there are still pending actions after completing a queue in this request. |
|
50 | - */ |
|
51 | - protected function handle() { |
|
52 | - do_action( 'action_scheduler_run_queue', 'Async Request' ); // run a queue in the same way as WP Cron, but declare the Async Request context |
|
53 | - |
|
54 | - $sleep_seconds = $this->get_sleep_seconds(); |
|
55 | - |
|
56 | - if ( $sleep_seconds ) { |
|
57 | - sleep( $sleep_seconds ); |
|
58 | - } |
|
59 | - |
|
60 | - $this->maybe_dispatch(); |
|
61 | - } |
|
62 | - |
|
63 | - /** |
|
64 | - * If the async request runner is needed and allowed to run, dispatch a request. |
|
65 | - */ |
|
66 | - public function maybe_dispatch() { |
|
67 | - if ( ! $this->allow() ) { |
|
68 | - return; |
|
69 | - } |
|
70 | - |
|
71 | - $this->dispatch(); |
|
72 | - ActionScheduler_QueueRunner::instance()->unhook_dispatch_async_request(); |
|
73 | - } |
|
74 | - |
|
75 | - /** |
|
76 | - * Only allow async requests when needed. |
|
77 | - * |
|
78 | - * Also allow 3rd party code to disable running actions via async requests. |
|
79 | - */ |
|
80 | - protected function allow() { |
|
81 | - |
|
82 | - if ( ! has_action( 'action_scheduler_run_queue' ) || ActionScheduler::runner()->has_maximum_concurrent_batches() || ! $this->store->has_pending_actions_due() ) { |
|
83 | - $allow = false; |
|
84 | - } else { |
|
85 | - $allow = true; |
|
86 | - } |
|
87 | - |
|
88 | - return apply_filters( 'action_scheduler_allow_async_request_runner', $allow ); |
|
89 | - } |
|
90 | - |
|
91 | - /** |
|
92 | - * Chaining async requests can crash MySQL. A brief sleep call in PHP prevents that. |
|
93 | - */ |
|
94 | - protected function get_sleep_seconds() { |
|
95 | - return apply_filters( 'action_scheduler_async_request_sleep_seconds', 5, $this ); |
|
96 | - } |
|
13 | + /** |
|
14 | + * Data store for querying actions |
|
15 | + * |
|
16 | + * @var ActionScheduler_Store |
|
17 | + * @access protected |
|
18 | + */ |
|
19 | + protected $store; |
|
20 | + |
|
21 | + /** |
|
22 | + * Prefix for ajax hooks |
|
23 | + * |
|
24 | + * @var string |
|
25 | + * @access protected |
|
26 | + */ |
|
27 | + protected $prefix = 'as'; |
|
28 | + |
|
29 | + /** |
|
30 | + * Action for ajax hooks |
|
31 | + * |
|
32 | + * @var string |
|
33 | + * @access protected |
|
34 | + */ |
|
35 | + protected $action = 'async_request_queue_runner'; |
|
36 | + |
|
37 | + /** |
|
38 | + * Initiate new async request |
|
39 | + */ |
|
40 | + public function __construct( ActionScheduler_Store $store ) { |
|
41 | + parent::__construct(); |
|
42 | + $this->store = $store; |
|
43 | + } |
|
44 | + |
|
45 | + /** |
|
46 | + * Handle async requests |
|
47 | + * |
|
48 | + * Run a queue, and maybe dispatch another async request to run another queue |
|
49 | + * if there are still pending actions after completing a queue in this request. |
|
50 | + */ |
|
51 | + protected function handle() { |
|
52 | + do_action( 'action_scheduler_run_queue', 'Async Request' ); // run a queue in the same way as WP Cron, but declare the Async Request context |
|
53 | + |
|
54 | + $sleep_seconds = $this->get_sleep_seconds(); |
|
55 | + |
|
56 | + if ( $sleep_seconds ) { |
|
57 | + sleep( $sleep_seconds ); |
|
58 | + } |
|
59 | + |
|
60 | + $this->maybe_dispatch(); |
|
61 | + } |
|
62 | + |
|
63 | + /** |
|
64 | + * If the async request runner is needed and allowed to run, dispatch a request. |
|
65 | + */ |
|
66 | + public function maybe_dispatch() { |
|
67 | + if ( ! $this->allow() ) { |
|
68 | + return; |
|
69 | + } |
|
70 | + |
|
71 | + $this->dispatch(); |
|
72 | + ActionScheduler_QueueRunner::instance()->unhook_dispatch_async_request(); |
|
73 | + } |
|
74 | + |
|
75 | + /** |
|
76 | + * Only allow async requests when needed. |
|
77 | + * |
|
78 | + * Also allow 3rd party code to disable running actions via async requests. |
|
79 | + */ |
|
80 | + protected function allow() { |
|
81 | + |
|
82 | + if ( ! has_action( 'action_scheduler_run_queue' ) || ActionScheduler::runner()->has_maximum_concurrent_batches() || ! $this->store->has_pending_actions_due() ) { |
|
83 | + $allow = false; |
|
84 | + } else { |
|
85 | + $allow = true; |
|
86 | + } |
|
87 | + |
|
88 | + return apply_filters( 'action_scheduler_allow_async_request_runner', $allow ); |
|
89 | + } |
|
90 | + |
|
91 | + /** |
|
92 | + * Chaining async requests can crash MySQL. A brief sleep call in PHP prevents that. |
|
93 | + */ |
|
94 | + protected function get_sleep_seconds() { |
|
95 | + return apply_filters( 'action_scheduler_async_request_sleep_seconds', 5, $this ); |
|
96 | + } |
|
97 | 97 | } |
@@ -7,109 +7,109 @@ |
||
7 | 7 | */ |
8 | 8 | class ActionScheduler_WPCommentCleaner { |
9 | 9 | |
10 | - /** |
|
11 | - * Post migration hook used to cleanup the WP comment table. |
|
12 | - * |
|
13 | - * @var string |
|
14 | - */ |
|
15 | - protected static $cleanup_hook = 'action_scheduler/cleanup_wp_comment_logs'; |
|
16 | - |
|
17 | - /** |
|
18 | - * An instance of the ActionScheduler_wpCommentLogger class to interact with the comments table. |
|
19 | - * |
|
20 | - * This instance should only be used as an interface. It should not be initialized. |
|
21 | - * |
|
22 | - * @var ActionScheduler_wpCommentLogger |
|
23 | - */ |
|
24 | - protected static $wp_comment_logger = null; |
|
25 | - |
|
26 | - /** |
|
27 | - * The key used to store the cached value of whether there are logs in the WP comment table. |
|
28 | - * |
|
29 | - * @var string |
|
30 | - */ |
|
31 | - protected static $has_logs_option_key = 'as_has_wp_comment_logs'; |
|
32 | - |
|
33 | - /** |
|
34 | - * Initialize the class and attach callbacks. |
|
35 | - */ |
|
36 | - public static function init() { |
|
37 | - if ( empty( self::$wp_comment_logger ) ) { |
|
38 | - self::$wp_comment_logger = new ActionScheduler_wpCommentLogger(); |
|
39 | - } |
|
40 | - |
|
41 | - add_action( self::$cleanup_hook, array( __CLASS__, 'delete_all_action_comments' ) ); |
|
42 | - |
|
43 | - // While there are orphaned logs left in the comments table, we need to attach the callbacks which filter comment counts. |
|
44 | - add_action( 'pre_get_comments', array( self::$wp_comment_logger, 'filter_comment_queries' ), 10, 1 ); |
|
45 | - 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 |
|
46 | - add_action( 'comment_feed_where', array( self::$wp_comment_logger, 'filter_comment_feed' ), 10, 2 ); |
|
47 | - |
|
48 | - // Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen |
|
49 | - add_action( 'load-tools_page_action-scheduler', array( __CLASS__, 'register_admin_notice' ) ); |
|
50 | - add_action( 'load-woocommerce_page_wc-status', array( __CLASS__, 'register_admin_notice' ) ); |
|
51 | - } |
|
52 | - |
|
53 | - /** |
|
54 | - * Determines if there are log entries in the wp comments table. |
|
55 | - * |
|
56 | - * Uses the flag set on migration completion set by @see self::maybe_schedule_cleanup(). |
|
57 | - * |
|
58 | - * @return boolean Whether there are scheduled action comments in the comments table. |
|
59 | - */ |
|
60 | - public static function has_logs() { |
|
61 | - return 'yes' === get_option( self::$has_logs_option_key ); |
|
62 | - } |
|
63 | - |
|
64 | - /** |
|
65 | - * Schedules the WP Post comment table cleanup to run in 6 months if it's not already scheduled. |
|
66 | - * Attached to the migration complete hook 'action_scheduler/migration_complete'. |
|
67 | - */ |
|
68 | - public static function maybe_schedule_cleanup() { |
|
69 | - if ( (bool) get_comments( array( 'type' => ActionScheduler_wpCommentLogger::TYPE, 'number' => 1, 'fields' => 'ids' ) ) ) { |
|
70 | - update_option( self::$has_logs_option_key, 'yes' ); |
|
71 | - |
|
72 | - if ( ! as_next_scheduled_action( self::$cleanup_hook ) ) { |
|
73 | - as_schedule_single_action( gmdate( 'U' ) + ( 6 * MONTH_IN_SECONDS ), self::$cleanup_hook ); |
|
74 | - } |
|
75 | - } |
|
76 | - } |
|
77 | - |
|
78 | - /** |
|
79 | - * Delete all action comments from the WP Comments table. |
|
80 | - */ |
|
81 | - public static function delete_all_action_comments() { |
|
82 | - global $wpdb; |
|
83 | - $wpdb->delete( $wpdb->comments, array( 'comment_type' => ActionScheduler_wpCommentLogger::TYPE, 'comment_agent' => ActionScheduler_wpCommentLogger::AGENT ) ); |
|
84 | - delete_option( self::$has_logs_option_key ); |
|
85 | - } |
|
86 | - |
|
87 | - /** |
|
88 | - * Registers admin notices about the orphaned action logs. |
|
89 | - */ |
|
90 | - public static function register_admin_notice() { |
|
91 | - add_action( 'admin_notices', array( __CLASS__, 'print_admin_notice' ) ); |
|
92 | - } |
|
10 | + /** |
|
11 | + * Post migration hook used to cleanup the WP comment table. |
|
12 | + * |
|
13 | + * @var string |
|
14 | + */ |
|
15 | + protected static $cleanup_hook = 'action_scheduler/cleanup_wp_comment_logs'; |
|
16 | + |
|
17 | + /** |
|
18 | + * An instance of the ActionScheduler_wpCommentLogger class to interact with the comments table. |
|
19 | + * |
|
20 | + * This instance should only be used as an interface. It should not be initialized. |
|
21 | + * |
|
22 | + * @var ActionScheduler_wpCommentLogger |
|
23 | + */ |
|
24 | + protected static $wp_comment_logger = null; |
|
25 | + |
|
26 | + /** |
|
27 | + * The key used to store the cached value of whether there are logs in the WP comment table. |
|
28 | + * |
|
29 | + * @var string |
|
30 | + */ |
|
31 | + protected static $has_logs_option_key = 'as_has_wp_comment_logs'; |
|
32 | + |
|
33 | + /** |
|
34 | + * Initialize the class and attach callbacks. |
|
35 | + */ |
|
36 | + public static function init() { |
|
37 | + if ( empty( self::$wp_comment_logger ) ) { |
|
38 | + self::$wp_comment_logger = new ActionScheduler_wpCommentLogger(); |
|
39 | + } |
|
40 | + |
|
41 | + add_action( self::$cleanup_hook, array( __CLASS__, 'delete_all_action_comments' ) ); |
|
42 | + |
|
43 | + // While there are orphaned logs left in the comments table, we need to attach the callbacks which filter comment counts. |
|
44 | + add_action( 'pre_get_comments', array( self::$wp_comment_logger, 'filter_comment_queries' ), 10, 1 ); |
|
45 | + 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 |
|
46 | + add_action( 'comment_feed_where', array( self::$wp_comment_logger, 'filter_comment_feed' ), 10, 2 ); |
|
47 | + |
|
48 | + // Action Scheduler may be displayed as a Tools screen or WooCommerce > Status administration screen |
|
49 | + add_action( 'load-tools_page_action-scheduler', array( __CLASS__, 'register_admin_notice' ) ); |
|
50 | + add_action( 'load-woocommerce_page_wc-status', array( __CLASS__, 'register_admin_notice' ) ); |
|
51 | + } |
|
52 | + |
|
53 | + /** |
|
54 | + * Determines if there are log entries in the wp comments table. |
|
55 | + * |
|
56 | + * Uses the flag set on migration completion set by @see self::maybe_schedule_cleanup(). |
|
57 | + * |
|
58 | + * @return boolean Whether there are scheduled action comments in the comments table. |
|
59 | + */ |
|
60 | + public static function has_logs() { |
|
61 | + return 'yes' === get_option( self::$has_logs_option_key ); |
|
62 | + } |
|
63 | + |
|
64 | + /** |
|
65 | + * Schedules the WP Post comment table cleanup to run in 6 months if it's not already scheduled. |
|
66 | + * Attached to the migration complete hook 'action_scheduler/migration_complete'. |
|
67 | + */ |
|
68 | + public static function maybe_schedule_cleanup() { |
|
69 | + if ( (bool) get_comments( array( 'type' => ActionScheduler_wpCommentLogger::TYPE, 'number' => 1, 'fields' => 'ids' ) ) ) { |
|
70 | + update_option( self::$has_logs_option_key, 'yes' ); |
|
71 | + |
|
72 | + if ( ! as_next_scheduled_action( self::$cleanup_hook ) ) { |
|
73 | + as_schedule_single_action( gmdate( 'U' ) + ( 6 * MONTH_IN_SECONDS ), self::$cleanup_hook ); |
|
74 | + } |
|
75 | + } |
|
76 | + } |
|
77 | + |
|
78 | + /** |
|
79 | + * Delete all action comments from the WP Comments table. |
|
80 | + */ |
|
81 | + public static function delete_all_action_comments() { |
|
82 | + global $wpdb; |
|
83 | + $wpdb->delete( $wpdb->comments, array( 'comment_type' => ActionScheduler_wpCommentLogger::TYPE, 'comment_agent' => ActionScheduler_wpCommentLogger::AGENT ) ); |
|
84 | + delete_option( self::$has_logs_option_key ); |
|
85 | + } |
|
86 | + |
|
87 | + /** |
|
88 | + * Registers admin notices about the orphaned action logs. |
|
89 | + */ |
|
90 | + public static function register_admin_notice() { |
|
91 | + add_action( 'admin_notices', array( __CLASS__, 'print_admin_notice' ) ); |
|
92 | + } |
|
93 | 93 | |
94 | - /** |
|
95 | - * Prints details about the orphaned action logs and includes information on where to learn more. |
|
96 | - */ |
|
97 | - public static function print_admin_notice() { |
|
98 | - $next_cleanup_message = ''; |
|
99 | - $next_scheduled_cleanup_hook = as_next_scheduled_action( self::$cleanup_hook ); |
|
100 | - |
|
101 | - if ( $next_scheduled_cleanup_hook ) { |
|
102 | - /* translators: %s: date interval */ |
|
103 | - $next_cleanup_message = sprintf( __( 'This data will be deleted in %s.', 'action-scheduler' ), human_time_diff( gmdate( 'U' ), $next_scheduled_cleanup_hook ) ); |
|
104 | - } |
|
105 | - |
|
106 | - $notice = sprintf( |
|
107 | - /* translators: 1: next cleanup message 2: github issue URL */ |
|
108 | - __( 'Action Scheduler has migrated data to custom tables; however, orphaned log entries exist in the WordPress Comments table. %1$s <a href="%2$s">Learn more »</a>', 'action-scheduler' ), |
|
109 | - $next_cleanup_message, |
|
110 | - 'https://github.com/woocommerce/action-scheduler/issues/368' |
|
111 | - ); |
|
112 | - |
|
113 | - echo '<div class="notice notice-warning"><p>' . wp_kses_post( $notice ) . '</p></div>'; |
|
114 | - } |
|
94 | + /** |
|
95 | + * Prints details about the orphaned action logs and includes information on where to learn more. |
|
96 | + */ |
|
97 | + public static function print_admin_notice() { |
|
98 | + $next_cleanup_message = ''; |
|
99 | + $next_scheduled_cleanup_hook = as_next_scheduled_action( self::$cleanup_hook ); |
|
100 | + |
|
101 | + if ( $next_scheduled_cleanup_hook ) { |
|
102 | + /* translators: %s: date interval */ |
|
103 | + $next_cleanup_message = sprintf( __( 'This data will be deleted in %s.', 'action-scheduler' ), human_time_diff( gmdate( 'U' ), $next_scheduled_cleanup_hook ) ); |
|
104 | + } |
|
105 | + |
|
106 | + $notice = sprintf( |
|
107 | + /* translators: 1: next cleanup message 2: github issue URL */ |
|
108 | + __( 'Action Scheduler has migrated data to custom tables; however, orphaned log entries exist in the WordPress Comments table. %1$s <a href="%2$s">Learn more »</a>', 'action-scheduler' ), |
|
109 | + $next_cleanup_message, |
|
110 | + 'https://github.com/woocommerce/action-scheduler/issues/368' |
|
111 | + ); |
|
112 | + |
|
113 | + echo '<div class="notice notice-warning"><p>' . wp_kses_post( $notice ) . '</p></div>'; |
|
114 | + } |
|
115 | 115 | } |
@@ -5,12 +5,12 @@ |
||
5 | 5 | */ |
6 | 6 | class ActionScheduler_FinishedAction extends ActionScheduler_Action { |
7 | 7 | |
8 | - public function execute() { |
|
9 | - // don't execute |
|
10 | - } |
|
8 | + public function execute() { |
|
9 | + // don't execute |
|
10 | + } |
|
11 | 11 | |
12 | - public function is_finished() { |
|
13 | - return TRUE; |
|
14 | - } |
|
12 | + public function is_finished() { |
|
13 | + return TRUE; |
|
14 | + } |
|
15 | 15 | } |
16 | - |
|
17 | 16 | \ No newline at end of file |
17 | + |
|
18 | 18 | \ No newline at end of file |
@@ -8,16 +8,16 @@ |
||
8 | 8 | */ |
9 | 9 | class ActionScheduler_CanceledAction extends ActionScheduler_FinishedAction { |
10 | 10 | |
11 | - /** |
|
12 | - * @param string $hook |
|
13 | - * @param array $args |
|
14 | - * @param ActionScheduler_Schedule $schedule |
|
15 | - * @param string $group |
|
16 | - */ |
|
17 | - public function __construct( $hook, array $args = array(), ActionScheduler_Schedule $schedule = null, $group = '' ) { |
|
18 | - parent::__construct( $hook, $args, $schedule, $group ); |
|
19 | - if ( is_null( $schedule ) ) { |
|
20 | - $this->set_schedule( new ActionScheduler_NullSchedule() ); |
|
21 | - } |
|
22 | - } |
|
11 | + /** |
|
12 | + * @param string $hook |
|
13 | + * @param array $args |
|
14 | + * @param ActionScheduler_Schedule $schedule |
|
15 | + * @param string $group |
|
16 | + */ |
|
17 | + public function __construct( $hook, array $args = array(), ActionScheduler_Schedule $schedule = null, $group = '' ) { |
|
18 | + parent::__construct( $hook, $args, $schedule, $group ); |
|
19 | + if ( is_null( $schedule ) ) { |
|
20 | + $this->set_schedule( new ActionScheduler_NullSchedule() ); |
|
21 | + } |
|
22 | + } |
|
23 | 23 | } |