PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.0.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.0.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 1.4.1 1.4.2 1.5.0 1.5.1 All 61 releases
← All changes | includes/Frontend/MyAccount.php +176 -67 1.5.02.0.0 View file →
@@ -1,8 +1,11 @@
1 1 <?php
2 2
3 3 namespace SpringDevs\Subscription\Frontend;
4 4
5 +use SpringDevs\Subscription\Illuminate\Helper;
6 +use SpringDevs\Subscription\Illuminate\Subscription\Subscription;
7 +
5 8 // HPOS: This file is compatible with WooCommerce High-Performance Order Storage (HPOS).
6 9 // All WooCommerce order data is accessed via WooCommerce CRUD methods (wc_get_order, wc_get_order_item_meta, etc.).
7 10 // All direct post meta access is for subscription data only, not WooCommerce order data.
8 11 // If you add new order data access, use WooCommerce CRUD for HPOS compatibility.
@@ -12,21 +15,48 @@
12 15 *
13 16 * @package SpringDevs\Subscription\Frontend
14 17 */
15 18 class MyAccount {
19 + /**
20 + * Subscriptions endpoint slug.
21 + *
22 + * @var string
23 + */
24 + private $subscriptions_endpoint = 'subscriptions';
16 25
26 + /**
27 + * View Subscriptions endpoint slug.
28 + *
29 + * @var string
30 + */
31 + private $view_subscriptions_endpoint = 'view-subscription';
17 32
33 +
18 34 /**
19 35 * Initialize the class
20 36 */
21 37 public function __construct() {
38 + // Assign endpoint slug from settings.
39 + $this->subscriptions_endpoint = Subscription::get_user_endpoint( 'subs_list' );
40 + $this->view_subscriptions_endpoint = Subscription::get_user_endpoint( 'view_subs' );
41 +
42 + // Flush rewrite rules on init.
22 43 add_action( 'init', array( $this, 'flush_rewrite_rules' ) );
23 - add_filter( 'woocommerce_account_menu_items', array( $this, 'custom_my_account_menu_items' ) );
24 - add_filter( 'woocommerce_endpoint_view-subscription_title', array( $this, 'change_single_title' ) );
25 - add_filter( 'the_title', array( $this, 'change_lists_title' ), 10 );
44 +
45 + // Add My Subscriptions menu item.
46 + add_filter( 'woocommerce_account_menu_items', array( $this, 'custom_my_account_menu_items' ), 200 );
47 +
48 + // Add subscription url endpoints to query vars.
26 49 add_filter( 'woocommerce_get_query_vars', array( $this, 'custom_query_vars' ) );
27 - add_action( 'woocommerce_account_view-subscription_endpoint', array( $this, 'view_subscrpt_content' ) );
28 - add_action( 'woocommerce_account_subscriptions_endpoint', array( $this, 'subscrpt_endpoint_content' ) );
50 +
51 + // Subscription EndPoint Content.
52 + add_action( "woocommerce_account_{$this->subscriptions_endpoint}_endpoint", array( $this, 'subscrpt_endpoint_content' ) );
53 + add_action( "woocommerce_account_{$this->view_subscriptions_endpoint}_endpoint", array( $this, 'view_subscrpt_content' ) );
54 +
55 + // Subscription page titles
56 + add_filter( "woocommerce_endpoint_{$this->subscriptions_endpoint}_title", array( $this, 'change_subscriptions_title' ) );
57 + add_filter( "woocommerce_endpoint_{$this->view_subscriptions_endpoint}_title", array( $this, 'change_single_subscription_title' ) );
58 +
29 59 add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ) );
30 60 }
31 61
32 62 /**
@@ -36,9 +66,11 @@
36 66 *
37 67 * @return array
38 68 */
39 69 public function custom_query_vars( array $query_vars ): array {
40 - $query_vars['view-subscription'] = 'view-subscription';
70 + $query_vars[ $this->subscriptions_endpoint ] = $this->subscriptions_endpoint;
71 + $query_vars[ $this->view_subscriptions_endpoint ] = $this->view_subscriptions_endpoint;
72 +
41 73 return $query_vars;
42 74 }
43 75
44 76 /**
@@ -43,96 +75,170 @@
43 75
44 76 /**
45 77 * Display Subscription Content.
46 78 *
47 - * @param Int $id Post ID.
79 + * @param int $id Post ID.
48 80 */
49 - public function view_subscrpt_content( int $id ) {
50 - $order_id = get_post_meta( $id, '_subscrpt_order_id', true );
51 - $order_item_id = get_post_meta( $id, '_subscrpt_order_item_id', true );
52 - if ( ! $order_id || ! $order_item_id ) {
81 + public function view_subscrpt_content( $id ) {
82 + $id = absint( $id ); // typecast to int.
83 +
84 + $subs_post = get_post( $id );
85 + $author_id = $subs_post ? (int) $subs_post->post_author : 0;
86 + $current_user_id = get_current_user_id();
87 + $user_is_admin = current_user_can( 'manage_options' );
88 +
89 + if ( ! $user_is_admin && (int) $author_id !== (int) $current_user_id ) {
53 90 return wp_safe_redirect( '/404' );
54 91 }
55 - $order = wc_get_order( $order_id );
56 - $order_item = $order->get_item( $order_item_id );
57 - $status = get_post_status( $id );
58 - $user_cancel = get_post_meta( $id, '_subscrpt_user_cancel', true );
59 - $start_date = get_post_meta( $id, '_subscrpt_start_date', true );
60 - $next_date = get_post_meta( $id, '_subscrpt_next_date', true );
61 - $trial = get_post_meta( $id, '_subscrpt_trial', true );
62 - $trial_mode = get_post_meta( $id, '_subscrpt_trial_mode', true );
63 92
93 + $subscription_id = $id;
94 + $subscription_data = Helper::get_subscription_data( $subscription_id );
95 + $related_orders = Helper::get_related_orders( $subscription_id );
96 +
97 + $status = $subscription_data['status'] ?? '';
98 + $verbose_status = Helper::get_verbose_status( $status );
99 +
100 + $order_id = $subscription_data['order']['order_id'] ?? 0;
101 + $order_item_id = $subscription_data['order']['order_item_id'] ?? 0;
102 +
103 + $order = wc_get_order( $order_id );
104 + $order_item = $order ? $order->get_item( $order_item_id ) : null;
105 +
106 + if ( ! $order || ! $order_item ) {
107 + return wp_safe_redirect( '/404' );
108 + }
109 +
110 + $user_cancel = $subscription_data['can_user_cancel'] ?? false;
111 +
112 + $start_date = $subscription_data['start_date'] ?? '';
113 + $start_date = ! empty( $start_date ) ? wp_date( 'F j, Y', strtotime( $start_date ) ) : '-';
114 +
115 + $next_date = $subscription_data['next_date'] ?? '';
116 + $next_date = ! empty( $next_date ) ? wp_date( 'F j, Y', strtotime( $next_date ) ) : '-';
117 +
118 + $trial = get_post_meta( $id, '_subscrpt_trial', true );
119 + $trial_mode = get_post_meta( $id, '_subscrpt_trial_mode', true );
120 +
121 + // Undiscounted subtotal, the discount that recurs, tax on the discounted amount, and the renewal total.
122 + $display_totals = Helper::get_subscription_display_totals( $id, $order_item );
123 +
124 + $price = $display_totals['total'];
125 + $price_excl_tax = $display_totals['full_excl'];
126 + $tax_amount = $display_totals['tax'];
127 + $discount = $display_totals['discount'];
128 +
129 + $is_grace_period = isset( $subscription_data['grace_period'] );
130 + $grace_remaining = $subscription_data['grace_period']['remaining_days'] ?? 0;
131 + $grace_end_date = $subscription_data['grace_period']['end_date'] ?? '';
132 + $grace_end_date = ! empty( $grace_end_date ) ? wp_date( 'F j, Y', strtotime( $grace_end_date ) ) : '';
133 +
64 134 $subscrpt_nonce = wp_create_nonce( 'subscrpt_nonce' );
65 135 $action_buttons = array();
66 136
67 137 if ( 'cancelled' !== $status ) {
68 - if ( in_array( $status, array( 'pending', 'active', 'on_hold' ), true ) && 'yes' === $user_cancel ) {
138 + if ( in_array( $status, array( 'pending', 'active', 'on_hold' ), true ) && $user_cancel ) {
139 + $label = __( 'Cancel', 'subscription' );
140 + $label = apply_filters( 'subscrpt_split_payment_button_text', $label, 'cancel', $id, $status );
141 +
69 142 $action_buttons['cancel'] = array(
70 143 'url' => subscrpt_get_action_url( 'cancelled', $subscrpt_nonce, $id ),
71 - 'label' => __( 'Cancel', 'wp_subscription' ),
144 + 'label' => $label,
72 145 'class' => 'cancel',
73 146 );
74 147 } elseif ( trim( $status ) === trim( 'pe_cancelled' ) ) {
75 - $action_buttons['reactive'] = array(
76 - 'url' => subscrpt_get_action_url( 'reactive', $subscrpt_nonce, $id ),
77 - 'label' => __( 'Reactive', 'wp_subscription' ),
148 + $label = __( 'Reactivate', 'subscription' );
149 + $label = apply_filters( 'subscrpt_split_payment_button_text', $label, 'reactivate', $id, $status );
150 +
151 + $action_buttons['reactivate'] = array(
152 + 'url' => subscrpt_get_action_url( 'reactivate', $subscrpt_nonce, $id ),
153 + 'label' => $label,
78 154 );
79 155 } elseif ( 'expired' === $status && 'pending' !== $order->get_status() ) {
80 - $action_buttons['renew'] = array(
81 - 'url' => subscrpt_get_action_url( 'renew', $subscrpt_nonce, $id ),
82 - 'label' => __( 'Renew', 'wp_subscription' ),
83 - );
156 + // Check if maximum payments reached before showing renew button
157 + if ( ! subscrpt_is_max_payments_reached( $id ) ) {
158 + $label = __( 'Renew', 'subscription' );
159 + $label = apply_filters( 'subscrpt_split_payment_button_text', $label, 'renew', $id, $status );
160 +
161 + $action_buttons['renew'] = array(
162 + 'url' => subscrpt_get_action_url( 'renew', $subscrpt_nonce, $id ),
163 + 'label' => $label,
164 + );
165 + }
84 166 }
85 167
86 168 if ( 'pending' === $order->get_status() ) {
169 + $label = __( 'Pay now', 'subscription' );
170 + $label = apply_filters( 'subscrpt_split_payment_button_text', $label, 'pay_now', $id, $status );
171 +
87 172 $action_buttons['pay_now'] = array(
88 173 'url' => $order->get_checkout_payment_url(),
89 - 'label' => __( 'Pay now', 'wp_subscription' ),
174 + 'label' => $label,
90 175 );
91 176 }
92 177 }
93 178
94 - $is_auto_renew = get_post_meta( $id, '_subscrpt_auto_renew', true );
95 - $renewal_setting = get_option( 'subscrpt_auto_renewal_toggle', '1' );
96 - if ( '' === $is_auto_renew && '1' === $renewal_setting ) {
97 - update_post_meta( $id, '_subscrpt_auto_renew', 1 );
98 - }
179 + $is_auto_renew = $subscription_data['is_auto_renew'];
180 + $renewal_setting = in_array( get_option( 'wp_subscription_auto_renewal_toggle', '1' ), [ 1, '1', 'true', 'yes' ], true );
181 +
99 182 $saved_methods = wc_get_customer_saved_methods_list( get_current_user_id() );
100 183 $has_methods = isset( $saved_methods['cc'] );
101 - if ( $has_methods && '1' === $renewal_setting && class_exists( 'WC_Stripe' ) && $order && 'stripe' === $order->get_payment_method() ) {
102 - if ( '0' === $is_auto_renew ) {
103 - $action_buttons['auto-renew-on'] = array(
104 - 'url' => subscrpt_get_action_url( 'renew-on', $subscrpt_nonce, $id ),
105 - 'label' => __( 'Turn on Auto Renewal', 'wp_subscription' ),
106 - );
107 - } else {
108 - $action_buttons['auto-renew-off'] = array(
109 - 'url' => subscrpt_get_action_url( 'renew-off', $subscrpt_nonce, $id ),
110 - 'label' => __( 'Turn off Auto Renewal', 'wp_subscription' ),
111 - );
184 + if ( $has_methods && $renewal_setting && class_exists( 'WC_Stripe' ) && $order && 'stripe' === $order->get_payment_method() ) {
185 + // Check maximum payment limit for auto-renewal buttons too
186 + if ( ! subscrpt_is_max_payments_reached( $id ) ) {
187 + if ( ! $is_auto_renew ) {
188 + $label = __( 'Turn on Auto Renewal', 'subscription' );
189 + $label = apply_filters( 'subscrpt_split_payment_button_text', $label, 'auto-renew-on', $id, $status );
190 +
191 + $action_buttons['auto-renew-on'] = array(
192 + 'url' => subscrpt_get_action_url( 'renew-on', $subscrpt_nonce, $id ),
193 + 'label' => $label,
194 + );
195 + } else {
196 + $label = __( 'Turn off Auto Renewal', 'subscription' );
197 + $label = apply_filters( 'subscrpt_split_payment_button_text', $label, 'auto-renew-off', $id, $status );
198 +
199 + $action_buttons['auto-renew-off'] = array(
200 + 'url' => subscrpt_get_action_url( 'renew-off', $subscrpt_nonce, $id ),
201 + 'label' => $label,
202 + );
203 + }
112 204 }
113 205 }
114 206
115 - $post_status_object = get_post_status_object( $status );
116 - $action_buttons = apply_filters( 'subscrpt_single_action_buttons', $action_buttons, $id, $subscrpt_nonce, $status );
207 + // Allow programmatically disabling cancel button
208 + $disable_cancel = apply_filters( 'subscrpt_split_payment_disable_cancel', false, $id, $status );
209 + if ( $disable_cancel && isset( $action_buttons['cancel'] ) ) {
210 + unset( $action_buttons['cancel'] );
211 + }
117 212
213 + $action_buttons = apply_filters( 'subscrpt_single_action_buttons', $action_buttons, $id, $subscrpt_nonce, $status );
214 +
118 215 wc_get_template(
119 216 'myaccount/single.php',
120 217 array(
121 218 'id' => $id,
219 + 'status' => $status,
220 + 'verbose_status' => $verbose_status,
122 221 'start_date' => $start_date,
123 222 'next_date' => $next_date,
223 + 'is_grace_period' => $is_grace_period,
224 + 'grace_remaining' => $grace_remaining,
225 + 'grace_end_date' => $grace_end_date,
124 226 'trial' => $trial,
125 227 'trial_mode' => empty( $trial_mode ) ? 'off' : $trial_mode,
126 228 'order' => $order,
127 229 'order_item' => $order_item,
128 - 'status' => $post_status_object,
230 + 'related_orders' => $related_orders,
231 + 'price' => $price,
232 + 'price_excl_tax' => $price_excl_tax,
233 + 'tax' => $tax_amount,
234 + 'discount' => $discount,
129 235 'user_cancel' => $user_cancel,
130 236 'action_buttons' => $action_buttons,
131 237 'wp_button_class' => wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '',
132 238 ),
133 239 'subscription',
134 - WP_SUBSCRIPTION_TEMPLATES
240 + SUBSCRPT_TEMPLATES
135 241 );
136 242 }
137 243
138 244 /**
@@ -138,37 +244,36 @@
138 244 /**
139 245 * Re-write flush
140 246 */
141 247 public function flush_rewrite_rules() {
142 - add_rewrite_endpoint( 'subscriptions', EP_ROOT | EP_PAGES );
248 + add_rewrite_endpoint( $this->subscriptions_endpoint, EP_ROOT | EP_PAGES );
143 249 flush_rewrite_rules();
144 250 }
145 251
146 252 /**
147 - * Change View Subscription Title
253 + * Change All Subscriptions Title
148 254 *
149 255 * @param string $title Title.
150 256 *
151 257 * @return string
152 258 */
153 - public function change_single_title( string $title ): string {
154 - /* translators: %s: Subscription ID */
155 - return sprintf( __( 'Subscription #%s', 'wp_subscription' ), get_query_var( 'view-subscription' ) );
259 + public function change_subscriptions_title( string $title ): string {
260 + $title = __( 'My Subscriptions', 'subscription' );
261 + return $title;
156 262 }
157 263
158 264 /**
159 - * Change Subscription Lists Title
265 + * Change View Subscription Title
160 266 *
161 267 * @param string $title Title.
162 268 *
163 269 * @return string
164 270 */
165 - public function change_lists_title( string $title ): string {
166 - global $wp_query;
167 - $is_endpoint = isset( $wp_query->query_vars['subscriptions'] );
168 - if ( $is_endpoint && ! is_admin() && is_account_page() ) {
169 - $title = __( 'My Subscriptions', 'wp_subscription' );
170 - }
271 + public function change_single_subscription_title( string $title ): string {
272 + $subs_id = get_query_var( $this->view_subscriptions_endpoint, 0 );
273 +
274 + /* translators: %s: Subscription ID */
275 + $title = sprintf( __( 'Subscription #%s', 'subscription' ), $subs_id );
171 276 return $title;
172 277 }
173 278
174 279 /**
@@ -177,12 +282,16 @@
177 282 * @param array $items MyAccount menu items.
178 283 * @return array
179 284 */
180 285 public function custom_my_account_menu_items( array $items ): array {
181 - $logout = $items['customer-logout'];
182 - unset( $items['customer-logout'] );
183 - $items['subscriptions'] = __( 'Subscriptions', 'wp_subscription' );
184 - $items['customer-logout'] = $logout;
286 + // Check if subscriptions menu item already exists to prevent duplicates
287 + if ( ! isset( $items[ $this->subscriptions_endpoint ] ) ) {
288 + $logout = $items['customer-logout'];
289 + unset( $items['customer-logout'] );
290 +
291 + $items[ $this->subscriptions_endpoint ] = __( 'Subscriptions', 'subscription' );
292 + $items['customer-logout'] = $logout;
293 + }
185 294 return $items;
186 295 }
187 296
188 297 /**
@@ -196,9 +305,9 @@
196 305 'author' => get_current_user_id(),
197 306 'posts_per_page' => 10,
198 307 'paged' => $current_page,
199 308 'post_type' => 'subscrpt_order',
200 - 'post_status' => array( 'pending', 'active', 'on_hold', 'cancelled', 'expired', 'pe_cancelled' ),
309 + 'post_status' => array( 'pending', 'active', 'on_hold', 'cancelled', 'expired', 'pe_cancelled', 'completed' ),
201 310 );
202 311
203 312 $postslist = new \WP_Query( $args );
204 313 wc_get_template(
@@ -208,9 +317,9 @@
208 317 'postslist' => $postslist,
209 318 'current_page' => $current_page,
210 319 ),
211 320 'subscription',
212 - WP_SUBSCRIPTION_TEMPLATES
321 + SUBSCRPT_TEMPLATES
213 322 );
214 323 }
215 324
216 325 /**