PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.4.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.4.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 +80 -20 1.3.1 → 2.4.0 View file →
@@ -12,36 +12,96 @@
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' ) );
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();
17 22 }
18 23
19 24 /**
20 - * Run daily cron task to check if subscription expired.
25 + * Migrate to subscrpt_hourly_cron and ensure correct interval.
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 + *
32 + * @return void
21 33 */
22 - public function daily_cron_task() {
23 - $args = array(
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' );
37 +
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 + }
42 +
43 + $event = wp_get_scheduled_event( 'subscrpt_hourly_cron' );
44 + if ( $event && 'hourly' === $event->schedule ) {
45 + return;
46 + }
47 +
48 + wp_clear_scheduled_hook( 'subscrpt_hourly_cron' );
49 + wp_schedule_event( strtotime( 'tomorrow midnight' ), 'hourly', 'subscrpt_hourly_cron' );
50 + }
51 +
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' );
61 + }
62 +
63 + /**
64 + * Expire active subscriptions whose term has ended.
65 + *
66 + * Pending cancellations (`pe_cancelled`) are handled separately by
67 + * {@see Cancellation}, not here.
68 + */
69 + public function update_subscription_statusses() {
70 + $args = [
24 71 'post_type' => 'subscrpt_order',
25 - 'post_status' => array( 'active', 'pe_cancelled' ),
72 + 'post_status' => [ 'active' ],
26 73 'fields' => 'ids',
27 - 'author' => get_current_user_id(),
28 - );
74 + 'meta_query' => [
75 + 'relation' => 'OR',
76 + [
77 + 'key' => '_subscrpt_next_date',
78 + 'value' => time(),
79 + 'compare' => '<=',
80 + ],
81 + [
82 + 'relation' => 'AND',
83 + [
84 + 'key' => '_subscrpt_trial',
85 + 'value' => null,
86 + 'compare' => '!=',
87 + ],
88 + [
89 + 'key' => '_subscrpt_start_date',
90 + 'value' => time(),
91 + 'compare' => '<=',
92 + ],
93 + ],
94 + ],
95 + ];
29 96
30 - $active_subscriptions = get_posts( $args );
97 + $expired_subscriptions = get_posts( $args );
31 98
32 - if ( $active_subscriptions && count( $active_subscriptions ) > 0 ) {
33 - foreach ( $active_subscriptions as $subscription ) {
34 - $start_date = get_post_meta( $subscription, '_subscrpt_start_date', true );
35 - $next_date = get_post_meta( $subscription, '_subscrpt_next_date', true );
36 - $trial = get_post_meta( $subscription, '_subscrpt_trial', true );
37 -
38 - if ( time() >= $next_date || ( null !== $trial && time() >= $start_date ) ) {
39 - if ( 'pe_cancelled' === get_post_status( $subscription ) ) {
40 - Action::status( 'cancelled', $subscription );
41 - } else {
42 - Action::status( 'expired', $subscription );
43 - }
99 + if ( $expired_subscriptions && count( $expired_subscriptions ) > 0 ) {
100 + // Initialize WooCommerce mailer before processing
101 + if ( function_exists( 'WC' ) && WC()->mailer() ) {
102 + foreach ( $expired_subscriptions as $subscription ) {
103 + Action::status( 'expired', $subscription );
44 104 }
45 105 }
46 106 }
47 107 }