PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.2.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.2.0
2.4.0 2.3.0 2.2.0 2.1.0 2.0.0 1.11.2 1.11.1 1.11.0 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.6 1.9.5 trunk 1.3.0 1.3.1 1.3.2 1.4.0 All 65 releases
← All changes | includes/Illuminate/Cron.php +56 -53 1.4.0 → 2.2.0 View file →
@@ -12,92 +12,95 @@
12 12 /**
13 13 * Initialize the class.
14 14 */
15 15 public function __construct() {
16 - add_action( 'subscrpt_daily_cron', array( $this, 'daily_cron_task' ) );
17 - add_action( 'subscrpt_renew_reminder_cron', array( $this, 'send_renew_reminder_mail' ) );
16 + add_action( 'subscrpt_hourly_cron', [ $this, 'hourly_cron_task' ] );
17 +
18 + // ? Dev Note: This is a backward compatibility measure. Remove following action and maybe_reschedule_cron() method after 1 Jan, 2027.
19 + // Safety net: if the old WP-Cron event fires before migration clears it, still process subscriptions.
20 + add_action( 'subscrpt_daily_cron', [ $this, 'hourly_cron_task' ] );
21 + $this->maybe_reschedule_cron();
18 22 }
19 23
20 24 /**
21 - * Send renew reminder mail.
25 + * Migrate to subscrpt_hourly_cron and ensure correct interval.
22 26 *
27 + * Skips rescheduling when running inside wp-cron.php (DOING_CRON) to avoid
28 + * a race condition where WP temporarily removes an event from the queue before
29 + * firing it — without the guard, we would reschedule at midnight and corrupt
30 + * WP-Cron's own next-run timestamp.
31 + *
23 32 * @return void
24 33 */
25 - public function send_renew_reminder_mail() {
26 - $time = strtotime( '7 days' );
34 + private function maybe_reschedule_cron() {
35 + // Remove legacy event name — no-op once migration is complete.
36 + wp_clear_scheduled_hook( 'subscrpt_daily_cron' );
27 37
28 - $args = array(
29 - 'post_type' => 'subscrpt_order',
30 - 'post_status' => array( 'active', 'pe_cancelled' ),
31 - 'fields' => 'ids',
32 - 'meta_query' => array(
33 - 'relation' => 'AND',
34 - array(
35 - 'key' => '_subscrpt_next_date',
36 - 'value' => $time,
37 - 'compare' => '<=',
38 - ),
39 - array(
40 - 'key' => '_subscrpt_trial',
41 - 'compare' => 'NOT EXISTS',
42 - ),
43 - array(
44 - 'key' => '_subscrpt_reminder_mail_sent',
45 - 'compare' => 'NOT EXISTS',
46 - ),
47 - ),
48 - );
38 + // Do not interfere with WP-Cron's own event lifecycle when running via wp-cron.php.
39 + if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
40 + return;
41 + }
49 42
50 - $subscriptions = get_posts( $args );
43 + $event = wp_get_scheduled_event( 'subscrpt_hourly_cron' );
44 + if ( $event && 'hourly' === $event->schedule ) {
45 + return;
46 + }
51 47
52 - if ( 0 === count($subscriptions) ) {
53 - return;
54 - }
48 + wp_clear_scheduled_hook( 'subscrpt_hourly_cron' );
49 + wp_schedule_event( strtotime( 'tomorrow midnight' ), 'hourly', 'subscrpt_hourly_cron' );
50 + }
55 51
56 - WC()->mailer();
57 - foreach ( $subscriptions as $subscription_id ) {
58 - do_action( 'subscrpt_renew_reminder_email_notification', $subscription_id );
59 - }
52 + /**
53 + * Run hourly cron task to check if subscriptions have expired.
54 + */
55 + public function hourly_cron_task() {
56 + do_action( 'before_subscription_update_cron' );
57 +
58 + $this->update_subscription_statusses();
59 +
60 + do_action( 'after_subscription_update_cron' );
60 61 }
61 62
62 63 /**
63 - * Run daily cron task to check if subscription expired.
64 + * Expire active subscriptions whose term has ended.
65 + *
66 + * Pending cancellations (`pe_cancelled`) are handled separately by
67 + * {@see Cancellation}, not here.
64 68 */
65 - public function daily_cron_task() {
66 - $args = array(
69 + public function update_subscription_statusses() {
70 + $args = [
67 71 'post_type' => 'subscrpt_order',
68 - 'post_status' => array( 'active', 'pe_cancelled' ),
72 + 'post_status' => [ 'active' ],
69 73 'fields' => 'ids',
70 - 'meta_query' => array(
74 + 'meta_query' => [
71 75 'relation' => 'OR',
72 - array(
76 + [
73 77 'key' => '_subscrpt_next_date',
74 78 'value' => time(),
75 79 'compare' => '<=',
76 - ),
77 - array(
80 + ],
81 + [
78 82 'relation' => 'AND',
79 - array(
83 + [
80 84 'key' => '_subscrpt_trial',
81 85 'value' => null,
82 86 'compare' => '!=',
83 - ),
84 - array(
87 + ],
88 + [
85 89 'key' => '_subscrpt_start_date',
86 90 'value' => time(),
87 91 'compare' => '<=',
88 - ),
89 - ),
90 - ),
91 - );
92 + ],
93 + ],
94 + ],
95 + ];
92 96
93 97 $expired_subscriptions = get_posts( $args );
94 98
95 99 if ( $expired_subscriptions && count( $expired_subscriptions ) > 0 ) {
96 - foreach ( $expired_subscriptions as $subscription ) {
97 - if ( 'pe_cancelled' === get_post_status( $subscription ) ) {
98 - Action::status( 'cancelled', $subscription );
99 - } else {
100 + // Initialize WooCommerce mailer before processing
101 + if ( function_exists( 'WC' ) && WC()->mailer() ) {
102 + foreach ( $expired_subscriptions as $subscription ) {
100 103 Action::status( 'expired', $subscription );
101 104 }
102 105 }
103 106 }