PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.0.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.0.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 / templates / myaccount / single.php

single.php in Subscriptions for WooCommerce with Stripe Recurring Payments 2.0.0, at templates/myaccount/single.php

475 lines 17.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Exit if accessed directly.
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6 /**
7 * Single subscription page
8 *
9 * @var WC_Order $order
10 * @var WC_Order_Item $order_item
11 * @var array $related_orders
12 * @var string $start_date
13 * @var string $next_date
14 * @var string|null $trial
15 * @var string|null $trial_mode
16 * @var string $status
17 * @var array $action_buttons
18 * @var bool $is_grace_period
19 * @var int $grace_remaining
20 * @var float $price Renewal total, after any discount that recurs.
21 * @var float $price_excl_tax Renewal subtotal before discount and tax.
22 * @var float $tax Tax on the discounted renewal amount.
23 * @var float $discount Discount that applies to each renewal. 0 when none recurs.
24 *
25 * This template can be overridden by copying it to <your_theme>/subscription/myaccount/single.php
26 *
27 * @package SpringDevs\Subscription
28 */
29
30 use SpringDevs\Subscription\Illuminate\Helper;
31
32 if ( ! isset( $id ) ) {
33 return;
34 }
35
36 if ( ! get_the_title( $id ) ) {
37 return;
38 }
39
40 do_action( 'before_single_subscrpt_content', $id );
41 ?>
42 <style>
43 .auto-renew-on,
44 .subscription_renewal_early,
45 .auto-renew-off {
46 margin-bottom: 10px;
47 }
48 .subscrpt_action_buttons {
49 display: flex;
50 flex-wrap: wrap;
51 gap: 10px;
52 }
53 .product-name .subscrpt-plan-term {
54 display: block;
55 margin-top: 4px;
56 font-size: 13px;
57 color: #6b7280;
58 }
59 </style>
60 <table class="woocommerce-table woocommerce-table--order-details shop_table order_details subscription_details">
61 <tbody>
62 <tr>
63 <td><?php esc_html_e( 'Order', 'subscription' ); ?></td>
64 <td><a href="<?php echo esc_html( wc_get_endpoint_url( 'view-order', $order->get_id(), wc_get_page_permalink( 'myaccount' ) ) ); ?>" target="_blank"># <?php echo esc_html( $order->get_id() ); ?></a></td>
65 </tr>
66 <tr>
67 <td><?php esc_html_e( 'Status', 'subscription' ); ?></td>
68 <td>
69 <?php if ( $is_grace_period && $grace_remaining > 0 ) : ?>
70 <span class="subscrpt-legacy-status subscrpt-legacy-status--active grace-active">
71 Active
72
73 <?php
74 $grace_remaining_text = sprintf(
75 // translators: Number of days remaining in grace period.
76 __( '%d days remaining!', 'subscription' ),
77 $grace_remaining
78 );
79 ?>
80 <span class="grace-icon" data-tooltip="<?php echo esc_attr( $grace_remaining_text ); ?>">
81 <span class="dashicons dashicons-warning"></span>
82 </span>
83 </span>
84 <?php else : ?>
85 <span class="subscrpt-legacy-status subscrpt-legacy-status--<?php echo esc_attr( strtolower( $status ) ); ?>">
86 <?php echo esc_html( $verbose_status ); ?>
87 </span>
88 <?php endif; ?>
89 </td>
90 </tr>
91
92 <?php if ( $is_grace_period && $grace_remaining > 0 ) : ?>
93 <tr>
94 <td><?php esc_html_e( 'Grace Period Ends On', 'subscription' ); ?></td>
95 <td><?php echo esc_html( $grace_end_date ); ?></td>
96 </tr>
97 <?php endif; ?>
98
99 <?php if ( null != $trial && 'off' !== $trial ) : ?>
100 <tr>
101 <td><?php esc_html_e( 'Trial', 'subscription' ); ?></td>
102 <td><?php echo esc_html( $trial ); ?></td>
103 </tr>
104 <?php endif; ?>
105 <tr>
106 <td>
107 <?php
108 if ( 'null' == $trial || 'off' === $trial_mode ) {
109 esc_html_e( 'Start date', 'subscription' );
110 } elseif ( 'extended' === $trial_mode ) {
111 esc_html_e( 'Trial End & Subscription Start', 'subscription' );
112 } else {
113 esc_html_e( 'Trial End & First Billing', 'subscription' );
114 }
115 ?>
116 </td>
117 <td><?php echo esc_html( $start_date ); ?></td>
118 </tr>
119 <?php if ( ( null == $trial || in_array( $trial_mode, array( 'off', 'extended' ), true ) ) && get_post_meta( $id, '_subscrpt_next_date', true ) ) : ?>
120 <tr>
121 <td>
122 <?php
123 esc_html_e( 'Next payment date', 'subscription' );
124 ?>
125 </td>
126 <td>
127 <?php echo esc_html( $next_date ); ?>
128 </td>
129 </tr>
130 <?php endif; ?>
131
132 <!-- get the max_no_payment info using Helper -->
133 <?php $remaining_payments = subscrpt_get_remaining_payments( $id ); ?>
134 <?php $payments_made = subscrpt_count_payments_made( $id ); ?>
135 <?php
136 // Get maximum payments using helper function (handles variations properly)
137 $product_id = get_post_meta( $id, '_subscrpt_product_id', true );
138 $max_payments = subscrpt_get_max_payments( $id );
139
140 // Get Payment Type and Access Duration Information
141 $payment_type = $product_id ? get_post_meta( $product_id, '_subscrpt_payment_type', true ) : 'recurring';
142 $payment_type = $payment_type ?: 'recurring'; // Default to recurring if empty
143
144 // Also check subscription's own meta data
145 $subscription_payment_type = get_post_meta( $id, '_subscrpt_payment_type', true );
146 $subscription_max_payments = get_post_meta( $id, '_subscrpt_max_no_payment', true );
147
148 // Also check if this subscription has variation data
149 $variation_id = get_post_meta( $id, '_subscrpt_variation_id', true );
150 if ( $variation_id ) {
151 $variation_payment_type = get_post_meta( $variation_id, '_subscrpt_payment_type', true );
152 $variation_max_payments = get_post_meta( $variation_id, '_subscrpt_max_no_payment', true );
153
154 // Use variation data if product data is not available
155 if ( empty( $payment_type ) || 'recurring' === $payment_type ) {
156 if ( ! empty( $variation_payment_type ) ) {
157 $payment_type = $variation_payment_type;
158 }
159 }
160 if ( empty( $max_payments ) && ! empty( $variation_max_payments ) ) {
161 $max_payments = $variation_max_payments;
162 }
163 }
164
165 // Use subscription's own data if available and more specific
166 if ( ! empty( $subscription_payment_type ) ) {
167 $payment_type = $subscription_payment_type;
168 }
169 if ( ! empty( $subscription_max_payments ) ) {
170 $max_payments = $subscription_max_payments;
171 }
172
173 // Final fallback: Infer payment type from max_payments if not explicitly set
174 if ( ( empty( $payment_type ) || 'recurring' === $payment_type ) && $max_payments > 0 ) {
175 $payment_type = 'split_payment';
176 }
177
178 // Ensure max_payments is properly set for display
179 $max_payments = (int) $max_payments;
180 ?>
181
182 <!-- show payment progress if max_payments is set and not unlimited -->
183 <?php if ( ( $remaining_payments !== 'unlimited' && $max_payments > 0 ) || ( 'split_payment' === $payment_type && $max_payments > 0 ) ) : ?>
184 <tr>
185 <td><?php esc_html_e( 'Total Payments', 'subscription' ); ?></td>
186 <td><?php echo esc_html( $payments_made ) . ' / ' . esc_html( $max_payments ); ?></td>
187 </tr>
188 <?php endif; ?>
189
190 <tr>
191 <td><?php esc_html_e( 'Payment Type', 'subscription' ); ?></td>
192 <td>
193 <?php
194 if ( 'split_payment' === $payment_type ) {
195 esc_html_e( 'Split Payment', 'subscription' );
196 } else {
197 esc_html_e( 'Recurring', 'subscription' );
198 }
199 ?>
200 <!-- DEBUG: Show raw values -->
201 <!-- <small style="color: #666; font-size: 11px; display: block;">
202 Debug: Product ID: <?php echo esc_html( $product_id ); ?>,
203 Variation ID: <?php echo esc_html( $variation_id ?: 'None' ); ?>,
204 Type: <?php echo esc_html( $payment_type ); ?>,
205 Max: <?php echo esc_html( $max_payments ); ?>
206 </small> -->
207 </td>
208 </tr>
209
210 <!-- Access Duration Information for Split Payments -->
211 <?php if ( 'split_payment' === $payment_type && $max_payments > 0 ) : ?>
212 <?php
213 // Plan subscriptions store access-ends on the subscription; classic ones on
214 // the product. Prefer the subscription meta, fall back to the product.
215 $access_ends_timing = get_post_meta( $id, '_subscrpt_access_ends_timing', true );
216 $access_ends_timing = $access_ends_timing ? $access_ends_timing : ( get_post_meta( $product_id, '_subscrpt_access_ends_timing', true ) ?: 'after_full_duration' );
217 $custom_duration_time = get_post_meta( $id, '_subscrpt_custom_access_duration_time', true ) ?: ( get_post_meta( $product_id, '_subscrpt_custom_access_duration_time', true ) ?: 1 );
218 $custom_duration_type = get_post_meta( $id, '_subscrpt_custom_access_duration_type', true ) ?: ( get_post_meta( $product_id, '_subscrpt_custom_access_duration_type', true ) ?: 'months' );
219
220 // Calculate access end date if Pro version is available
221 $access_end_date_string = null;
222 if ( function_exists( 'subscrpt_pro_activated' ) && subscrpt_pro_activated() ) {
223 if ( class_exists( '\SpringDevs\SubscriptionPro\Illuminate\SplitPaymentHandler' ) ) {
224 $access_end_date_string = \SpringDevs\SubscriptionPro\Illuminate\SplitPaymentHandler::get_access_end_date_string( $id );
225 }
226 }
227 ?>
228 <tr>
229 <td><?php esc_html_e( 'Access Duration', 'subscription' ); ?></td>
230 <td>
231 <?php
232 switch ( $access_ends_timing ) {
233 case 'lifetime':
234 esc_html_e( 'Lifetime access after completion', 'subscription' );
235 break;
236 case 'after_full_duration':
237 esc_html_e( 'Full subscription duration', 'subscription' );
238 break;
239 case 'custom_duration':
240 printf(
241 /* translators: %1$s: duration time, %2$s: duration type */
242 esc_html__( '%1$s %2$s after first payment', 'subscription' ),
243 esc_html( $custom_duration_time ),
244 esc_html( ucfirst( Helper::get_typos( $custom_duration_time, $custom_duration_type, true ) ) )
245 );
246 break;
247 default:
248 esc_html_e( 'Full subscription duration', 'subscription' );
249 break;
250 }
251 ?>
252 </td>
253 </tr>
254
255 <!-- Show calculated access end date if available -->
256 <?php if ( $access_end_date_string ) : ?>
257 <tr>
258 <td><?php esc_html_e( 'Access Ends On', 'subscription' ); ?></td>
259 <td><?php echo esc_html( $access_end_date_string ); ?></td>
260 </tr>
261 <?php endif; ?>
262 <?php endif; ?>
263
264 <?php if ( ! empty( $order->get_payment_method_title() ) ) : ?>
265 <tr>
266 <td><?php esc_html_e( 'Payment', 'subscription' ); ?></td>
267 <td>
268 <span data-is_manual="yes" class="subscription-payment-method"><?php echo esc_html( $order->get_payment_method_title() ); ?></span>
269 </td>
270 </tr>
271 <?php endif; ?>
272 <?php if ( 0 < count( $action_buttons ) ) : ?>
273 <tr>
274 <td><?php echo esc_html_e( 'Actions', 'subscription' ); ?></td>
275 <td class="subscrpt_action_buttons">
276 <?php foreach ( $action_buttons as $action_button ) : ?>
277 <a href="<?php echo esc_attr( $action_button['url'] ); ?>" class="button
278 <?php
279 if ( isset( $action_button['class'] ) ) {
280 echo esc_attr( $action_button['class'] );}
281 ?>
282 <?php echo esc_attr( $wp_button_class ); ?>"><?php echo esc_html( $action_button['label'] ); ?></a>
283 <?php endforeach; ?>
284 </td>
285 </tr>
286 <?php endif; ?>
287 </tbody>
288 </table>
289
290 <?php do_action( 'subscrpt_before_subscription_totals', (int) $id ); ?>
291
292 <h2><?php echo esc_html_e( 'Subscription Totals', 'subscription' ); ?></h2>
293 <table class="woocommerce-table woocommerce-table--order-details shop_table order_details">
294 <thead>
295 <tr>
296 <th class="product-name"><?php echo esc_html_e( 'Product', 'subscription' ); ?></th>
297 <th class="product-total"><?php echo esc_html_e( 'Total', 'subscription' ); ?></th>
298 </tr>
299 </thead>
300 <tbody>
301 <?php
302 $product_name = $order_item->get_name();
303 $product_link = get_permalink( $order_item->get_variation_id() !== 0 ? $order_item->get_variation_id() : $order_item->get_product_id() );
304 $order_item_meta = $order_item->get_meta( '_subscrpt_meta', true );
305 $time = '1' === $order_item_meta['time'] ? null : $order_item_meta['time'];
306 $type = subscrpt_get_typos( $order_item_meta['time'], $order_item_meta['type'] );
307 $product_price_html = Helper::format_price_with_order_item( $price, $order_item->get_id() );
308 ?>
309 <tr class="order_item">
310 <td class="product-name">
311 <a href="<?php echo esc_html( $product_link ); ?>"><?php echo esc_html( $product_name ); ?></a>
312 <strong class="product-quantity">× <?php echo esc_html( $order_item->get_quantity() ); ?></strong>
313 <?php
314 $plan_label = function_exists( 'subscrpt_get_subscription_plan_label' ) ? subscrpt_get_subscription_plan_label( $id ) : '';
315 if ( $plan_label ) :
316 ?>
317 <span class="subscrpt-plan-term"><?php printf( /* translators: %s: plan name. */ esc_html__( 'Plan: %s', 'subscription' ), esc_html( $plan_label ) ); ?></span>
318 <?php endif; ?>
319 </td>
320 <td class="product-total">
321 <span class="woocommerce-Price-amount amount">
322 <?php
323 $unit_price = (float) get_post_meta( $id, '_subscrpt_price', true );
324 $display_price = $unit_price * max( 1, (int) $order_item->get_quantity() );
325 echo wp_kses_post( Helper::format_price_with_order_item( $display_price, $order_item->get_id() ) );
326 ?>
327 </span>
328 </td>
329 </tr>
330 </tbody>
331 <tfoot>
332 <tr>
333 <th scope="row"><?php esc_html_e( 'Subtotal', 'subscription' ); ?>:</th>
334 <td>
335 <span class="woocommerce-Price-amount amount">
336 <?php echo wp_kses_post( wc_price( $price_excl_tax, array( 'currency' => $order->get_currency() ) ) ); ?>
337 </span>
338 </td>
339 </tr>
340
341 <?php if ( ! empty( $discount ) && $discount > 0 ) : ?>
342 <tr class="subscrpt-recurring-discount">
343 <th scope="row"><?php esc_html_e( 'Discount', 'subscription' ); ?>:</th>
344 <td>
345 <span class="woocommerce-Price-amount amount">
346 <?php
347 printf(
348 '-%s',
349 wp_kses_post( wc_price( $discount, array( 'currency' => $order->get_currency() ) ) )
350 );
351 ?>
352 </span>
353 </td>
354 </tr>
355 <?php endif; ?>
356
357 <?php if ( $tax > 0 ) : ?>
358 <tr>
359 <th scope="row"><?php esc_html_e( 'Tax', 'subscription' ); ?>:</th>
360 <td>
361 <span class="woocommerce-Price-amount amount">
362 <?php echo wp_kses_post( wc_price( $tax, array( 'currency' => $order->get_currency() ) ) ); ?>
363 </span>
364 </td>
365 </tr>
366 <?php endif; ?>
367
368 <tr>
369 <th scope="row"><?php esc_html_e( 'Renew', 'subscription' ); ?>:</th>
370 <td>
371 <span class="woocommerce-Price-amount amount">
372 <?php echo wp_kses_post( $product_price_html ); ?>
373 </span>
374 </td>
375 </tr>
376 </tfoot>
377 </table>
378
379 <?php do_action( 'subscrpt_after_subscription_totals', (int) $id ); ?>
380
381 <!-- Show related subscription orders -->
382 <?php
383 /*
384 * Sequence number within this subscription: 1 = first (parent) order, then each
385 * renewal in order. Helper::get_related_orders() returns newest-first, so the
386 * map is built from the reversed list. Relations whose order no longer exists
387 * are skipped here as well, keeping the numbering gapless with the rendered rows.
388 */
389 $related_order_seq = [];
390 foreach ( array_reverse( $related_orders ) as $subscrpt_relation ) {
391 if ( isset( $related_order_seq[ $subscrpt_relation->order_id ] ) || ! wc_get_order( $subscrpt_relation->order_id ) ) {
392 continue;
393 }
394 $related_order_seq[ $subscrpt_relation->order_id ] = count( $related_order_seq ) + 1;
395 }
396 ?>
397 <h2><?php echo esc_html_e( 'Related Orders', 'subscription' ); ?></h2>
398 <table class="woocommerce-table woocommerce-table--order-details shop_table order_details">
399 <thead>
400 <tr>
401 <th class="order-number"><?php echo esc_html_e( '#', 'subscription' ); ?></th>
402 <th class="order-type"><?php echo esc_html_e( 'Type', 'subscription' ); ?></th>
403 <th class="order-date"><?php echo esc_html_e( 'Date', 'subscription' ); ?></th>
404 <th class="order-status"><?php echo esc_html_e( 'Status', 'subscription' ); ?></th>
405 <th class="order-total"><?php echo esc_html_e( 'Total', 'subscription' ); ?></th>
406 </tr>
407 </thead>
408 <tbody>
409 <?php if ( empty( $related_orders ) ) : ?>
410 <tr class="order_item">
411 <td colspan="5" class="no-orders">
412 <?php echo esc_html_e( 'No related orders found.', 'subscription' ); ?>
413 </td>
414 </tr>
415 <?php endif; ?>
416
417 <?php foreach ( $related_orders as $related_order ) : ?>
418 <?php
419 $order_id = $related_order->order_id;
420 $order = wc_get_order( $order_id );
421 if ( ! $order ) {
422 continue;
423 }
424
425 $order_type = $related_order->type;
426 $order_type_label = wps_subscription_order_relation_type_cast( $order_type );
427
428 $order_created_date = $order->get_date_created()->date_i18n( get_option( 'date_format' ) );
429
430 $order_status = $order->get_status();
431 $order_status_name = wc_get_order_status_name( $order_status );
432
433 $order_total = $order->get_total();
434 $formatted_order_total = wc_price( $order_total, array( 'currency' => $order->get_currency() ) );
435 ?>
436
437 <tr class="order_item">
438 <td class="order-number">
439 <?php
440 // translators: %s: WooCommerce order number.
441 $order_number_label = sprintf( __( 'Order #%s', 'subscription' ), $order->get_order_number() );
442 ?>
443 <a href="<?php echo esc_url( wc_get_endpoint_url( 'view-order', $order_id, wc_get_page_permalink( 'myaccount' ) ) ); ?>" title="<?php echo esc_attr( $order_number_label ); ?>" aria-label="<?php echo esc_attr( $order_number_label ); ?>">
444 <?php echo esc_html( number_format_i18n( $related_order_seq[ $order_id ] ?? 0 ) ); ?>
445 </a>
446 </td>
447 <td class="order-type">
448 <?php echo esc_html( $order_type_label ); ?>
449 </td>
450 <td class="order-date">
451 <?php echo esc_html( $order_created_date ); ?>
452 </td>
453 <td class="order-status">
454 <span class="order-status-<?php echo esc_attr( $order_status ); ?>">
455 <?php echo esc_html( $order_status_name ); ?>
456 </span>
457 </td>
458 <td class="order-total">
459 <?php echo wp_kses_post( $formatted_order_total ); ?>
460 </td>
461 </tr>
462 <?php endforeach; ?>
463 </tbody>
464 </table>
465
466 <section class="woocommerce-customer-details">
467 <h2 class="woocommerce-column__title"><?php esc_html_e( 'Billing address', 'subscription' ); ?></h2>
468 <address>
469 <?php echo wp_kses_post( $order->get_formatted_billing_address() ); ?>
470 <p class="woocommerce-customer-details--phone"><?php echo esc_html( $order->get_billing_phone() ); ?></p>
471 <p class="woocommerce-customer-details--email"><?php echo esc_html( $order->get_billing_email() ); ?></p>
472 </address>
473 </section>
474 <div class="clear"></div>
475