PluginUs.Net - Business Tools for WooCommerce and WordPress

[realize your idea - make your dreams come true]
Botoscope is currently in early access

Support Forum

You need to log-in to create request (topic) to the support

Bug report — WooCommerce Currency Switcher (FOX) 2.5.0

The support doesn work on Saturdays and Sundays, so some Friday requests can be answered on Monday. If you have problems with registration ask help on contact us page please
If you not got email within 24~36 business hours, firstly check your spam box, and if no any email from the support there - back to the forum and read answer here. DO NOT ANSWER ON EMAILS [noreply@pluginus.net] FROM THE FORUM!! Emails are just for your info, all answers should be published only here.
The support doesn work on Saturdays and Sundays, so some Friday requests can be answered on Monday.

# Bug report — WooCommerce Currency Switcher (FOX) 2.5.0

**To:** PluginUS support / CodeCanyon item support
**Severity:** Critical — breaks WooCommerce checkout completion on any site with HPOS disabled
**Affected version:** 2.5.0 (2.4.x not affected)

---

## Summary

In 2.5.0, `WOOCS::woocommerce_get_order_currency()` causes **infinite recursion** whenever an order object's currency is read on the front end and **HPOS (High-Performance Order Storage) is disabled**.

The practical effect: the WooCommerce **order-received /"Thank you" page returns HTTP 500**. The order and payment complete correctly, but the customer sees *"There has been a critical error on this website."* instead of confirmation — so customers believe their purchase failed.

## Environment

| | |
|---|---|
| FOX version | 2.5.0 (regression; 2.4.x unaffected) |
| WooCommerce | 10.9.4 |
| WordPress | 6.9.5 |
| PHP | 8.3 |
| **HPOS** | **disabled** (`woocommerce_custom_orders_table_enabled = no`; 532 orders in legacy `wp_posts` storage) |
| Other | WPML multi-currency in use |

## Root cause

`classes/woocs.php` line 379 registers a handler on the order-currency filter:

```php
add_action( 'woocommerce_order_get_currency', array( $this, 'woocommerce_get_order_currency' ), 1, 2 );
```

The handler (line 3629) contains an **HPOS early-return guard**, then calls `$order->get_currency()`:

```php
public function woocommerce_get_order_currency( $order_currency, $order ) {
// HPOS
if ( $this->woocs_hpos->isEnabledHpos() ) {
return $order_currency; // <-- guarded path, no recursion
}

if ( ! wp_doing_ajax() and ! is_admin() and is_object( $order ) ) {
...
$currency = $order ? $order->get_currency() : get_post_meta( $order_id, '_order_currency', true );
// ^^^^^^^^^^^^^^^^^^^^^ re-fires the very filter we are inside
...
}

return $order_currency;
}
```

`WC_Abstract_Order::get_currency()` → `WC_Data::get_prop()` → `apply_filters( 'woocommerce_order_get_currency', ... )` → **this same handler again**, with no recursion guard.

**When HPOS is enabled the early return prevents this**, which is presumably why it was not caught in testing. With HPOS disabled the guard is skipped and the call recurses until the process dies.

## Observed stack (repeating 4-frame cycle)

```
#0 woocommerce/includes/abstracts/abstract-wc-data.php(939): WC_Data->get_hook_prefix()
#1 woocommerce/includes/abstracts/abstract-wc-order.php(346): WC_Data->get_prop()
#2 woocommerce-currency-switcher/classes/woocs.php(3642): WC_Abstract_Order->get_currency()
#3 wp-includes/class-wp-hook.php(341): WOOCS->woocommerce_get_order_currency()
#4 wp-includes/plugin.php(205): WP_Hook->apply_filters()
#5 woocommerce/includes/abstracts/abstract-wc-data.php(939): apply_filters()
... repeats until stack/memory exhausted
```

With Xdebug present this aborts cleanly:

```
PHP Fatal error: Uncaught Error: Xdebug has detected a possible infinite loop,
and aborted your script with a stack depth of '512' frames
```

Without Xdebug (production) it instead exhausts memory, and the fatal is reported at whatever allocation happens to fail next — so the reported file/line **varies between runs** (`abstract-wc-deprecated-hooks.php`, `class-wp-hook.php`, `plugin.php`, WPML's `ClassLoader.php`). This makes the bug appear to be caused by unrelated plugins, which cost us several hours of misdiagnosis. Raising `WP_MEMORY_LIMIT` from 512M to 768M did not help — it simply consumed more before dying.

## Steps to reproduce

1. WooCommerce with **HPOS disabled** (legacy post storage)
2. Install FOX 2.5.0
3. Place any order
4. Visit the order-received URL: `/checkout/order-received/{id}/?key={order_key}`
5. → HTTP 500; error log shows infinite recursion / memory exhaustion

Deactivating FOX 2.5.0 makes the same URL return HTTP 200 immediately (verified: 500 → 200, page renders"Thank you. Your order has been received.").

## Suggested fix

Read the currency without re-entering the filter, e.g. read the raw prop / post meta directly, or add a re-entrancy guard:

```php
public function woocommerce_get_order_currency( $order_currency, $order ) {
static $in_progress = false;
if ( $in_progress ) {
return $order_currency;
}
$in_progress = true;
// ... existing logic ...
$in_progress = false;
return $order_currency;
}
```

Given `$order_currency` is already passed into the handler as the first argument, calling `$order->get_currency()` appears unnecessary — using `$order_currency` directly would avoid the recursion entirely.

## Impact for us

Live e-commerce site; every customer completing a booking saw a critical-error page after paying. Mitigated by deactivating FOX, which disables multi-currency display for our customers — we would like to restore it once fixed.

Please confirm whether a 2.5.1 is planned, and in the meantime where we can download **2.4.9** (the version we upgraded from) — the CodeCanyon archive only exposes up to 2.4.2.x.