From e40091aebecb2da001b8e0151a08baab73bfcbd3 Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Fri, 2 Aug 2024 22:35:21 -0400
Subject: [PATCH 01/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 164 +++++++++++++++++++++
classes/abstracts/ActionScheduler.php | 6 +
2 files changed, 170 insertions(+)
create mode 100644 classes/ActionScheduler_PastDueMonitor.php
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
new file mode 100644
index 000000000..969826417
--- /dev/null
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -0,0 +1,164 @@
+threshold_seconds = absint( apply_filters( 'action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS ) );
+ $this->threshold_minimum = absint( apply_filters( 'action_scheduler_pastdue_actions_min', 1 ) );
+ $this->check_interval = absint( apply_filters( 'action_scheduler_pastdue_actions_check_interval', ( $this->threshold_seconds / 4 ) ) );
+ $this->email_interval_seconds = absint( apply_filters( 'action_scheduler_pastdue_actions_email_interval', HOUR_IN_SECONDS ) );
+
+ add_action( 'action_scheduler_stored_action', array( $this, 'on_action_stored' ), 0 );
+
+ if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || false == DOING_AJAX ) ) {
+ add_action( 'admin_notices', array( $this, 'action__admin_notices' ) );
+ }
+ }
+
+ /**
+ * Action: action_scheduler_stored_action
+ *
+ * Run check on number of past-due actions,
+ * and maybe send email notification.
+ */
+ public function on_action_stored( $action_id ) {
+ if ( 'action_scheduler_stored_action' !== current_action() ) {
+ return;
+ }
+
+ if ( ! $this->critical() ) {
+ return;
+ }
+
+ $this->maybe_send_email();
+ }
+
+ protected function maybe_send_email() {
+ $transient = get_transient( 'action_scheduler_pastdue_actions_last_email' );
+
+ if ( ! empty( $transient ) ) {
+ return;
+ }
+
+ $threshold = absint( apply_filters( 'action_scheduler_pastdue_actions_email_min', $this->threshold_minimum ) );
+
+ if ( $this->num_pastdue_actions < $threshold ) {
+ return;
+ }
+
+ $to = get_bloginfo( 'admin_email' );
+ $from = '';
+ $subject = '';
+ $message = '';
+
+ set_transient( 'action_scheduler_pastdue_actions_last_email', time(), $this->email_interval_seconds );
+
+ wp_mail( $to, $subject, $message, "From: $from" );
+ }
+
+ protected function critical() {
+ // Allow third-parties to preempt the default check logic.
+ $check = apply_filters( 'action_scheduler_pastdue_actions_check_pre', null );
+
+ // If no third-party preempted and there are no past-due actions, return early.
+ if ( ! is_null( $check ) ) {
+ return $check;
+ }
+
+ $transient = get_transient( 'action_scheduler_pastdue_actions_critical' );
+
+ if ( ! empty( $transient ) ) {
+ return 'yes' === $transient;
+ }
+
+ # Scheduled actions query arguments.
+ $query_args = array(
+ 'date' => as_get_datetime_object( time() - $threshold_seconds ),
+ 'status' => ActionScheduler_Store::STATUS_PENDING,
+ 'per_page' => $this->threshold_minimum,
+ );
+
+ $store = ActionScheduler_Store::instance();
+ $this->num_pastdue_actions = ( int ) $store->query_actions( $query_args, 'count' );
+
+ # Check if past-due actions count is greater than or equal to threshold.
+ $check = ( $num_pastdue_actions >= $this->threshold_minimum );
+ $check = ( bool ) apply_filters( 'action_scheduler_pastdue_actions_check', $check, $this->num_pastdue_actions, $this->threshold_seconds, $this->threshold_minimum );
+
+ $transient = $check ? 'yes' : 'no';
+ set_transient( 'action_scheduler_pastdue_actions_critical', $transient, $this->check_interval );
+
+ return $check;
+ }
+
+ /**
+ * Action: admin_notices
+ *
+ * Maybe check past-due actions, and print notice.
+ */
+ public function action__admin_notices() {
+ if ( 'admin_notices' !== current_action() ) {
+ return;
+ }
+
+ # Filter to prevent showing notice (ex: inappropriate user).
+ if ( ! apply_filters( 'action_scheduler_check_pastdue_actions', current_user_can( 'manage_options' ) ) ) {
+ return;
+ }
+
+ if ( ! $this->critical() ) {
+ return;
+ }
+
+ $actions_url = add_query_arg( array(
+ 'page' => 'action-scheduler',
+ 'status' => 'past-due',
+ 'order' => 'asc',
+ ), admin_url( 'tools.php' ) );
+
+ # Print notice.
+ echo '';
+ printf(
+ // translators: 1) is the number of affected actions, 2) is a link to an admin screen.
+ _n(
+ 'Action Scheduler: %1$d past-due action found; something may be wrong. Read documentation »',
+ 'Action Scheduler: %1$d past-due actions found; something may be wrong. Read documentation »',
+ $this->num_pastdue_actions,
+ 'action-scheduler'
+ ),
+ $this->num_pastdue_actions,
+ esc_attr( esc_url( $actions_url ) )
+ );
+ echo '
';
+
+ # Facilitate third-parties to evaluate and print notices.
+ do_action( 'action_scheduler_pastdue_actions_extra_notices', $query_args );
+ }
+
+}
diff --git a/classes/abstracts/ActionScheduler.php b/classes/abstracts/ActionScheduler.php
index 0163f7072..e4128d28b 100644
--- a/classes/abstracts/ActionScheduler.php
+++ b/classes/abstracts/ActionScheduler.php
@@ -41,6 +41,10 @@ public static function admin_view() {
return ActionScheduler_AdminView::instance();
}
+ public static function monitor() {
+ return ActionSchdeduler_PastDueMonitor::instance();
+ }
+
/**
* Get the absolute system path to the plugin directory, or a file therein
* @static
@@ -146,6 +150,7 @@ public static function init( $plugin_file ) {
$logger = self::logger();
$runner = self::runner();
$admin_view = self::admin_view();
+ $monitor = self::monitor();
// Ensure initialization on plugin activation.
if ( ! did_action( 'init' ) ) {
@@ -153,6 +158,7 @@ public static function init( $plugin_file ) {
add_action( 'init', array( $store, 'init' ), 1, 0 );
add_action( 'init', array( $logger, 'init' ), 1, 0 );
add_action( 'init', array( $runner, 'init' ), 1, 0 );
+ add_action( 'init', array( $monitor, 'init' ), 1, 0 );
add_action(
'init',
From 672bf1da15389c1dda3721869c25acb5fdda50d8 Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Fri, 2 Aug 2024 22:39:07 -0400
Subject: [PATCH 02/14] save
---
classes/ActionScheduler_AdminView.php | 99 -------------------
.../ActionScheduler_AdminView_Deprecated.php | 20 +++-
2 files changed, 19 insertions(+), 100 deletions(-)
diff --git a/classes/ActionScheduler_AdminView.php b/classes/ActionScheduler_AdminView.php
index ed30950a7..fdb72cbf3 100644
--- a/classes/ActionScheduler_AdminView.php
+++ b/classes/ActionScheduler_AdminView.php
@@ -40,7 +40,6 @@ public function init() {
}
add_action( 'admin_menu', array( $this, 'register_menu' ) );
- add_action( 'admin_notices', array( $this, 'maybe_check_pastdue_actions' ) );
add_action( 'current_screen', array( $this, 'add_help_tabs' ) );
}
}
@@ -110,104 +109,6 @@ protected function get_list_table() {
return $this->list_table;
}
- /**
- * Action: admin_notices
- *
- * Maybe check past-due actions, and print notice.
- *
- * @uses $this->check_pastdue_actions()
- */
- public function maybe_check_pastdue_actions() {
-
- # 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.
- $last_check = get_transient( 'action_scheduler_last_pastdue_actions_check' );
-
- # If transient exists, we're within interval, so bail.
- if ( ! empty( $last_check ) ) {
- return;
- }
-
- # Perform the check.
- $this->check_pastdue_actions();
- }
-
- /**
- * Check past-due actions, and print notice.
- *
- * @todo update $link_url to "Past-due" filter when released (see issue #510, PR #511)
- */
- 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 fallback value for past-due actions count.
- $num_pastdue_actions = 0;
-
- // Allow third-parties to preempt the default check logic.
- $check = apply_filters( 'action_scheduler_pastdue_actions_check_pre', null );
-
- // If no third-party preempted and there are no past-due actions, return early.
- if ( ! is_null( $check ) ) {
- return;
- }
-
- # 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 ( is_null( $check ) ) {
- $store = ActionScheduler_Store::instance();
- $num_pastdue_actions = ( int ) $store->query_actions( $query_args, 'count' );
-
- # 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 );
- }
-
- # 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 );
-
- return;
- }
-
- $actions_url = add_query_arg( array(
- 'page' => 'action-scheduler',
- 'status' => 'past-due',
- 'order' => 'asc',
- ), admin_url( 'tools.php' ) );
-
- # Print notice.
- echo '';
- printf(
- // translators: 1) is the number of affected actions, 2) is a link to an admin screen.
- _n(
- 'Action Scheduler: %1$d past-due action found; something may be wrong. Read documentation »',
- 'Action Scheduler: %1$d past-due actions found; something may be wrong. Read documentation »',
- $num_pastdue_actions,
- 'action-scheduler'
- ),
- $num_pastdue_actions,
- esc_attr( esc_url( $actions_url ) )
- );
- echo '
';
-
- # Facilitate third-parties to evaluate and print notices.
- do_action( 'action_scheduler_pastdue_actions_extra_notices', $query_args );
- }
-
/**
* Provide more information about the screen and its data in the help tab.
*/
diff --git a/deprecated/ActionScheduler_AdminView_Deprecated.php b/deprecated/ActionScheduler_AdminView_Deprecated.php
index 62d964e0f..fb2b0c967 100644
--- a/deprecated/ActionScheduler_AdminView_Deprecated.php
+++ b/deprecated/ActionScheduler_AdminView_Deprecated.php
@@ -144,4 +144,22 @@ public function post_updated_messages( $messages ) {
_deprecated_function( __METHOD__, '2.0.0' );
return $messages;
}
-}
\ No newline at end of file
+
+ /**
+ * Action: admin_notices
+ *
+ * Maybe check past-due actions, and print notice.
+ *
+ * @uses $this->check_pastdue_actions()
+ */
+ public function maybe_check_pastdue_actions() {
+ _deprecated_function( __METHOD__, '3.8.2' );
+ }
+
+ /**
+ * Check past-due actions, and print notice.
+ */
+ protected function check_pastdue_actions() {
+ _deprecated_function( __METHOD__, '3.8.2' );
+ }
+}
From 1d7c248ab186f48690c303edab80faf9476f5c84 Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Fri, 2 Aug 2024 22:54:26 -0400
Subject: [PATCH 03/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index 969826417..4168d6ca6 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -10,8 +10,8 @@ class ActionScheduler_PastDueMonitor {
protected $threshold_seconds;
protected $threshold_minimum;
- protected $check_interval;
- protected $email_interval_seconds;
+ protected $interval_check;
+ protected $interval_email_seconds;
protected $num_pastdue_actions = 0;
/**
@@ -29,10 +29,11 @@ public static function instance() {
}
public function init() {
- $this->threshold_seconds = absint( apply_filters( 'action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS ) );
- $this->threshold_minimum = absint( apply_filters( 'action_scheduler_pastdue_actions_min', 1 ) );
- $this->check_interval = absint( apply_filters( 'action_scheduler_pastdue_actions_check_interval', ( $this->threshold_seconds / 4 ) ) );
- $this->email_interval_seconds = absint( apply_filters( 'action_scheduler_pastdue_actions_email_interval', HOUR_IN_SECONDS ) );
+ $this->threshold_seconds = absint( apply_filters( 'action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS ) );
+ $this->threshold_minimum = absint( apply_filters( 'action_scheduler_pastdue_actions_min', 1 ) );
+ $this->interval_check = absint( apply_filters( 'action_scheduler_pastdue_actions_check_interval', ( $this->threshold_seconds / 4 ) ) );
+ $this->interval_email_seconds = absint( apply_filters( 'action_scheduler_pastdue_actions_email_interval', HOUR_IN_SECONDS ) );
+ $this->threshold_email_minimum = absint( apply_filters( 'action_scheduler_pastdue_actions_email_min', $this->threshold_minimum ) )
add_action( 'action_scheduler_stored_action', array( $this, 'on_action_stored' ), 0 );
@@ -66,9 +67,7 @@ protected function maybe_send_email() {
return;
}
- $threshold = absint( apply_filters( 'action_scheduler_pastdue_actions_email_min', $this->threshold_minimum ) );
-
- if ( $this->num_pastdue_actions < $threshold ) {
+ if ( $this->num_pastdue_actions < $this->threshold_email_min ) {
return;
}
@@ -77,7 +76,7 @@ protected function maybe_send_email() {
$subject = '';
$message = '';
- set_transient( 'action_scheduler_pastdue_actions_last_email', time(), $this->email_interval_seconds );
+ set_transient( 'action_scheduler_pastdue_actions_last_email', time(), $this->interval_email_seconds );
wp_mail( $to, $subject, $message, "From: $from" );
}
@@ -112,7 +111,7 @@ protected function critical() {
$check = ( bool ) apply_filters( 'action_scheduler_pastdue_actions_check', $check, $this->num_pastdue_actions, $this->threshold_seconds, $this->threshold_minimum );
$transient = $check ? 'yes' : 'no';
- set_transient( 'action_scheduler_pastdue_actions_critical', $transient, $this->check_interval );
+ set_transient( 'action_scheduler_pastdue_actions_critical', $transient, $this->interval_check );
return $check;
}
From 4e13f5fe689659157cf00dd35bd243e1c27e6d23 Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Sat, 3 Aug 2024 02:17:03 -0400
Subject: [PATCH 04/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 34 ++++++++--------------
classes/abstracts/ActionScheduler.php | 3 +-
2 files changed, 14 insertions(+), 23 deletions(-)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index 4168d6ca6..ed2bfb36e 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -2,6 +2,7 @@
/**
* Class ActionScheduler_PastDueMonitor
+ *
* @codeCoverageIgnore
*/
class ActionScheduler_PastDueMonitor {
@@ -10,12 +11,15 @@ class ActionScheduler_PastDueMonitor {
protected $threshold_seconds;
protected $threshold_minimum;
+ protected $threshold_email_minimum;
protected $interval_check;
protected $interval_email_seconds;
protected $num_pastdue_actions = 0;
+ protected $query_args = array();
/**
* @return ActionScheduler_PastDueMonitor
+ *
* @codeCoverageIgnore
*/
public static function instance() {
@@ -33,34 +37,20 @@ public function init() {
$this->threshold_minimum = absint( apply_filters( 'action_scheduler_pastdue_actions_min', 1 ) );
$this->interval_check = absint( apply_filters( 'action_scheduler_pastdue_actions_check_interval', ( $this->threshold_seconds / 4 ) ) );
$this->interval_email_seconds = absint( apply_filters( 'action_scheduler_pastdue_actions_email_interval', HOUR_IN_SECONDS ) );
- $this->threshold_email_minimum = absint( apply_filters( 'action_scheduler_pastdue_actions_email_min', $this->threshold_minimum ) )
+ $this->threshold_email_minimum = absint( apply_filters( 'action_scheduler_pastdue_actions_email_min', $this->threshold_minimum ) );
- add_action( 'action_scheduler_stored_action', array( $this, 'on_action_stored' ), 0 );
+ $this->maybe_send_email();
if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || false == DOING_AJAX ) ) {
add_action( 'admin_notices', array( $this, 'action__admin_notices' ) );
}
}
- /**
- * Action: action_scheduler_stored_action
- *
- * Run check on number of past-due actions,
- * and maybe send email notification.
- */
- public function on_action_stored( $action_id ) {
- if ( 'action_scheduler_stored_action' !== current_action() ) {
- return;
- }
-
+ protected function maybe_send_email() {
if ( ! $this->critical() ) {
return;
}
- $this->maybe_send_email();
- }
-
- protected function maybe_send_email() {
$transient = get_transient( 'action_scheduler_pastdue_actions_last_email' );
if ( ! empty( $transient ) ) {
@@ -97,17 +87,17 @@ protected function critical() {
}
# Scheduled actions query arguments.
- $query_args = array(
- 'date' => as_get_datetime_object( time() - $threshold_seconds ),
+ $this->query_args = array(
+ 'date' => as_get_datetime_object( time() - $this->threshold_seconds ),
'status' => ActionScheduler_Store::STATUS_PENDING,
'per_page' => $this->threshold_minimum,
);
$store = ActionScheduler_Store::instance();
- $this->num_pastdue_actions = ( int ) $store->query_actions( $query_args, 'count' );
+ $this->num_pastdue_actions = ( int ) $store->query_actions( $this->query_args, 'count' );
# Check if past-due actions count is greater than or equal to threshold.
- $check = ( $num_pastdue_actions >= $this->threshold_minimum );
+ $check = ( $this->num_pastdue_actions >= $this->threshold_minimum );
$check = ( bool ) apply_filters( 'action_scheduler_pastdue_actions_check', $check, $this->num_pastdue_actions, $this->threshold_seconds, $this->threshold_minimum );
$transient = $check ? 'yes' : 'no';
@@ -157,7 +147,7 @@ public function action__admin_notices() {
echo '
';
# Facilitate third-parties to evaluate and print notices.
- do_action( 'action_scheduler_pastdue_actions_extra_notices', $query_args );
+ do_action( 'action_scheduler_pastdue_actions_extra_notices', $this->query_args );
}
}
diff --git a/classes/abstracts/ActionScheduler.php b/classes/abstracts/ActionScheduler.php
index e4128d28b..0dab7f2ad 100644
--- a/classes/abstracts/ActionScheduler.php
+++ b/classes/abstracts/ActionScheduler.php
@@ -42,7 +42,7 @@ public static function admin_view() {
}
public static function monitor() {
- return ActionSchdeduler_PastDueMonitor::instance();
+ return ActionScheduler_PastDueMonitor::instance();
}
/**
@@ -186,6 +186,7 @@ function () {
$store->init();
$logger->init();
$runner->init();
+ $monitor->init();
self::$data_store_initialized = true;
/**
From 3ea707d35d25529289d81ca08b9069d78c0d5528 Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Sat, 3 Aug 2024 02:31:29 -0400
Subject: [PATCH 05/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index ed2bfb36e..f50ddabff 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -80,10 +80,14 @@ protected function critical() {
return $check;
}
- $transient = get_transient( 'action_scheduler_pastdue_actions_critical' );
+ if ( ! empty( $this->num_pastdue_actions ) ) {
+ return true;
+ }
+
+ $transient = get_transient( 'action_scheduler_pastdue_actions_pause' );
if ( ! empty( $transient ) ) {
- return 'yes' === $transient;
+ return false;
}
# Scheduled actions query arguments.
@@ -100,8 +104,9 @@ protected function critical() {
$check = ( $this->num_pastdue_actions >= $this->threshold_minimum );
$check = ( bool ) apply_filters( 'action_scheduler_pastdue_actions_check', $check, $this->num_pastdue_actions, $this->threshold_seconds, $this->threshold_minimum );
- $transient = $check ? 'yes' : 'no';
- set_transient( 'action_scheduler_pastdue_actions_critical', $transient, $this->interval_check );
+ if ( ! $check ) {
+ set_transient( 'action_scheduler_pastdue_actions_pause', time(), $this->interval_check );
+ }
return $check;
}
From 0a01652fdfde9ac6e9034fd354658e818f0ee3ca Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Sat, 3 Aug 2024 02:50:35 -0400
Subject: [PATCH 06/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 37 ++++++++++++++--------
1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index f50ddabff..698151955 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -61,14 +61,21 @@ protected function maybe_send_email() {
return;
}
- $to = get_bloginfo( 'admin_email' );
- $from = '';
- $subject = '';
- $message = '';
+ $sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
+
+ if ( null !== $sitename ) {
+ if ( str_starts_with( $sitename, 'www.' ) ) {
+ $sitename = substr( $sitename, 4 );
+ }
+ }
+
+ $to = get_site_option( 'admin_email' );
+ $subject = sprintf( '%s: past-due scheduled actions', $sitename );
+ $message = $this->message();
set_transient( 'action_scheduler_pastdue_actions_last_email', time(), $this->interval_email_seconds );
- wp_mail( $to, $subject, $message, "From: $from" );
+ wp_mail( $to, $subject, $message );
}
protected function critical() {
@@ -130,15 +137,23 @@ public function action__admin_notices() {
return;
}
+ # Print notice.
+ echo '';
+ echo $this->message();
+ echo '
';
+
+ # Facilitate third-parties to evaluate and print notices.
+ do_action( 'action_scheduler_pastdue_actions_extra_notices', $this->query_args );
+ }
+
+ protected function message() {
$actions_url = add_query_arg( array(
'page' => 'action-scheduler',
'status' => 'past-due',
'order' => 'asc',
), admin_url( 'tools.php' ) );
- # Print notice.
- echo '';
- printf(
+ return sprintf(
// translators: 1) is the number of affected actions, 2) is a link to an admin screen.
_n(
'Action Scheduler: %1$d past-due action found; something may be wrong. Read documentation »',
@@ -147,12 +162,8 @@ public function action__admin_notices() {
'action-scheduler'
),
$this->num_pastdue_actions,
- esc_attr( esc_url( $actions_url ) )
+ esc_url( $actions_url )
);
- echo '
';
-
- # Facilitate third-parties to evaluate and print notices.
- do_action( 'action_scheduler_pastdue_actions_extra_notices', $this->query_args );
}
}
From 16dafb30ac7426516c251d4598cd4b475375f02f Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Sat, 3 Aug 2024 02:54:45 -0400
Subject: [PATCH 07/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index 698151955..8137769d5 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -57,7 +57,7 @@ protected function maybe_send_email() {
return;
}
- if ( $this->num_pastdue_actions < $this->threshold_email_min ) {
+ if ( $this->num_pastdue_actions < $this->threshold_email_minimum ) {
return;
}
@@ -70,7 +70,7 @@ protected function maybe_send_email() {
}
$to = get_site_option( 'admin_email' );
- $subject = sprintf( '%s: past-due scheduled actions', $sitename );
+ $subject = sprintf( 'Action Scheduler: past-due scheduled actions (%s)', $sitename );
$message = $this->message();
set_transient( 'action_scheduler_pastdue_actions_last_email', time(), $this->interval_email_seconds );
From 70b028e0117fd4db5ac4b352345db05877157ef7 Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Mon, 5 Aug 2024 19:24:33 -0400
Subject: [PATCH 08/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 130 +++++++++++++--------
1 file changed, 83 insertions(+), 47 deletions(-)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index 8137769d5..e37639c6d 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -7,6 +7,9 @@
*/
class ActionScheduler_PastDueMonitor {
+ const TRANSIENT_LAST_EMAIL = 'action_scheduler_pastdue_actions_last_email';
+ const TRANSIENT_CHECK_INTERVAL = 'action_scheduler_last_pastdue_actions_check';
+
private static $monitor = null;
protected $threshold_seconds;
@@ -32,6 +35,11 @@ public static function instance() {
return self::$monitor;
}
+ /**
+ * Initialize.
+ *
+ * @return void
+ */
public function init() {
$this->threshold_seconds = absint( apply_filters( 'action_scheduler_pastdue_actions_seconds', DAY_IN_SECONDS ) );
$this->threshold_minimum = absint( apply_filters( 'action_scheduler_pastdue_actions_min', 1 ) );
@@ -39,83 +47,98 @@ public function init() {
$this->interval_email_seconds = absint( apply_filters( 'action_scheduler_pastdue_actions_email_interval', HOUR_IN_SECONDS ) );
$this->threshold_email_minimum = absint( apply_filters( 'action_scheduler_pastdue_actions_email_min', $this->threshold_minimum ) );
- $this->maybe_send_email();
+ add_action( 'action_scheduler_stored_action', array( $this, 'maybe_send_email' ) );
if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || false == DOING_AJAX ) ) {
add_action( 'admin_notices', array( $this, 'action__admin_notices' ) );
}
}
- protected function maybe_send_email() {
- if ( ! $this->critical() ) {
- return;
- }
-
- $transient = get_transient( 'action_scheduler_pastdue_actions_last_email' );
+ /**
+ * Check if threshold for past-due actions is flooded.
+ *
+ * @return bool
+ */
+ protected function flooded() {
+ $transient = get_transient( self::TRANSIENT_CHECK_INTERVAL );
if ( ! empty( $transient ) ) {
- return;
- }
-
- if ( $this->num_pastdue_actions < $this->threshold_email_minimum ) {
- return;
+ return false;
}
- $sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
+ # Scheduled actions query arguments.
+ $this->query_args = array(
+ 'date' => as_get_datetime_object( time() - $this->threshold_seconds ),
+ 'status' => ActionScheduler_Store::STATUS_PENDING,
+ 'per_page' => $this->threshold_minimum,
+ );
- if ( null !== $sitename ) {
- if ( str_starts_with( $sitename, 'www.' ) ) {
- $sitename = substr( $sitename, 4 );
- }
- }
+ $store = ActionScheduler_Store::instance();
+ $this->num_pastdue_actions = ( int ) $store->query_actions( $this->query_args, 'count' );
- $to = get_site_option( 'admin_email' );
- $subject = sprintf( 'Action Scheduler: past-due scheduled actions (%s)', $sitename );
- $message = $this->message();
+ # Check if past-due actions count is greater than or equal to threshold.
+ $flooded = ( $this->num_pastdue_actions >= $this->threshold_minimum );
+ $flooded = ( bool ) apply_filters( 'action_scheduler_pastdue_actions_check', $flooded, $this->num_pastdue_actions, $this->threshold_seconds, $this->threshold_minimum );
- set_transient( 'action_scheduler_pastdue_actions_last_email', time(), $this->interval_email_seconds );
+ # If not flooded, delay next check.
+ if ( ! $flooded ) {
+ set_transient( self::TRANSIENT_CHECK_INTERVAL, time(), $this->interval_check );
+ }
- wp_mail( $to, $subject, $message );
+ return $flooded;
}
- protected function critical() {
+ /**
+ * Action: action_scheduler_stored_action
+ *
+ * Maybe send email notice of past-due actions over threshold.
+ *
+ * @return void
+ */
+ public function maybe_send_email() {
+ if ( 'action_scheduler_stored_action' !== current_action() ) {
+ return;
+ }
+
// Allow third-parties to preempt the default check logic.
- $check = apply_filters( 'action_scheduler_pastdue_actions_check_pre', null );
+ $pre = apply_filters( 'action_scheduler_pastdue_actions_check_pre', null );
// If no third-party preempted and there are no past-due actions, return early.
- if ( ! is_null( $check ) ) {
- return $check;
+ if ( ! is_null( $pre ) ) {
+ return;
}
- if ( ! empty( $this->num_pastdue_actions ) ) {
- return true;
+ if ( ! $this->flooded() ) {
+ return;
}
- $transient = get_transient( 'action_scheduler_pastdue_actions_pause' );
+ $transient = get_transient( self::TRANSIENT_LAST_EMAIL );
if ( ! empty( $transient ) ) {
- return false;
+ return;
}
- # Scheduled actions query arguments.
- $this->query_args = array(
- 'date' => as_get_datetime_object( time() - $this->threshold_seconds ),
- 'status' => ActionScheduler_Store::STATUS_PENDING,
- 'per_page' => $this->threshold_minimum,
- );
-
- $store = ActionScheduler_Store::instance();
- $this->num_pastdue_actions = ( int ) $store->query_actions( $this->query_args, 'count' );
+ if ( $this->num_pastdue_actions < $this->threshold_email_minimum ) {
+ return;
+ }
- # Check if past-due actions count is greater than or equal to threshold.
- $check = ( $this->num_pastdue_actions >= $this->threshold_minimum );
- $check = ( bool ) apply_filters( 'action_scheduler_pastdue_actions_check', $check, $this->num_pastdue_actions, $this->threshold_seconds, $this->threshold_minimum );
+ $sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
- if ( ! $check ) {
- set_transient( 'action_scheduler_pastdue_actions_pause', time(), $this->interval_check );
+ if ( null !== $sitename ) {
+ if ( str_starts_with( $sitename, 'www.' ) ) {
+ $sitename = substr( $sitename, 4 );
+ }
}
- return $check;
+ $to = get_site_option( 'admin_email' );
+ $subject = sprintf( 'Action Scheduler: past-due scheduled actions (%s)', $sitename );
+ $message = $this->message();
+
+ set_transient( self::TRANSIENT_LAST_EMAIL, time(), $this->interval_email_seconds );
+
+ wp_mail( $to, $subject, $message, array(
+ 'Content-type: text/html; charset=UTF-8',
+ ) );
}
/**
@@ -133,7 +156,15 @@ public function action__admin_notices() {
return;
}
- if ( ! $this->critical() ) {
+ // Allow third-parties to preempt the default check logic.
+ $pre = apply_filters( 'action_scheduler_pastdue_actions_check_pre', null );
+
+ // If no third-party preempted and there are no past-due actions, return early.
+ if ( ! is_null( $pre ) ) {
+ return;
+ }
+
+ if ( ! $this->flooded() ) {
return;
}
@@ -146,6 +177,11 @@ public function action__admin_notices() {
do_action( 'action_scheduler_pastdue_actions_extra_notices', $this->query_args );
}
+ /**
+ * Message for admin notice and email notice.
+ *
+ * @return string
+ */
protected function message() {
$actions_url = add_query_arg( array(
'page' => 'action-scheduler',
From c2e42d4d56d252218318cdf179d6671a2a420ae5 Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Mon, 5 Aug 2024 19:37:51 -0400
Subject: [PATCH 09/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 105 ++++++++++++++++-----
1 file changed, 84 insertions(+), 21 deletions(-)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index e37639c6d..8fe93dfc3 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -7,20 +7,69 @@
*/
class ActionScheduler_PastDueMonitor {
- const TRANSIENT_LAST_EMAIL = 'action_scheduler_pastdue_actions_last_email';
+ const TRANSIENT_LAST_EMAIL = 'action_scheduler_pastdue_actions_last_email';
const TRANSIENT_CHECK_INTERVAL = 'action_scheduler_last_pastdue_actions_check';
+ /**
+ * Instance.
+ *
+ * @var null|self
+ */
private static $monitor = null;
+ /**
+ * Number of seconds in the past to qualify as past-due action.
+ *
+ * @var int
+ */
protected $threshold_seconds;
- protected $threshold_minimum;
+
+ /**
+ * Number of minimum past-due actions to display admin notice.
+ *
+ * @var int
+ */
+ protected $threshold_admin_minimum;
+
+ /**
+ * Number of minimum past-due actions to send email notice.
+ *
+ * @var int
+ */
protected $threshold_email_minimum;
+
+ /**
+ * Number of seconds before past-due actions check after
+ * negative (not flooded) check.
+ *
+ * @var int
+ */
protected $interval_check;
+
+ /**
+ * Number of seconds between email notices.
+ *
+ * @var int
+ */
protected $interval_email_seconds;
+
+ /**
+ * Number of past-due actions (determined by thresholds).
+ *
+ * @var int
+ */
protected $num_pastdue_actions = 0;
+
+ /**
+ * Query arguments for past-due actions.
+ *
+ * @var array
+ */
protected $query_args = array();
/**
+ * Get singleton instance.
+ *
* @return ActionScheduler_PastDueMonitor
*
* @codeCoverageIgnore
@@ -28,7 +77,7 @@ class ActionScheduler_PastDueMonitor {
public static function instance() {
if ( empty( self::$monitor ) ) {
- $class = apply_filters( 'action_scheduler_pastdue_actions_monitor_class', 'ActionScheduler_PastDueMonitor' );
+ $class = apply_filters( 'action_scheduler_pastdue_actions_monitor_class', 'ActionScheduler_PastDueMonitor' );
self::$monitor = new $class();
}
@@ -49,7 +98,7 @@ public function init() {
add_action( 'action_scheduler_stored_action', array( $this, 'maybe_send_email' ) );
- if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || false == DOING_AJAX ) ) {
+ if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || empty( DOING_AJAX ) ) ) {
add_action( 'admin_notices', array( $this, 'action__admin_notices' ) );
}
}
@@ -66,7 +115,7 @@ protected function flooded() {
return false;
}
- # Scheduled actions query arguments.
+ // Scheduled actions query arguments.
$this->query_args = array(
'date' => as_get_datetime_object( time() - $this->threshold_seconds ),
'status' => ActionScheduler_Store::STATUS_PENDING,
@@ -74,13 +123,14 @@ protected function flooded() {
);
$store = ActionScheduler_Store::instance();
- $this->num_pastdue_actions = ( int ) $store->query_actions( $this->query_args, 'count' );
- # Check if past-due actions count is greater than or equal to threshold.
+ $this->num_pastdue_actions = absint( $store->query_actions( $this->query_args, 'count' ) );
+
+ // Check if past-due actions count is greater than or equal to threshold.
$flooded = ( $this->num_pastdue_actions >= $this->threshold_minimum );
- $flooded = ( bool ) apply_filters( 'action_scheduler_pastdue_actions_check', $flooded, $this->num_pastdue_actions, $this->threshold_seconds, $this->threshold_minimum );
+ $flooded = (bool) apply_filters( 'action_scheduler_pastdue_actions_check', $flooded, $this->num_pastdue_actions, $this->threshold_seconds, $this->threshold_minimum );
- # If not flooded, delay next check.
+ // If not flooded, delay next check.
if ( ! $flooded ) {
set_transient( self::TRANSIENT_CHECK_INTERVAL, time(), $this->interval_check );
}
@@ -133,12 +183,13 @@ public function maybe_send_email() {
$to = get_site_option( 'admin_email' );
$subject = sprintf( 'Action Scheduler: past-due scheduled actions (%s)', $sitename );
$message = $this->message();
+ $headers = array(
+ 'Content-type: text/html; charset=UTF-8',
+ );
set_transient( self::TRANSIENT_LAST_EMAIL, time(), $this->interval_email_seconds );
- wp_mail( $to, $subject, $message, array(
- 'Content-type: text/html; charset=UTF-8',
- ) );
+ wp_mail( $to, $subject, $message, $headers );
}
/**
@@ -151,7 +202,7 @@ public function action__admin_notices() {
return;
}
- # Filter to prevent showing notice (ex: inappropriate user).
+ // Filter to prevent showing notice (ex: inappropriate user).
if ( ! apply_filters( 'action_scheduler_check_pastdue_actions', current_user_can( 'manage_options' ) ) ) {
return;
}
@@ -168,12 +219,21 @@ public function action__admin_notices() {
return;
}
- # Print notice.
+ // Print notice.
echo '';
- echo $this->message();
+ echo wp_kses(
+ $this->message(),
+ array(
+ 'strong' => array(),
+ 'a' => array(
+ 'target' => true,
+ 'href' => true,
+ ),
+ )
+ );
echo '
';
- # Facilitate third-parties to evaluate and print notices.
+ // Facilitate third-parties to evaluate and print notices.
do_action( 'action_scheduler_pastdue_actions_extra_notices', $this->query_args );
}
@@ -183,11 +243,14 @@ public function action__admin_notices() {
* @return string
*/
protected function message() {
- $actions_url = add_query_arg( array(
- 'page' => 'action-scheduler',
- 'status' => 'past-due',
- 'order' => 'asc',
- ), admin_url( 'tools.php' ) );
+ $actions_url = add_query_arg(
+ array(
+ 'page' => 'action-scheduler',
+ 'status' => 'past-due',
+ 'order' => 'asc',
+ ),
+ admin_url( 'tools.php' )
+ );
return sprintf(
// translators: 1) is the number of affected actions, 2) is a link to an admin screen.
From df102dc716507221b0794506a365abdf7ca97d37 Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Mon, 5 Aug 2024 19:48:45 -0400
Subject: [PATCH 10/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 23 +++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index 8fe93dfc3..3846aff1d 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -29,7 +29,7 @@ class ActionScheduler_PastDueMonitor {
*
* @var int
*/
- protected $threshold_admin_minimum;
+ protected $threshold_minimum;
/**
* Number of minimum past-due actions to send email notice.
@@ -130,10 +130,7 @@ protected function flooded() {
$flooded = ( $this->num_pastdue_actions >= $this->threshold_minimum );
$flooded = (bool) apply_filters( 'action_scheduler_pastdue_actions_check', $flooded, $this->num_pastdue_actions, $this->threshold_seconds, $this->threshold_minimum );
- // If not flooded, delay next check.
- if ( ! $flooded ) {
- set_transient( self::TRANSIENT_CHECK_INTERVAL, time(), $this->interval_check );
- }
+ set_transient( self::TRANSIENT_CHECK_INTERVAL, time(), $this->interval_check );
return $flooded;
}
@@ -141,11 +138,12 @@ protected function flooded() {
/**
* Action: action_scheduler_stored_action
*
- * Maybe send email notice of past-due actions over threshold.
+ * Delete check interval transient, perform flooded check,
+ * and maybe send email.
*
* @return void
*/
- public function maybe_send_email() {
+ public function on_action_stored() {
if ( 'action_scheduler_stored_action' !== current_action() ) {
return;
}
@@ -158,10 +156,21 @@ public function maybe_send_email() {
return;
}
+ delete_transient( self::TRANSIENT_CHECK_INTERVAL );
+
if ( ! $this->flooded() ) {
return;
}
+ $this->maybe_send_email();
+ }
+
+ /**
+ * Maybe send email notice of past-due actions over threshold.
+ *
+ * @return void
+ */
+ protected function maybe_send_email() {
$transient = get_transient( self::TRANSIENT_LAST_EMAIL );
if ( ! empty( $transient ) ) {
From fc8a8dcb66b13d88c5cf1a0c2b12d5389adf161b Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Mon, 5 Aug 2024 19:51:17 -0400
Subject: [PATCH 11/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index 3846aff1d..f37c64554 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -96,7 +96,7 @@ public function init() {
$this->interval_email_seconds = absint( apply_filters( 'action_scheduler_pastdue_actions_email_interval', HOUR_IN_SECONDS ) );
$this->threshold_email_minimum = absint( apply_filters( 'action_scheduler_pastdue_actions_email_min', $this->threshold_minimum ) );
- add_action( 'action_scheduler_stored_action', array( $this, 'maybe_send_email' ) );
+ add_action( 'action_scheduler_stored_action', array( $this, 'on_action_stored' ) );
if ( is_admin() && ( ! defined( 'DOING_AJAX' ) || empty( DOING_AJAX ) ) ) {
add_action( 'admin_notices', array( $this, 'action__admin_notices' ) );
From 36af56c9e55a2ec2b6392642a743113adf460889 Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Wed, 7 Aug 2024 22:17:31 -0400
Subject: [PATCH 12/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 3 +++
1 file changed, 3 insertions(+)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index f37c64554..75ec5334b 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -158,6 +158,9 @@ public function on_action_stored() {
delete_transient( self::TRANSIENT_CHECK_INTERVAL );
+ // Removing the callback before querying actions is necessary to prevent loop.
+ remove_action( 'action_scheduler_stored_action', array( $this, 'on_action_stored' ) );
+
if ( ! $this->flooded() ) {
return;
}
From 25a186b9aedd9a51d495e05c5d0feb860319886a Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Fri, 6 Sep 2024 21:30:53 -0400
Subject: [PATCH 13/14] save
---
classes/ActionScheduler_PastDueMonitor.php | 89 +++++++++++++++++++++-
1 file changed, 86 insertions(+), 3 deletions(-)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index 75ec5334b..0cea25b82 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -67,6 +67,20 @@ class ActionScheduler_PastDueMonitor {
*/
protected $query_args = array();
+ /**
+ * Notification methods.
+ *
+ * @var array
+ */
+ protected $notify_methods = array();
+
+ /**
+ * Email address to send notification.
+ *
+ * @var string
+ */
+ protected $notify_email_to;
+
/**
* Get singleton instance.
*
@@ -95,6 +109,16 @@ public function init() {
$this->interval_check = absint( apply_filters( 'action_scheduler_pastdue_actions_check_interval', ( $this->threshold_seconds / 4 ) ) );
$this->interval_email_seconds = absint( apply_filters( 'action_scheduler_pastdue_actions_email_interval', HOUR_IN_SECONDS ) );
$this->threshold_email_minimum = absint( apply_filters( 'action_scheduler_pastdue_actions_email_min', $this->threshold_minimum ) );
+ $this->notify_methods = $this->notify_methods();
+
+ $notify_email_to = apply_filters( 'action_scheduler_pastdue_monitor_notify_email_to', get_site_option( 'admin_email' ) );
+
+ if ( ! is_string( $notify_email_to ) || ! is_email( $notify_email_to ) ) {
+ trigger_error( 'Invalid email address provided for past-due actions flooded email notification: using site\'s administrator email address.', E_USER_WARNING );
+ $notify_email_to = get_site_option( 'admin_email' );
+ }
+
+ $this->notify_email_to = $notify_email_to;
add_action( 'action_scheduler_stored_action', array( $this, 'on_action_stored' ) );
@@ -103,6 +127,60 @@ public function init() {
}
}
+ /**
+ * Check if notification method enabled.
+ *
+ * @param string $method
+ * @return bool
+ */
+ protected function notify( $method ) {
+ return ! empty( $this->notify_methods[ $method ] );
+ }
+
+ /**
+ * Get enabled notification methods.
+ *
+ * @return array
+ */
+ protected function notify_methods() {
+ $all = array(
+ 'admin' => true,
+ 'email' => true,
+ );
+
+ $default = $all;
+ $default['admin'] = function_exists( 'current_user_can' ) && current_user_can( 'manage_options' );
+ $methods = $default;
+
+ // Apply deprecated filter.
+ if ( has_filter( 'action_scheduler_check_pastdue_actions' ) ) {
+ $methods['admin'] = apply_filters_deprecated(
+ 'action_scheduler_check_pastdue_actions',
+ array( $methods['admin'] ),
+ '', // todo: add version number
+ 'action_scheduler_pastdue_monitor_notify'
+ );
+ }
+
+ // Allow site devs to specify notification preference.
+ $methods = apply_filters( 'action_scheduler_pastdue_monitor_notify', $methods );
+
+ // Support for scalar and bool values (ex: `__return_false`).
+ if ( is_scalar( $methods ) || is_bool( $methods ) ) {
+ return boolval( $methods ) ? $all : array();
+ }
+
+ // Insist on an array.
+ if ( ! is_array( $methods ) ) {
+ return $default;
+ }
+
+ // Clear out unsupported methods.
+ $methods = array_intersect_key( $methods, $all );
+
+ return $methods;
+ }
+
/**
* Check if threshold for past-due actions is flooded.
*
@@ -174,6 +252,10 @@ public function on_action_stored() {
* @return void
*/
protected function maybe_send_email() {
+ if ( ! $this->notify( 'email' ) ) {
+ return;
+ }
+
$transient = get_transient( self::TRANSIENT_LAST_EMAIL );
if ( ! empty( $transient ) ) {
@@ -192,7 +274,7 @@ protected function maybe_send_email() {
}
}
- $to = get_site_option( 'admin_email' );
+ $to = $this->notify_email_to;
$subject = sprintf( 'Action Scheduler: past-due scheduled actions (%s)', $sitename );
$message = $this->message();
$headers = array(
@@ -202,6 +284,8 @@ protected function maybe_send_email() {
set_transient( self::TRANSIENT_LAST_EMAIL, time(), $this->interval_email_seconds );
wp_mail( $to, $subject, $message, $headers );
+
+ do_action( 'action_scheduler_pastdue_monitor_notified_email' );
}
/**
@@ -214,8 +298,7 @@ public function action__admin_notices() {
return;
}
- // Filter to prevent showing notice (ex: inappropriate user).
- if ( ! apply_filters( 'action_scheduler_check_pastdue_actions', current_user_can( 'manage_options' ) ) ) {
+ if ( ! $this->notify( 'admin' ) ) {
return;
}
From 4d643f5c28d9a2f8d2e590ff8e6b1e383e9da41e Mon Sep 17 00:00:00 2001
From: Caleb Stauffer
Date: Tue, 17 Sep 2024 13:54:07 -0400
Subject: [PATCH 14/14] add documentation for filter
---
classes/ActionScheduler_PastDueMonitor.php | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/classes/ActionScheduler_PastDueMonitor.php b/classes/ActionScheduler_PastDueMonitor.php
index 0cea25b82..6b6932961 100644
--- a/classes/ActionScheduler_PastDueMonitor.php
+++ b/classes/ActionScheduler_PastDueMonitor.php
@@ -163,6 +163,16 @@ protected function notify_methods() {
}
// Allow site devs to specify notification preference.
+ /**
+ * Allow site devs to specify the active notification methods.
+ *
+ * Default:
+ * array( 'admin' => true, 'email' => true )
+ *
+ * Supported:
+ * - array
+ * - boolean: true = enable all, false = disable all
+ */
$methods = apply_filters( 'action_scheduler_pastdue_monitor_notify', $methods );
// Support for scalar and bool values (ex: `__return_false`).