Skip to content

Commit 7b8b643

Browse files
authored
Fix currency change for manual subscription renewal. (#5404)
* Fix currency change for manual subscription renewal. * Add tests for new renewal check, also allow continued checks if false is returned. * Add changelog * Fix property assignment type * Update running filters property
1 parent 32d8618 commit 7b8b643

File tree

4 files changed

+93
-3
lines changed

4 files changed

+93
-3
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: fix
3+
4+
Fix ability to change currency when a subscription renewal is in the cart.

includes/multi-currency/Compatibility/WooCommerceSubscriptions.php

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
use WC_Payments_Features;
1111
use WCPay\MultiCurrency\MultiCurrency;
12-
use WCPay\MultiCurrency\Utils;
1312

1413
/**
1514
* Class that controls Multi Currency Compatibility with WooCommerce Subscriptions Plugin and WCPay Subscriptions.
@@ -23,6 +22,13 @@ class WooCommerceSubscriptions extends BaseCompatibility {
2322
*/
2423
public $switch_cart_item = '';
2524

25+
/**
26+
* If we are running through our filters.
27+
*
28+
* @var bool
29+
*/
30+
private $running_override_selected_currency_filters = false;
31+
2632
/**
2733
* Init the class.
2834
*
@@ -142,7 +148,7 @@ public function maybe_disable_mixed_cart( $value ) {
142148
*/
143149
public function override_selected_currency( $return ) {
144150
// If it's not false, return it.
145-
if ( $return ) {
151+
if ( $return || $this->running_override_selected_currency_filters ) {
146152
return $return;
147153
}
148154

@@ -152,6 +158,16 @@ public function override_selected_currency( $return ) {
152158
return $order ? $order->get_currency() : $return;
153159
}
154160

161+
// The running_override_selected_currency_filters property has been added here due to if it isn't, it will create an infinite loop of calls.
162+
if ( WC()->session->get( 'order_awaiting_payment' ) ) {
163+
$this->running_override_selected_currency_filters = true;
164+
$order = wc_get_order( WC()->session->get( 'order_awaiting_payment' ) );
165+
$this->running_override_selected_currency_filters = false;
166+
if ( $order && $this->order_contains_renewal( $order ) ) {
167+
return $order->get_currency();
168+
}
169+
}
170+
155171
$switch_id = $this->get_subscription_switch_id_from_superglobal();
156172
if ( $switch_id ) {
157173
return get_post_meta( $switch_id, '_order_currency', true );
@@ -284,6 +300,20 @@ private function cart_contains_renewal() {
284300
return wcs_cart_contains_renewal();
285301
}
286302

303+
/**
304+
* Checks an order to see if it contains a subscription product renewal.
305+
*
306+
* @param object $order Order object.
307+
*
308+
* @return bool The cart item containing the renewal as an array, else false.
309+
*/
310+
private function order_contains_renewal( $order ): bool {
311+
if ( ! function_exists( 'wcs_order_contains_renewal' ) ) {
312+
return false;
313+
}
314+
return wcs_order_contains_renewal( $order );
315+
}
316+
287317
/**
288318
* Gets the subscription switch items out of the cart.
289319
*

tests/unit/helpers/class-wc-helper-subscriptions.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ function wcs_get_subscriptions( $args ) {
7676
return ( WC_Subscriptions::$wcs_get_subscriptions )( $args );
7777
}
7878

79+
function wcs_order_contains_renewal() {
80+
if ( ! WC_Subscriptions::$wcs_order_contains_renewal ) {
81+
return;
82+
}
83+
return ( WC_Subscriptions::$wcs_order_contains_renewal )();
84+
}
85+
7986
/**
8087
* Class WC_Subscriptions.
8188
*
@@ -159,6 +166,13 @@ class WC_Subscriptions {
159166
*/
160167
public static $wcs_create_renewal_order = null;
161168

169+
/**
170+
* wcs_order_contains_renewal mock.
171+
*
172+
* @var function
173+
*/
174+
public static $wcs_order_contains_renewal = null;
175+
162176
public static function set_wcs_order_contains_subscription( $function ) {
163177
self::$wcs_order_contains_subscription = $function;
164178
}
@@ -198,4 +212,8 @@ public static function wcs_cart_contains_resubscribe( $function ) {
198212
public static function wcs_create_renewal_order( $function ) {
199213
self::$wcs_create_renewal_order = $function;
200214
}
215+
216+
public static function wcs_order_contains_renewal( $function ) {
217+
self::$wcs_order_contains_renewal = $function;
218+
}
201219
}

tests/unit/multi-currency/compatibility/test-class-woocommerce-subscriptions.php

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,12 +272,42 @@ public function test_override_selected_currency_return_currency_code_when_renewa
272272
$order->set_currency( 'JPY' );
273273
$order->save();
274274

275-
// Mock that order as the renewal in the cart.
275+
// Mock that order has the renewal in the cart.
276276
$this->mock_wcs_cart_contains_renewal( 42, $order->get_id() );
277277

278278
$this->assertSame( 'JPY', $this->woocommerce_subscriptions->override_selected_currency( false ) );
279279
}
280280

281+
// Returns order currency code when order awaiting payment has renewal in it.
282+
public function test_override_selected_currency_returns_order_currency_code_when_order_awaiting_payment_has_renewal() {
283+
// Set up an order with a non-default currency.
284+
$order = WC_Helper_Order::create_order();
285+
$order->set_currency( 'JPY' );
286+
$order->save();
287+
WC()->session->set( 'order_awaiting_payment', $order->get_id() );
288+
289+
// Mock that order has the renewal in the cart.
290+
$this->mock_wcs_cart_contains_renewal( false );
291+
$this->mock_wcs_order_contains_renewal( true );
292+
293+
$this->assertSame( 'JPY', $this->woocommerce_subscriptions->override_selected_currency( false ) );
294+
}
295+
296+
// Returns false when order awaiting payment does not have a renewal in it.
297+
public function test_override_selected_currency_return_false_when_order_awaiting_payment_has_no_renewal() {
298+
// Set up an order with a non-default currency.
299+
$order = WC_Helper_Order::create_order();
300+
$order->set_currency( 'JPY' );
301+
$order->save();
302+
WC()->session->set( 'order_awaiting_payment', $order->get_id() );
303+
304+
// Mock that order renewal in the cart.
305+
$this->mock_wcs_cart_contains_renewal( false );
306+
$this->mock_wcs_order_contains_renewal( false );
307+
308+
$this->assertFalse( $this->woocommerce_subscriptions->override_selected_currency( false ) );
309+
}
310+
281311
// Test correct currency when shopper clicks upgrade/downgrade button in My Account – "switch".
282312
public function test_override_selected_currency_return_currency_code_for_switch_request() {
283313
// Reset/clear any previous mocked state.
@@ -628,4 +658,12 @@ function () use ( $subscription_id ) {
628658
}
629659
);
630660
}
661+
662+
private function mock_wcs_order_contains_renewal( $renewal = false ) {
663+
WC_Subscriptions::wcs_order_contains_renewal(
664+
function () use ( $renewal ) {
665+
return $renewal;
666+
}
667+
);
668+
}
631669
}

0 commit comments

Comments
 (0)