Skip to content
This repository was archived by the owner on May 21, 2025. It is now read-only.

Commit bb49bf0

Browse files
committed
Merge branch 'trunk' into fix/remove-new-draft-checkout-status-from-get-related-order-ids
2 parents 890f870 + d9609cf commit bb49bf0

13 files changed

+234
-18
lines changed

build/index.asset.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<?php return array('dependencies' => array('wc-blocks-checkout', 'wc-price-format', 'wc-settings', 'wp-element', 'wp-i18n', 'wp-plugins'), 'version' => 'b74144542a686437daa06d7e57f2567f');
1+
<?php return array('dependencies' => array('wc-blocks-checkout', 'wc-price-format', 'wc-settings', 'wp-element', 'wp-i18n', 'wp-plugins'), 'version' => '7e9abfc482fe190e29673f828b33f482');

build/index.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

changelog.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
*** WooCommerce Subscriptions Core Changelog ***
22

3-
= 7.2.0 - 2024-xx-xx =
3+
= 7.3.0 - 2024-xx-xx =
44
* Fix - Removing the new "wc-checkout-draft" status from the method used to retrieve related orders.
5+
* Fix - Fixed an issue with subscriptions containing multiple renewal orders to mark a random item as processing, instead of the last order.
6+
7+
= 7.2.0 - 2024-06-13 =
8+
* Fix - label improvement on my subscription page template.
9+
* Fix - Regenerate subscriptions related order caches (renewal, resubscribe, switch) if it's stored as an invalid value to prevent fatal errors.
510
* Update - Show "FREE" instead of 0 when there is no shipping cost in the recurring totals section of the Cart and Checkout blocks (requires WooCommerce 9.0+).
11+
* Dev - New function wcs_set_recurring_item_total() to set line item totals that have been copied from an initial order to their proper recurring totals (i.e. remove sign-up fees).
612

713
= 7.1.1 - 2024-05-09 =
814
* Fix - Resolved an issue that caused "WC_DateTime could not be converted to int" warnings to occur on non-hpos sites while editing a subscription.

includes/class-wc-subscriptions-core-plugin.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class WC_Subscriptions_Core_Plugin {
1616
* The version of subscriptions-core library.
1717
* @var string
1818
*/
19-
protected $library_version = '7.1.1'; // WRCS: DEFINED_VERSION.
19+
protected $library_version = '7.2.0'; // WRCS: DEFINED_VERSION.
2020

2121
/**
2222
* The subscription scheduler instance.

includes/class-wc-subscriptions-renewal-order.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ public static function maybe_record_subscription_payment( $order_id, $orders_old
130130
$is_failed_renewal_order = 'failed' === $orders_old_status || wc_string_to_bool( $order->get_meta( WC_Subscription::RENEWAL_FAILED_META_KEY, true ) );
131131
$is_failed_renewal_order = apply_filters( 'woocommerce_subscriptions_is_failed_renewal_order', $is_failed_renewal_order, $order_id, $orders_old_status );
132132

133-
if ( $order_needed_payment ) {
133+
// Subscription will be activated only if this is the last renewal order of the subscription.
134+
if ( $order_needed_payment && wcs_is_order_last_renewal_of_subscription( $order, $subscription ) ) {
134135
$subscription->payment_complete();
135136
$was_activated = true;
136137
}

includes/data-stores/class-wcs-related-order-store-cached-cpt.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,9 @@ public function get_related_order_ids_from_cache( $subscription, $relation_type
210210

211211
$meta_data = $this->get_related_order_metadata( $subscription, $relation_type );
212212

213-
return $meta_data ? maybe_unserialize( $meta_data->meta_value ) : '';
213+
$related_orders = $meta_data ? maybe_unserialize( $meta_data->meta_value ) : '';
214+
215+
return is_array( $related_orders ) ? $related_orders : '';
214216
}
215217

216218
/**

includes/wcs-order-functions.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,3 +1003,55 @@ function wcs_order_contains_early_renewal( $order ) {
10031003
function wcs_get_subscription_item_grouping_key( $item, $renewal_time = '' ) {
10041004
return apply_filters( 'woocommerce_subscriptions_item_grouping_key', wcs_get_subscription_grouping_key( $item->get_product(), $renewal_time ), $item );
10051005
}
1006+
1007+
/**
1008+
* Sets the order item total to its recurring product price.
1009+
*
1010+
* This function takes an order item and checks if its totals have been modified to account for free trials or sign-up fees (i.e. parent orders).
1011+
* If the totals have been adjusted, the function sets the item's total back to their recurring total.
1012+
*
1013+
* Note: If the line item has a custom total that doesn't match the expected price, don't override it.
1014+
*
1015+
* @param WC_Order_Item $item Subscription line item.
1016+
*/
1017+
function wcs_set_recurring_item_total( &$item ) {
1018+
$product = $item->get_product();
1019+
1020+
if ( ! $product || ! WC_Subscriptions_Product::is_subscription( $product ) ) {
1021+
return;
1022+
}
1023+
1024+
$sign_up_fee = WC_Subscriptions_Product::get_sign_up_fee( $product );
1025+
$sign_up_fee = is_numeric( $sign_up_fee ) ? (float) $sign_up_fee : 0;
1026+
$trial_length = WC_Subscriptions_Product::get_trial_length( $product );
1027+
1028+
$recurring_price = (float) $product->get_price();
1029+
$initial_price = $trial_length > 0 ? $sign_up_fee : $recurring_price + $sign_up_fee;
1030+
$initial_total = wc_get_price_excluding_tax(
1031+
$product,
1032+
[
1033+
'qty' => $item->get_quantity(),
1034+
'price' => $initial_price,
1035+
]
1036+
);
1037+
1038+
// Check if a custom item total was set on the order. If so, don't override it.
1039+
if ( (float) $item->get_subtotal() !== $initial_total ) {
1040+
return;
1041+
}
1042+
1043+
$recurring_total = wc_get_price_excluding_tax(
1044+
$product,
1045+
[
1046+
'qty' => $item->get_quantity(),
1047+
'price' => $recurring_price,
1048+
]
1049+
);
1050+
1051+
$item->set_props(
1052+
[
1053+
'subtotal' => $recurring_total,
1054+
'total' => $recurring_total,
1055+
]
1056+
);
1057+
}

includes/wcs-renewal-functions.php

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ function wcs_order_contains_renewal( $order ) {
6262
return apply_filters( 'woocommerce_subscriptions_is_renewal_order', $is_renewal, $order );
6363
}
6464

65+
/**
66+
* Determines if a given order is the subscription's latest renewal order.
67+
*
68+
* @param $order WC_Order The order object.
69+
* @param $subscription WC_Subscription The subscription object.
70+
* @return bool Whether the order is the latest renewal order of the provided subscription.
71+
*/
72+
function wcs_is_order_last_renewal_of_subscription( $order, $subscription ) {
73+
$last_renewal_order = wcs_get_last_renewal_order( $subscription );
74+
return $last_renewal_order && $last_renewal_order->get_id() === $order->get_id();
75+
}
76+
6577
/**
6678
* Checks the cart to see if it contains a subscription product renewal.
6779
*
@@ -128,10 +140,7 @@ function wcs_get_subscriptions_for_renewal_order( $order ) {
128140
*/
129141
function wcs_get_last_non_early_renewal_order( $subscription ) {
130142
$last_non_early_renewal = false;
131-
$renewal_orders = $subscription->get_related_orders( 'all', 'renewal' );
132-
133-
// We need the orders sorted by the date they were created, with the newest first.
134-
wcs_sort_objects( $renewal_orders, 'date_created', 'descending' );
143+
$renewal_orders = wcs_get_renewal_orders_sorted_by( $subscription, 'date_created' );
135144

136145
foreach ( $renewal_orders as $renewal_order ) {
137146
if ( ! wcs_order_contains_early_renewal( $renewal_order ) ) {
@@ -143,6 +152,34 @@ function wcs_get_last_non_early_renewal_order( $subscription ) {
143152
return $last_non_early_renewal;
144153
}
145154

155+
/**
156+
* Get the last renewal order (early renewals included).
157+
*
158+
* @param WC_Subscription $subscription The subscription object.
159+
* @return WC_Order|bool The last non-early renewal order, otherwise false.
160+
*/
161+
function wcs_get_last_renewal_order( $subscription ) {
162+
$renewal_orders = wcs_get_renewal_orders_sorted_by( $subscription, 'date_created' );
163+
return $renewal_orders ? reset( $renewal_orders ) : false;
164+
}
165+
166+
/**
167+
* Gets the renewal orders for a subscription, sorted by the specified property.
168+
*
169+
* @param WC_Subscription $subscription The subscription object.
170+
* @param string $sort_by The subscription property to sort by.
171+
* @param string $order Optional. The sort order to sort by. Default is 'descending'.
172+
*
173+
* @return WC_Order[] The subscriptions renewal orders sorted.
174+
*/
175+
function wcs_get_renewal_orders_sorted_by( $subscription, $sort_by, $order = 'descending' ) {
176+
$renewal_orders = $subscription->get_related_orders( 'all', 'renewal' );
177+
178+
wcs_sort_objects( $renewal_orders, $sort_by, $order );
179+
180+
return $renewal_orders;
181+
}
182+
146183
/**
147184
* Checks if manual renewals are required - automatic renewals are disabled.
148185
*

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"title": "WooCommerce Subscriptions Core",
44
"author": "Automattic",
55
"license": "GPL-3.0-or-later",
6-
"version": "7.1.1",
6+
"version": "7.2.0",
77
"description": "",
88
"homepage": "https://github.com/Automattic/woocommerce-subscriptions-core",
99
"main": "Gruntfile.js",

templates/myaccount/my-subscriptions.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* @author Prospress
66
* @category WooCommerce Subscriptions/Templates
7-
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.6.4
7+
* @version 7.2.0 - Migrated from WooCommerce Subscriptions v2.6.4
88
*/
99

1010
if ( ! defined( 'ABSPATH' ) ) {
@@ -31,7 +31,9 @@
3131
<?php foreach ( $subscriptions as $subscription_id => $subscription ) : ?>
3232
<tr class="order woocommerce-orders-table__row woocommerce-orders-table__row--status-<?php echo esc_attr( $subscription->get_status() ); ?>">
3333
<td class="subscription-id order-number woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-id woocommerce-orders-table__cell-order-number" data-title="<?php esc_attr_e( 'ID', 'woocommerce-subscriptions' ); ?>">
34-
<a href="<?php echo esc_url( $subscription->get_view_order_url() ); ?>"><?php echo esc_html( sprintf( _x( '#%s', 'hash before order number', 'woocommerce-subscriptions' ), $subscription->get_order_number() ) ); ?></a>
34+
<a href="<?php echo esc_url( $subscription->get_view_order_url() ); ?>" aria-label="<?php echo esc_attr( sprintf( __( 'View subscription number %s', 'woocommerce' ), $subscription->get_order_number() ) ) ?>">
35+
<?php echo esc_html( sprintf( _x( '#%s', 'hash before order number', 'woocommerce-subscriptions' ), $subscription->get_order_number() ) ); ?>
36+
</a>
3537
<?php do_action( 'woocommerce_my_subscriptions_after_subscription_id', $subscription ); ?>
3638
</td>
3739
<td class="subscription-status order-status woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-status woocommerce-orders-table__cell-order-status" data-title="<?php esc_attr_e( 'Status', 'woocommerce-subscriptions' ); ?>">

tests/unit/test-wcs-order-functions.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,122 @@ public function test_wcs_get_orders_with_meta_query() {
304304
$this->assertIsArray( $subscriptions );
305305
$this->assertEmpty( $subscriptions );
306306
}
307+
}
308+
309+
public function test_wcs_set_recurring_item_total() {
310+
/**
311+
* Regular subscription item.
312+
*/
313+
$product = WCS_Helper_Product::create_simple_subscription_product( [ 'price' => 10 ] );
314+
315+
$line_item = new WC_Order_Item_Product();
316+
$line_item->set_product( $product );
317+
$line_item->set_quantity( 1 );
318+
$line_item->set_total( 10 );
319+
$line_item->set_subtotal( 10 );
320+
321+
wcs_set_recurring_item_total( $line_item );
322+
323+
$this->assertEquals( 10, $line_item->get_total() );
324+
$this->assertEquals( 10, $line_item->get_subtotal() );
325+
326+
/**
327+
* Subscription item with trial.
328+
*/
329+
$trial_product = WCS_Helper_Product::create_simple_subscription_product(
330+
[
331+
'price' => 20,
332+
'subscription_trial_length' => 10,
333+
]
334+
);
335+
336+
$line_item = new WC_Order_Item_Product();
337+
$line_item->set_product( $trial_product );
338+
$line_item->set_quantity( 1 );
339+
$line_item->set_total( 0 ); // Trial product's are free initially.
340+
$line_item->set_subtotal( 0 );
341+
342+
wcs_set_recurring_item_total( $line_item );
343+
344+
$this->assertEquals( 20, $line_item->get_total() );
345+
$this->assertEquals( 20, $line_item->get_subtotal() );
346+
347+
/**
348+
* Subscription item with sign-up fee.
349+
*/
350+
$sign_up_fee_product = WCS_Helper_Product::create_simple_subscription_product(
351+
[
352+
'price' => 30,
353+
'subscription_sign_up_fee' => 50,
354+
]
355+
);
356+
357+
$line_item = new WC_Order_Item_Product();
358+
$line_item->set_product( $sign_up_fee_product );
359+
$line_item->set_quantity( 1 );
360+
$line_item->set_total( 80 ); // Initial total is the sum of the product price and sign-up fee.
361+
$line_item->set_subtotal( 80 );
362+
363+
wcs_set_recurring_item_total( $line_item );
364+
365+
$this->assertEquals( 30, $line_item->get_total() );
366+
$this->assertEquals( 30, $line_item->get_subtotal() );
367+
368+
/**
369+
* Subscription item with sign-up fee and trial.
370+
*/
371+
$sign_up_fee_trial_product = WCS_Helper_Product::create_simple_subscription_product(
372+
[
373+
'price' => 40,
374+
'subscription_sign_up_fee' => 60,
375+
'subscription_trial_length' => 10,
376+
]
377+
);
378+
379+
$line_item->set_product( $sign_up_fee_trial_product );
380+
$line_item->set_quantity( 1 );
381+
$line_item->set_total( 60 ); // Initial total is just the sign-up fee.
382+
$line_item->set_subtotal( 60 );
383+
384+
wcs_set_recurring_item_total( $line_item );
385+
386+
$this->assertEquals( 40, $line_item->get_total() );
387+
$this->assertEquals( 40, $line_item->get_subtotal() );
388+
389+
/**
390+
* Simple product
391+
*/
392+
$simple_product = WC_Helper_Product::create_simple_product();
393+
394+
$line_item->set_product( $simple_product );
395+
$line_item->set_quantity( 1 );
396+
$line_item->set_total( 50 ); // Default price is $10.00. We set it to $50 here to confirm it's not changed.
397+
$line_item->set_subtotal( 50 );
398+
399+
wcs_set_recurring_item_total( $line_item );
400+
401+
$this->assertEquals( 50, $line_item->get_total() );
402+
$this->assertEquals( 50, $line_item->get_subtotal() );
403+
404+
/**
405+
* Subscription item with quantity.
406+
*/
407+
$sign_up_fee_trial_product = WCS_Helper_Product::create_simple_subscription_product(
408+
[
409+
'price' => 40,
410+
'subscription_sign_up_fee' => 60,
411+
'subscription_trial_length' => 10,
412+
]
413+
);
414+
415+
$line_item->set_product( $sign_up_fee_trial_product );
416+
$line_item->set_quantity( 2 );
417+
$line_item->set_total( 120 ); // Initial total is just the sign-up fee.
418+
$line_item->set_subtotal( 120 );
419+
420+
wcs_set_recurring_item_total( $line_item );
307421

422+
$this->assertEquals( 80, $line_item->get_total() );
423+
$this->assertEquals( 80, $line_item->get_subtotal() );
308424
}
309425
}

woocommerce-subscriptions-core.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
* Author: Automattic
77
* Author URI: https://woocommerce.com/
88
* Requires WP: 5.6
9-
* Version: 7.1.1
9+
* Version: 7.2.0
1010
*/

0 commit comments

Comments
 (0)