PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 1.11.2
Subscriptions for WooCommerce with Stripe Recurring Payments v1.11.2
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
subscription / templates / myaccount / single.php

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

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