Commit 04eaffb3dc6 for woocommerce
commit 04eaffb3dc6940e75bd990158802caace099687f
Author: ThelmaChido <41231764+Thelmachido@users.noreply.github.com>
Date: Thu Jul 16 12:21:09 2026 +0200
Fix broken paid extensions link on update-core.php (#66075) (#66076)
* Fix broken paid extensions link on update-core.php (#66075)
The WooCommerce notice on the Updates screen built the helper URL as
'admin.php?page=' . self::get_source_page() . ' §ion=helper', and the
stray space before §ion was URL-encoded to %20, producing
admin.php?page=wc-admin%20§ion=helper and an access-denied error.
Remove the space so the link resolves correctly. get_source_page() is kept,
so both the wc-admin and wc-addons destinations still work.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Add regression test for the paid extensions helper link (#66075)
Extract the My Subscriptions URL into WC_Helper::get_subscriptions_url()
so it has a testable seam, and add a WC_Helper_Test regression test that
asserts the URL query contains no stray whitespace and targets
section=helper for both the wc-admin and wc-addons source pages. This
guards the exact regression fixed here (a space encoding to %20).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Point paid-extensions notice to Extensions › My Subscriptions
Replace the legacy `§ion=helper` target (which only opened the
WooCommerce landing page, and errored due to a stray space) with the
modern `wc-admin` My Subscriptions route via add_query_arg(). Escape the
URL at the notice call site with esc_url(), and update WC_Helper_Test to
assert the new destination. (#66075)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Thelmachido <thelma.mutete@a8c.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
diff --git a/plugins/woocommerce/changelog/66075-fix-paid-extensions-helper-link b/plugins/woocommerce/changelog/66075-fix-paid-extensions-helper-link
new file mode 100644
index 00000000000..206de0cb5b8
--- /dev/null
+++ b/plugins/woocommerce/changelog/66075-fix-paid-extensions-helper-link
@@ -0,0 +1,3 @@
+Significance: patch
+Type: fix
+Comment: Fix the broken paid extensions link in the WooCommerce notice on the Updates screen so it opens Extensions › My Subscriptions instead of an access-denied page.
diff --git a/plugins/woocommerce/includes/admin/helper/class-wc-helper.php b/plugins/woocommerce/includes/admin/helper/class-wc-helper.php
index 0b6445ead60..68ddf082126 100644
--- a/plugins/woocommerce/includes/admin/helper/class-wc-helper.php
+++ b/plugins/woocommerce/includes/admin/helper/class-wc-helper.php
@@ -136,6 +136,22 @@ class WC_Helper {
return in_array( $page, array( 'wc-admin', 'wc-addons' ), true ) ? $page : 'wc-admin';
}
+ /**
+ * Get the URL of the My Subscriptions screen used in admin notices.
+ *
+ * @return string
+ */
+ private static function get_subscriptions_url() {
+ return add_query_arg(
+ array(
+ 'page' => 'wc-admin',
+ 'tab' => 'my-subscriptions',
+ 'path' => rawurlencode( '/extensions' ),
+ ),
+ admin_url( 'admin.php' )
+ );
+ }
+
/**
* Include supporting helper classes.
*
@@ -2523,7 +2539,7 @@ class WC_Helper {
return sprintf(
/* translators: %1$s: helper url, %2$d: number of extensions */
_n( 'Note: You currently have <a href="%1$s">%2$d paid extension</a> which should be updated first before updating WooCommerce.', 'Note: You currently have <a href="%1$s">%2$d paid extensions</a> which should be updated first before updating WooCommerce.', $available, 'woocommerce' ),
- admin_url( 'admin.php?page=' . self::get_source_page() . ' §ion=helper' ),
+ esc_url( self::get_subscriptions_url() ),
$available
);
}
diff --git a/plugins/woocommerce/tests/php/includes/admin/helper/class-wc-helper-test.php b/plugins/woocommerce/tests/php/includes/admin/helper/class-wc-helper-test.php
index 8209f1bbacc..faa88bad370 100644
--- a/plugins/woocommerce/tests/php/includes/admin/helper/class-wc-helper-test.php
+++ b/plugins/woocommerce/tests/php/includes/admin/helper/class-wc-helper-test.php
@@ -19,6 +19,7 @@ class WC_Helper_Test extends \WC_Unit_Test_Case {
*/
public function tearDown(): void {
$this->cleanup_helper_transients();
+ unset( $_GET['page'] );
parent::tearDown();
}
@@ -291,4 +292,37 @@ class WC_Helper_Test extends \WC_Unit_Test_Case {
$this->assertArrayHasKey( $woocommerce_key, $woo_plugins );
}
+ /**
+ * Invoke the private static WC_Helper::get_subscriptions_url().
+ *
+ * @return string
+ */
+ private function get_subscriptions_url(): string {
+ $method = new ReflectionMethod( WC_Helper::class, 'get_subscriptions_url' );
+ $method->setAccessible( true );
+ return (string) $method->invoke( null );
+ }
+
+ /**
+ * @testdox get_subscriptions_url query contains no stray whitespace (regression: GH #66075).
+ */
+ public function test_subscriptions_url_query_has_no_whitespace(): void {
+ $_GET['page'] = 'wc-admin';
+
+ $query = wp_parse_url( $this->get_subscriptions_url(), PHP_URL_QUERY );
+
+ $this->assertIsString( $query );
+ $this->assertStringNotContainsString( ' ', $query );
+ $this->assertStringNotContainsString( '%20', $query );
+ }
+
+ /**
+ * @testdox get_subscriptions_url targets the Extensions - My Subscriptions screen.
+ */
+ public function test_subscriptions_url_targets_my_subscriptions(): void {
+ $this->assertStringEndsWith(
+ 'admin.php?page=wc-admin&tab=my-subscriptions&path=%2Fextensions',
+ $this->get_subscriptions_url()
+ );
+ }
}