Commit faa3db04c04 for woocommerce
commit faa3db04c0455fc1d6cb8779042ce4e83bbb455e
Author: Daniel Mallory <daniel.mallory@automattic.com>
Date: Thu Jul 23 11:43:23 2026 +0100
Clear cached provider lists with the payment providers cache (#66909)
* fix(payments): Clear provider lists with the providers service cache
The Payments service caches assembled provider lists per request, while
PaymentsProviders::clear_cache() and the deprecated reset_memo() clear
only the lower gateway caches. Before the request cache landed, the
lower reset was the only cache and guaranteed fresh reads, so code that
mutates gateway state and calls it can now be served a pre-mutation
provider list within the same request.
Move the provider-lists cache identity to the providers service and
delete that entry in clear_cache() too, restoring the lower reset as a
full invalidation. Payments keeps its private constants as aliases.
Refs #66865
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(payments): Explain the provider lists delete in clear_cache
Payments::clear_cache() deletes the provider lists entry before
delegating to PaymentsProviders::clear_cache(), which deletes it again.
The second delete reads as a duplicate and was flagged as one in review,
but it is the reach-up invalidation that keeps direct callers of the
lower service from reading stale lists. Note this at the delete site so
it doesn't get removed as redundant.
Refs #66865
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(payments): Register the provider lists cache group in the providers service
The guarantee that the provider_lists group never reaches a persistent
object cache rested on Payments::init() having run, since only that
class registered the group non-persistent. PaymentsProviders touches
the group too now, so register it in PaymentsProviders::init() as well.
Each service registers every group it touches and no longer depends on
the other layer's initialization order. Registering a group twice is
harmless; cache drop-ins merge the lists.
Suggested by @vladolaru in PR #66909 review.
Refs #66865
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
diff --git a/plugins/woocommerce/changelog/fix-66865-providers-cache-invalidation b/plugins/woocommerce/changelog/fix-66865-providers-cache-invalidation
new file mode 100644
index 00000000000..164765c768e
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-66865-providers-cache-invalidation
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Clear cached payment provider lists when the payment providers service cache is cleared.
diff --git a/plugins/woocommerce/src/Internal/Admin/Settings/Payments.php b/plugins/woocommerce/src/Internal/Admin/Settings/Payments.php
index a702a04c9f7..061531911da 100644
--- a/plugins/woocommerce/src/Internal/Admin/Settings/Payments.php
+++ b/plugins/woocommerce/src/Internal/Admin/Settings/Payments.php
@@ -29,8 +29,8 @@ class Payments {
const FROM_ADDITIONAL_PAYMENTS_TASK = 'WCADMIN_ADDITIONAL_PAYMENT_TASK';
const FROM_PROVIDER_ONBOARDING = 'PROVIDER_ONBOARDING';
- private const PROVIDERS_REQUEST_CACHE_GROUP = 'woocommerce_payments_providers';
- private const PROVIDERS_REQUEST_CACHE_KEY = 'provider_lists';
+ private const PROVIDERS_REQUEST_CACHE_GROUP = PaymentsProviders::PROVIDER_LISTS_REQUEST_CACHE_GROUP;
+ private const PROVIDERS_REQUEST_CACHE_KEY = PaymentsProviders::PROVIDER_LISTS_REQUEST_CACHE_KEY;
/**
* The payment providers service.
diff --git a/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsProviders.php b/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsProviders.php
index 529e1156b14..8c33f125d6e 100644
--- a/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsProviders.php
+++ b/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsProviders.php
@@ -84,6 +84,9 @@ class PaymentsProviders {
private const GATEWAY_DETAILS_REQUEST_CACHE_GROUP = 'woocommerce_payment_gateway_details';
private const GATEWAY_DETAILS_REQUEST_CACHE_KEY = 'gateway_details';
+ public const PROVIDER_LISTS_REQUEST_CACHE_GROUP = 'woocommerce_payments_providers';
+ public const PROVIDER_LISTS_REQUEST_CACHE_KEY = 'provider_lists';
+
/*
* The provider link types.
*
@@ -228,7 +231,7 @@ class PaymentsProviders {
$this->extension_suggestions = $payment_extension_suggestions;
$this->proxy = $proxy;
- wp_cache_add_non_persistent_groups( array( self::GATEWAY_DETAILS_REQUEST_CACHE_GROUP ) );
+ wp_cache_add_non_persistent_groups( array( self::GATEWAY_DETAILS_REQUEST_CACHE_GROUP, self::PROVIDER_LISTS_REQUEST_CACHE_GROUP ) );
}
/**
@@ -1246,7 +1249,8 @@ class PaymentsProviders {
}
/**
- * Clear cached payment gateway data.
+ * Clear cached payment gateway data, including the provider lists the
+ * Payments service derives from it.
*
* Call after changing gateway registration, settings, or account state during a request.
* Also useful for testing purposes.
@@ -1260,6 +1264,8 @@ class PaymentsProviders {
$this->payment_gateways_cache = array();
$this->payment_gateways_for_display_cache = array();
wp_cache_delete( self::GATEWAY_DETAILS_REQUEST_CACHE_KEY, self::GATEWAY_DETAILS_REQUEST_CACHE_GROUP );
+ // The Payments service owns and also clears this cache; deleting it here keeps direct callers of this service from reading stale provider lists.
+ wp_cache_delete( self::PROVIDER_LISTS_REQUEST_CACHE_KEY, self::PROVIDER_LISTS_REQUEST_CACHE_GROUP );
}
/**
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsProvidersTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsProvidersTest.php
index 920731b7904..4c4f1767d63 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsProvidersTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsProvidersTest.php
@@ -1117,6 +1117,24 @@ class PaymentsProvidersTest extends WC_Unit_Test_Case {
$this->assertSame( 4, $third_us['_order'] );
}
+ /**
+ * @testdox clear_cache removes provider lists cached by the Payments service.
+ */
+ public function test_clear_cache_removes_cached_provider_lists(): void {
+ wp_cache_set(
+ PaymentsProviders::PROVIDER_LISTS_REQUEST_CACHE_KEY,
+ array( 'US_display' => array( array( 'id' => 'stale-provider' ) ) ),
+ PaymentsProviders::PROVIDER_LISTS_REQUEST_CACHE_GROUP
+ );
+
+ $this->sut->clear_cache();
+
+ $this->assertFalse(
+ wp_cache_get( PaymentsProviders::PROVIDER_LISTS_REQUEST_CACHE_KEY, PaymentsProviders::PROVIDER_LISTS_REQUEST_CACHE_GROUP ),
+ 'Provider lists derived from gateway data must not survive a providers cache clear.'
+ );
+ }
+
/**
* Test that get_payment_gateway_details does not override gateway details with those from the suggestion
* when they exist.