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
subscription / includes / Frontend / MyAccount.php

MyAccount.php in Subscriptions for WooCommerce with Stripe Recurring Payments 2.4.0, at includes/Frontend/MyAccount.php

337 lines 11.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SpringDevs\Subscription\Frontend;
4
5 use SpringDevs\Subscription\Illuminate\Helper;
6 use SpringDevs\Subscription\Illuminate\Subscription\Subscription;
7
8 // HPOS: This file is compatible with WooCommerce High-Performance Order Storage (HPOS).
9 // All WooCommerce order data is accessed via WooCommerce CRUD methods (wc_get_order, wc_get_order_item_meta, etc.).
10 // All direct post meta access is for subscription data only, not WooCommerce order data.
11 // If you add new order data access, use WooCommerce CRUD for HPOS compatibility.
12
13 /**
14 * Class MyAccount
15 *
16 * @package SpringDevs\Subscription\Frontend
17 */
18 class MyAccount {
19 /**
20 * Subscriptions endpoint slug.
21 *
22 * @var string
23 */
24 private $subscriptions_endpoint = 'subscriptions';
25
26 /**
27 * View Subscriptions endpoint slug.
28 *
29 * @var string
30 */
31 private $view_subscriptions_endpoint = 'view-subscription';
32
33
34 /**
35 * Initialize the class
36 */
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.
43 add_action( 'init', array( $this, 'flush_rewrite_rules' ) );
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.
49 add_filter( 'woocommerce_get_query_vars', array( $this, 'custom_query_vars' ) );
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
59 add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ) );
60 }
61
62 /**
63 * Add custom url on MyAccount.
64 *
65 * @param array $query_vars query_vars.
66 *
67 * @return array
68 */
69 public function custom_query_vars( array $query_vars ): array {
70 $query_vars[ $this->subscriptions_endpoint ] = $this->subscriptions_endpoint;
71 $query_vars[ $this->view_subscriptions_endpoint ] = $this->view_subscriptions_endpoint;
72
73 return $query_vars;
74 }
75
76 /**
77 * Display Subscription Content.
78 *
79 * @param int $id Post ID.
80 */
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 ) {
90 return wp_safe_redirect( '/404' );
91 }
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 ) && Helper::has_next_payment( $status ) ? 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
134 $subscrpt_nonce = wp_create_nonce( 'subscrpt_nonce' );
135 $action_buttons = array();
136
137 if ( 'cancelled' !== $status ) {
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
142 $action_buttons['cancel'] = array(
143 'url' => subscrpt_get_action_url( 'cancelled', $subscrpt_nonce, $id ),
144 'label' => $label,
145 'class' => 'cancel',
146 );
147 } elseif ( trim( $status ) === trim( 'pe_cancelled' ) ) {
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,
154 );
155 } elseif ( 'expired' === $status && 'pending' !== $order->get_status() ) {
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 }
166 }
167
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
172 $action_buttons['pay_now'] = array(
173 'url' => $order->get_checkout_payment_url(),
174 'label' => $label,
175 );
176 }
177 }
178
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
182 $saved_methods = wc_get_customer_saved_methods_list( get_current_user_id() );
183 $has_methods = isset( $saved_methods['cc'] );
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 }
204 }
205 }
206
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 }
212
213 $action_buttons = apply_filters( 'subscrpt_single_action_buttons', $action_buttons, $id, $subscrpt_nonce, $status );
214
215 // Nothing renews once a subscription has ended, so drop the auto-renewal toggle — Pro adds it through the filter too.
216 if ( ! Helper::has_next_payment( $status ) ) {
217 unset( $action_buttons['auto-renew-on'], $action_buttons['auto-renew-off'] );
218 }
219
220 wc_get_template(
221 'myaccount/single.php',
222 array(
223 'id' => $id,
224 'status' => $status,
225 'verbose_status' => $verbose_status,
226 'start_date' => $start_date,
227 'next_date' => $next_date,
228 'is_grace_period' => $is_grace_period,
229 'grace_remaining' => $grace_remaining,
230 'grace_end_date' => $grace_end_date,
231 'trial' => $trial,
232 'trial_mode' => empty( $trial_mode ) ? 'off' : $trial_mode,
233 'order' => $order,
234 'order_item' => $order_item,
235 'related_orders' => $related_orders,
236 'price' => $price,
237 'price_excl_tax' => $price_excl_tax,
238 'tax' => $tax_amount,
239 'discount' => $discount,
240 'user_cancel' => $user_cancel,
241 'action_buttons' => $action_buttons,
242 'wp_button_class' => wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '',
243 ),
244 'subscription',
245 SUBSCRPT_TEMPLATES
246 );
247 }
248
249 /**
250 * Re-write flush
251 */
252 public function flush_rewrite_rules() {
253 add_rewrite_endpoint( $this->subscriptions_endpoint, EP_ROOT | EP_PAGES );
254 flush_rewrite_rules();
255 }
256
257 /**
258 * Change All Subscriptions Title
259 *
260 * @param string $title Title.
261 *
262 * @return string
263 */
264 public function change_subscriptions_title( string $title ): string {
265 $title = __( 'My Subscriptions', 'subscription' );
266 return $title;
267 }
268
269 /**
270 * Change View Subscription Title
271 *
272 * @param string $title Title.
273 *
274 * @return string
275 */
276 public function change_single_subscription_title( string $title ): string {
277 $subs_id = get_query_var( $this->view_subscriptions_endpoint, 0 );
278
279 /* translators: %s: Subscription ID */
280 $title = sprintf( __( 'Subscription #%s', 'subscription' ), $subs_id );
281 return $title;
282 }
283
284 /**
285 * Filter menu items.
286 *
287 * @param array $items MyAccount menu items.
288 * @return array
289 */
290 public function custom_my_account_menu_items( array $items ): array {
291 // Check if subscriptions menu item already exists to prevent duplicates
292 if ( ! isset( $items[ $this->subscriptions_endpoint ] ) ) {
293 $logout = $items['customer-logout'];
294 unset( $items['customer-logout'] );
295
296 $items[ $this->subscriptions_endpoint ] = __( 'Subscriptions', 'subscription' );
297 $items['customer-logout'] = $logout;
298 }
299 return $items;
300 }
301
302 /**
303 * Subscription Single EndPoint Content.
304 *
305 * @param int $current_page Current Page.
306 */
307 public function subscrpt_endpoint_content( $current_page ) {
308 $current_page = empty( $current_page ) ? 1 : absint( $current_page );
309 $args = array(
310 'author' => get_current_user_id(),
311 'posts_per_page' => 10,
312 'paged' => $current_page,
313 'post_type' => 'subscrpt_order',
314 'post_status' => array( 'pending', 'active', 'on_hold', 'cancelled', 'expired', 'pe_cancelled', 'completed' ),
315 );
316
317 $postslist = new \WP_Query( $args );
318 wc_get_template(
319 'myaccount/subscriptions.php',
320 array(
321 'wp_button_class' => wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '',
322 'postslist' => $postslist,
323 'current_page' => $current_page,
324 ),
325 'subscription',
326 SUBSCRPT_TEMPLATES
327 );
328 }
329
330 /**
331 * Enqueue assets
332 */
333 public function enqueue_styles() {
334 wp_enqueue_style( 'subscrpt_status_css' );
335 }
336 }
337