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/Helper.php +56 -10 1.11.2 → 2.4.0 View file →
@@ -1,5 +1,10 @@
1 1 <?php
2 +/**
3 + * Subscription helper utilities.
4 + *
5 + * @package SpringDevs\Subscription\Illuminate
6 + */
2 7
3 8 namespace SpringDevs\Subscription\Illuminate;
4 9
5 10 use SpringDevs\Subscription\Illuminate\Gateways\Stripe\Stripe;
@@ -68,8 +73,9 @@
68 73 'pending' => __( 'Pending', 'subscription' ),
69 74 'active' => __( 'Active', 'subscription' ),
70 75 'on-hold' => __( 'On Hold', 'subscription' ),
71 76 'expired' => __( 'Expired', 'subscription' ),
77 + 'completed' => __( 'Completed', 'subscription' ),
72 78 'pe_cancelled' => __( 'Pending Cancellation', 'subscription' ),
73 79 'cancelled' => __( 'Cancelled', 'subscription' ),
74 80 'draft' => __( 'Draft', 'subscription' ),
75 81 'trash' => __( 'Trash', 'subscription' ),
@@ -83,8 +89,22 @@
83 89 return isset( $statuses[ $status ] ) ? $statuses[ $status ] : '';
84 90 }
85 91
86 92 /**
93 + * Whether a subscription in this status still has a payment ahead.
94 + *
95 + * Cancelling or expiring keeps `_subscrpt_next_date` (the cancellation sweep
96 + * and reactivation read it), so views check the status before showing it.
97 + *
98 + * @param string $status Status.
99 + *
100 + * @return bool
101 + */
102 + public static function has_next_payment( $status ) {
103 + return ! in_array( $status, array( 'cancelled', 'expired' ), true );
104 + }
105 +
106 + /**
87 107 * Generate start date
88 108 *
89 109 * @param null|string $trial Trial.
90 110 *
@@ -514,9 +534,10 @@
514 534 'post_title' => "Subscription #{$subscription_id}",
515 535 )
516 536 );
517 537 // Check if this is a split payment subscription
518 - $payment_type = $product->get_meta( '_subscrpt_payment_type' ) ?: 'recurring';
538 + $payment_type = $product->get_meta( '_subscrpt_payment_type' );
539 + $payment_type = $payment_type ? $payment_type : 'recurring';
519 540 $max_payments = $product->get_meta( '_subscrpt_max_no_payment' );
520 541
521 542 $comment_content = '';
522 543 $activity_type = '';
@@ -979,10 +1000,13 @@
979 1000 foreach ( $cart_items as $key => $cart_item ) {
980 1001 $product = $cart_item['data'];
981 1002 if ( $product->is_type( 'simple' ) && isset( $cart_item['subscription'] ) ) {
982 1003 $cart_subscription = $cart_item['subscription'];
983 - $type = ucfirst( $cart_subscription['type'] );
984 - $price_data = self::build_cart_recurring_price_data( $cart_item, $key, $type );
1004 + // Cadence word must respect the frequency (plan items store the raw
1005 + // plural interval, e.g. "months"): singular for 1, plural + count above.
1006 + $sub_time = max( 1, (int) ( $cart_subscription['time'] ?? 1 ) );
1007 + $type = ( 1 === $sub_time ? '' : $sub_time . ' ' ) . ucfirst( self::get_typos( $sub_time, $cart_subscription['type'] ) );
1008 + $price_data = self::build_cart_recurring_price_data( $cart_item, $key, $type );
985 1009
986 1010 $recurrs[ $key ] = array_merge(
987 1011 $price_data,
988 1012 array(
@@ -988,10 +1012,15 @@
988 1012 array(
989 1013 'trial_status' => ! is_null( $cart_subscription['trial'] ),
990 1014 'start_date' => self::start_date( $cart_subscription['trial'] ),
991 1015 'next_date' => self::next_date( ( $cart_subscription['time'] ?? 1 ) . ' ' . $cart_subscription['type'], $cart_subscription['trial'] ),
992 - 'can_user_cancel' => $cart_item['data']->get_meta( '_subscrpt_user_cancel' ),
993 - 'max_no_payment' => $cart_item['data']->get_meta( '_subscrpt_max_no_payment' ),
1016 + 'can_user_cancel' => self::can_user_cancel( $cart_item['data']->get_meta( '_subscrpt_user_cancel' ) ) ? 'yes' : 'no',
1017 + 'max_no_payment' => ! empty( $cart_item['subscrpt_max_no_payment'] )
1018 + ? (int) $cart_item['subscrpt_max_no_payment']
1019 + : $cart_item['data']->get_meta( '_subscrpt_max_no_payment' ),
1020 + // Exact plan total for split items (the entered price the split is
1021 + // divided from); null for classic split items which have no plan total.
1022 + 'split_total' => isset( $cart_item['subscrpt_split_total'] ) ? (float) $cart_item['subscrpt_split_total'] : null,
994 1023 'quantity' => (int) $cart_item['quantity'],
995 1024 )
996 1025 );
997 1026 }
@@ -1108,11 +1137,13 @@
1108 1137 $new_order->calculate_totals();
1109 1138 $new_order->save();
1110 1139
1111 1140 if ( ! is_admin() && function_exists( 'wc_add_notice' ) && WC()->session ) {
1112 - $message = 'Renewal Order(#' . $new_order->get_id() . ') Created.';
1141 + /* translators: %d: renewal order ID. */
1142 + $message = sprintf( __( 'Renewal order #%d created.', 'subscription' ), $new_order->get_id() );
1113 1143 if ( $new_order->has_status( 'pending' ) ) {
1114 - $message .= 'Please <a href="' . $new_order->get_checkout_payment_url() . '">Pay now</a>';
1144 + /* translators: %s: URL of the order payment page. */
1145 + $message .= ' ' . sprintf( __( 'Please <a href="%s">pay now</a>.', 'subscription' ), esc_url( $new_order->get_checkout_payment_url() ) );
1115 1146 }
1116 1147 wc_add_notice( $message, 'success' );
1117 1148 }
1118 1149
@@ -1364,9 +1395,9 @@
1364 1395
1365 1396 $comment_id = wp_insert_comment(
1366 1397 array(
1367 1398 'comment_author' => 'Subscription for WooCommerce',
1368 - 'comment_content' => sprintf( 'Subscription Renewal order successfully created. order is %s', $new_order_id ),
1399 + 'comment_content' => sprintf( 'Subscription Renewal order successfully created. Order #%s', $new_order_id ),
1369 1400 'comment_post_ID' => $subscription_id,
1370 1401 'comment_type' => 'order_note',
1371 1402 )
1372 1403 );
@@ -1374,8 +1405,22 @@
1374 1405 update_comment_meta( $comment_id, '_subscrpt_activity_type', 'renewal_order' );
1375 1406 }
1376 1407
1377 1408 /**
1409 + * Whether a stored `_subscrpt_user_cancel` value lets the customer cancel.
1410 + *
1411 + * Only an explicit "no" forbids it. An empty value means the option was never
1412 + * saved - plan-connected products never store it - and the product form shows
1413 + * "Yes" for that case, so the answer here has to be yes too.
1414 + *
1415 + * @param mixed $value Stored meta value.
1416 + * @return bool
1417 + */
1418 + public static function can_user_cancel( $value ): bool {
1419 + return 'no' !== $value;
1420 + }
1421 +
1422 + /**
1378 1423 * Get a subscription data.
1379 1424 *
1380 1425 * @param int $subscription_id Subscription ID.
1381 1426 * @return array|null
@@ -1404,9 +1449,9 @@
1404 1449
1405 1450 $order_id = get_post_meta( $subscription_id, '_subscrpt_order_id', true );
1406 1451 $order_item_id = get_post_meta( $subscription_id, '_subscrpt_order_item_id', true );
1407 1452
1408 - $can_user_cancel = in_array( get_post_meta( $subscription_id, '_subscrpt_user_cancel', true ), array( 1, '1', 'true', 'yes' ), true );
1453 + $can_user_cancel = self::can_user_cancel( get_post_meta( $subscription_id, '_subscrpt_user_cancel', true ) );
1409 1454
1410 1455 $start_datetime = (int) get_post_meta( $subscription_id, '_subscrpt_start_date', true );
1411 1456 $start_date = ! empty( $start_datetime ) ? gmdate( DATE_RFC2822, $start_datetime ) : null;
1412 1457
@@ -1465,9 +1510,10 @@
1465 1510 );
1466 1511 }
1467 1512
1468 1513 if (
1469 - ! in_array( strtolower( $status ), array( 'cancelled', 'pending' ), true )
1514 + ! in_array( strtolower( $status ), array( 'cancelled', 'pending', 'completed' ), true )
1515 + && ! empty( $next_date )
1470 1516 && $next_datetime - time() <= 0
1471 1517 && (int) $default_grace_period > 0
1472 1518 ) {
1473 1519 $subscription_data['grace_period'] = array(