PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.3.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.3.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 +59 -9 1.11.0 → 2.3.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;
@@ -59,15 +64,18 @@
59 64 * Get verbose status from status slug.
60 65 *
61 66 * @param string $status Status.
62 67 * @param bool $return_all Whether to return all statuses or a single status.
68 + *
69 + * @return string|array Verbose status label, or the full status map when $return_all is true.
63 70 */
64 - public static function get_verbose_status( $status, $return_all = false ): string|array {
71 + public static function get_verbose_status( $status, $return_all = false ) {
65 72 $statuses = array(
66 73 'pending' => __( 'Pending', 'subscription' ),
67 74 'active' => __( 'Active', 'subscription' ),
68 75 'on-hold' => __( 'On Hold', 'subscription' ),
69 76 'expired' => __( 'Expired', 'subscription' ),
77 + 'completed' => __( 'Completed', 'subscription' ),
70 78 'pe_cancelled' => __( 'Pending Cancellation', 'subscription' ),
71 79 'cancelled' => __( 'Cancelled', 'subscription' ),
72 80 'draft' => __( 'Draft', 'subscription' ),
73 81 'trash' => __( 'Trash', 'subscription' ),
@@ -81,8 +89,22 @@
81 89 return isset( $statuses[ $status ] ) ? $statuses[ $status ] : '';
82 90 }
83 91
84 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 + /**
85 107 * Generate start date
86 108 *
87 109 * @param null|string $trial Trial.
88 110 *
@@ -495,12 +517,16 @@
495 517
496 518 // Allow modification of split payment arguments
497 519 $split_payment_args = apply_filters( 'subscrpt_split_payment_args', $split_payment_args, $order_item, $product );
498 520
521 + // Own the subscription from the order's customer, not the current user.
522 + $parent_order = wc_get_order( $order_item->get_order_id() );
523 +
499 524 $args = array(
500 525 'post_title' => 'Subscription',
501 526 'post_type' => 'subscrpt_order',
502 527 'post_status' => $split_payment_args['post_status'],
528 + 'post_author' => $parent_order ? (int) $parent_order->get_customer_id() : get_current_user_id(),
503 529 );
504 530 $subscription_id = wp_insert_post( $args );
505 531 wp_update_post(
506 532 array(
@@ -508,9 +534,10 @@
508 534 'post_title' => "Subscription #{$subscription_id}",
509 535 )
510 536 );
511 537 // Check if this is a split payment subscription
512 - $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';
513 540 $max_payments = $product->get_meta( '_subscrpt_max_no_payment' );
514 541
515 542 $comment_content = '';
516 543 $activity_type = '';
@@ -973,10 +1000,13 @@
973 1000 foreach ( $cart_items as $key => $cart_item ) {
974 1001 $product = $cart_item['data'];
975 1002 if ( $product->is_type( 'simple' ) && isset( $cart_item['subscription'] ) ) {
976 1003 $cart_subscription = $cart_item['subscription'];
977 - $type = ucfirst( $cart_subscription['type'] );
978 - $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 );
979 1009
980 1010 $recurrs[ $key ] = array_merge(
981 1011 $price_data,
982 1012 array(
@@ -982,10 +1012,15 @@
982 1012 array(
983 1013 'trial_status' => ! is_null( $cart_subscription['trial'] ),
984 1014 'start_date' => self::start_date( $cart_subscription['trial'] ),
985 1015 'next_date' => self::next_date( ( $cart_subscription['time'] ?? 1 ) . ' ' . $cart_subscription['type'], $cart_subscription['trial'] ),
986 - 'can_user_cancel' => $cart_item['data']->get_meta( '_subscrpt_user_cancel' ),
987 - '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,
988 1023 'quantity' => (int) $cart_item['quantity'],
989 1024 )
990 1025 );
991 1026 }
@@ -1358,9 +1393,9 @@
1358 1393
1359 1394 $comment_id = wp_insert_comment(
1360 1395 array(
1361 1396 'comment_author' => 'Subscription for WooCommerce',
1362 - 'comment_content' => sprintf( 'Subscription Renewal order successfully created. order is %s', $new_order_id ),
1397 + 'comment_content' => sprintf( 'Subscription Renewal order successfully created. Order #%s', $new_order_id ),
1363 1398 'comment_post_ID' => $subscription_id,
1364 1399 'comment_type' => 'order_note',
1365 1400 )
1366 1401 );
@@ -1368,8 +1403,22 @@
1368 1403 update_comment_meta( $comment_id, '_subscrpt_activity_type', 'renewal_order' );
1369 1404 }
1370 1405
1371 1406 /**
1407 + * Whether a stored `_subscrpt_user_cancel` value lets the customer cancel.
1408 + *
1409 + * Only an explicit "no" forbids it. An empty value means the option was never
1410 + * saved - plan-connected products never store it - and the product form shows
1411 + * "Yes" for that case, so the answer here has to be yes too.
1412 + *
1413 + * @param mixed $value Stored meta value.
1414 + * @return bool
1415 + */
1416 + public static function can_user_cancel( $value ): bool {
1417 + return 'no' !== $value;
1418 + }
1419 +
1420 + /**
1372 1421 * Get a subscription data.
1373 1422 *
1374 1423 * @param int $subscription_id Subscription ID.
1375 1424 * @return array|null
@@ -1398,9 +1447,9 @@
1398 1447
1399 1448 $order_id = get_post_meta( $subscription_id, '_subscrpt_order_id', true );
1400 1449 $order_item_id = get_post_meta( $subscription_id, '_subscrpt_order_item_id', true );
1401 1450
1402 - $can_user_cancel = in_array( get_post_meta( $subscription_id, '_subscrpt_user_cancel', true ), array( 1, '1', 'true', 'yes' ), true );
1451 + $can_user_cancel = self::can_user_cancel( get_post_meta( $subscription_id, '_subscrpt_user_cancel', true ) );
1403 1452
1404 1453 $start_datetime = (int) get_post_meta( $subscription_id, '_subscrpt_start_date', true );
1405 1454 $start_date = ! empty( $start_datetime ) ? gmdate( DATE_RFC2822, $start_datetime ) : null;
1406 1455
@@ -1459,9 +1508,10 @@
1459 1508 );
1460 1509 }
1461 1510
1462 1511 if (
1463 - ! in_array( strtolower( $status ), array( 'cancelled', 'pending' ), true )
1512 + ! in_array( strtolower( $status ), array( 'cancelled', 'pending', 'completed' ), true )
1513 + && ! empty( $next_date )
1464 1514 && $next_datetime - time() <= 0
1465 1515 && (int) $default_grace_period > 0
1466 1516 ) {
1467 1517 $subscription_data['grace_period'] = array(