Commit 790dcfaa3c5 for woocommerce
commit 790dcfaa3c5607574700a5f0b9881ca79dea8377
Author: Noruzzaman <noruzzamanrubel@gmail.com>
Date: Tue Oct 27 00:15:27 2026 +0600
Leverage is_admin() gate when initializing analytics integrations (#70070)
* Leverage is_admin() gate when initializing analytics integrations
* Keep analytics debug tools and user data filters available in REST and CLI contexts
* Avoid duplicate refund tool visibility checks
---------
Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com>
diff --git a/plugins/woocommerce/changelog/perf-69797-analytics-is-admin-gate b/plugins/woocommerce/changelog/perf-69797-analytics-is-admin-gate
new file mode 100644
index 00000000000..726274694c4
--- /dev/null
+++ b/plugins/woocommerce/changelog/perf-69797-analytics-is-admin-gate
@@ -0,0 +1,4 @@
+Significance: patch
+Type: performance
+
+Leverage is_admin() gate when initializing analytics to avoid running admin-specific logic and queries in non-admin contexts.
diff --git a/plugins/woocommerce/src/Internal/Admin/Analytics.php b/plugins/woocommerce/src/Internal/Admin/Analytics.php
index 7ef1603dd63..23b2d503949 100644
--- a/plugins/woocommerce/src/Internal/Admin/Analytics.php
+++ b/plugins/woocommerce/src/Internal/Admin/Analytics.php
@@ -5,6 +5,7 @@
namespace Automattic\WooCommerce\Internal\Admin;
+use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Admin\API\Reports\Cache;
use Automattic\WooCommerce\Utilities\OrderUtil;
use Automattic\WooCommerce\Utilities\FeaturesUtil;
@@ -110,25 +111,47 @@ class Analytics {
return;
}
- add_filter( 'woocommerce_component_settings_preload_endpoints', array( $this, 'add_preload_endpoints' ) );
- add_filter( 'woocommerce_admin_get_user_data_fields', array( $this, 'add_user_data_fields' ) );
- add_action( 'admin_menu', array( $this, 'register_pages' ) );
- add_filter( 'woocommerce_debug_tools', array( $this, 'register_cache_clear_tool' ) );
- add_filter( 'woocommerce_debug_tools', array( $this, 'register_regenerate_order_fulfillment_status_tool' ), 12 );
-
// Always register the batch hook so in-flight jobs survive after the legacy
// flag is cleared (clearing happens before the first batch is queued).
add_action( 'woocommerce_analytics_refund_fix_batch', array( $this, 'process_refund_fix_batch' ) );
// Merchant-triggered repair of refunds double-counted before #66320.
- add_filter( 'woocommerce_debug_tools', array( $this, 'register_refund_double_count_tool' ) );
add_action( self::REFUND_DOUBLE_COUNT_FIX_HOOK, array( $this, 'process_refund_double_count_fix_batch' ), 10, 2 );
add_action( 'woocommerce_analytics_regenerate_init', array( $this, 'maybe_cancel_refund_double_count_fix_on_regenerate' ), 10, 2 );
- if ( self::should_show_refund_fix_tool() ) {
+ $is_admin = is_admin();
+ $is_rest = self::is_rest_request();
+ $is_cli = self::is_cli_request();
+
+ if ( ! $is_admin && ! $is_rest && ! $is_cli ) {
+ return;
+ }
+
+ $should_show_refund_fix_tool = self::should_show_refund_fix_tool();
+
+ // Register debug tools in admin, REST, and WP-CLI contexts where they can be consumed.
+ add_filter( 'woocommerce_debug_tools', array( $this, 'register_cache_clear_tool' ) );
+ add_filter( 'woocommerce_debug_tools', array( $this, 'register_regenerate_order_fulfillment_status_tool' ), 12 );
+ add_filter( 'woocommerce_debug_tools', array( $this, 'register_refund_double_count_tool' ) );
+
+ if ( $should_show_refund_fix_tool ) {
add_filter( 'woocommerce_debug_tools', array( $this, 'register_full_refund_fix_data_tool' ) );
- add_action( 'admin_footer', array( $this, 'output_refund_fix_tool_js' ) );
- add_action( 'wp_ajax_woocommerce_check_refund_fix_needed', array( $this, 'ajax_check_refund_fix_needed' ) );
+ }
+
+ // User data preferences are read and updated in admin and REST contexts.
+ if ( $is_admin || $is_rest ) {
+ add_filter( 'woocommerce_admin_get_user_data_fields', array( $this, 'add_user_data_fields' ) );
+ }
+
+ // Admin-only UI screens, menus, and client-side assets.
+ if ( $is_admin ) {
+ add_filter( 'woocommerce_component_settings_preload_endpoints', array( $this, 'add_preload_endpoints' ) );
+ add_action( 'admin_menu', array( $this, 'register_pages' ) );
+
+ if ( $should_show_refund_fix_tool ) {
+ add_action( 'admin_footer', array( $this, 'output_refund_fix_tool_js' ) );
+ add_action( 'wp_ajax_woocommerce_check_refund_fix_needed', array( $this, 'ajax_check_refund_fix_needed' ) );
+ }
}
}
@@ -263,6 +286,25 @@ class Analytics {
|| 'yes' === get_option( 'woocommerce_analytics_show_old_refund_data_tool' );
}
+ /**
+ * Check whether the current execution context is a REST API request.
+ *
+ * @return bool
+ */
+ private static function is_rest_request(): bool {
+ return Constants::is_true( 'REST_REQUEST' )
+ || ( function_exists( 'WC' ) && WC() && WC()->is_rest_api_request() );
+ }
+
+ /**
+ * Check whether the current execution context is WP-CLI.
+ *
+ * @return bool
+ */
+ private static function is_cli_request(): bool {
+ return Constants::is_true( 'WP_CLI' );
+ }
+
/**
* Register the full refund fix data tool on the WooCommerce > Status > Tools page.
*
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/AnalyticsTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/AnalyticsTest.php
index 35f0b07be24..7351fb8aed7 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/AnalyticsTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/AnalyticsTest.php
@@ -3,6 +3,7 @@ declare( strict_types = 1 );
namespace Automattic\WooCommerce\Tests\Internal\Admin;
+use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Internal\Admin\Analytics;
use Automattic\WooCommerce\Internal\Admin\Schedulers\OrdersScheduler;
@@ -825,4 +826,234 @@ class AnalyticsTest extends WC_Unit_Test_Case {
// The tool still offers to run, rather than reporting that nothing was found.
$this->assertStringContainsString( 'Check and fix', $this->get_tool()['button'] );
}
+
+ /**
+ * Verify that admin integrations are not registered in non-admin contexts.
+ *
+ * @testdox Admin integrations are not registered in non-admin contexts.
+ */
+ public function test_admin_integrations_not_registered_in_non_admin_context(): void {
+ set_current_screen( 'front' );
+
+ $analytics = new Analytics();
+
+ try {
+ $this->assertFalse(
+ has_filter( 'woocommerce_component_settings_preload_endpoints', array( $analytics, 'add_preload_endpoints' ) ),
+ 'Preload endpoints filter should not be registered outside the admin area.'
+ );
+ $this->assertFalse(
+ has_filter( 'woocommerce_admin_get_user_data_fields', array( $analytics, 'add_user_data_fields' ) ),
+ 'User data fields filter should not be registered outside the admin area.'
+ );
+ $this->assertFalse(
+ has_action( 'admin_menu', array( $analytics, 'register_pages' ) ),
+ 'Admin menu action should not be registered outside the admin area.'
+ );
+ $this->assertFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_cache_clear_tool' ) ),
+ 'Cache clear tool filter should not be registered outside the admin area.'
+ );
+ $this->assertFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_regenerate_order_fulfillment_status_tool' ) ),
+ 'Regenerate fulfillment status tool filter should not be registered outside the admin area.'
+ );
+ $this->assertFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_refund_double_count_tool' ) ),
+ 'Refund double-count tool filter should not be registered outside the admin area.'
+ );
+ $this->assertFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_full_refund_fix_data_tool' ) ),
+ 'Full refund fix tool filter should not be registered outside the admin area.'
+ );
+ $this->assertFalse(
+ has_action( 'admin_footer', array( $analytics, 'output_refund_fix_tool_js' ) ),
+ 'Admin footer action should not be registered outside the admin area.'
+ );
+ $this->assertFalse(
+ has_action( 'wp_ajax_woocommerce_check_refund_fix_needed', array( $analytics, 'ajax_check_refund_fix_needed' ) ),
+ 'AJAX check refund fix action should not be registered outside the admin area.'
+ );
+
+ // Background Action Scheduler hooks must always be registered.
+ $this->assertNotFalse(
+ has_action( 'woocommerce_analytics_refund_fix_batch', array( $analytics, 'process_refund_fix_batch' ) ),
+ 'Refund fix batch hook must remain registered in non-admin contexts for background execution.'
+ );
+ $this->assertNotFalse(
+ has_action( Analytics::REFUND_DOUBLE_COUNT_FIX_HOOK, array( $analytics, 'process_refund_double_count_fix_batch' ) ),
+ 'Refund double count fix batch hook must remain registered in non-admin contexts for background execution.'
+ );
+ $this->assertNotFalse(
+ has_action( 'woocommerce_analytics_regenerate_init', array( $analytics, 'maybe_cancel_refund_double_count_fix_on_regenerate' ) ),
+ 'Regenerate cancel hook must remain registered in non-admin contexts.'
+ );
+ } finally {
+ remove_action( 'woocommerce_analytics_refund_fix_batch', array( $analytics, 'process_refund_fix_batch' ) );
+ remove_action( Analytics::REFUND_DOUBLE_COUNT_FIX_HOOK, array( $analytics, 'process_refund_double_count_fix_batch' ) );
+ remove_action( 'woocommerce_analytics_regenerate_init', array( $analytics, 'maybe_cancel_refund_double_count_fix_on_regenerate' ) );
+ set_current_screen( 'dashboard' );
+ }
+ }
+
+ /**
+ * Verify that admin integrations are registered in admin contexts.
+ *
+ * @testdox Admin integrations are registered in admin contexts.
+ */
+ public function test_admin_integrations_registered_in_admin_context(): void {
+ set_current_screen( 'dashboard' );
+
+ $analytics = new Analytics();
+
+ try {
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_component_settings_preload_endpoints', array( $analytics, 'add_preload_endpoints' ) ),
+ 'Preload endpoints filter should be registered in the admin area.'
+ );
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_admin_get_user_data_fields', array( $analytics, 'add_user_data_fields' ) ),
+ 'User data fields filter should be registered in the admin area.'
+ );
+ $this->assertNotFalse(
+ has_action( 'admin_menu', array( $analytics, 'register_pages' ) ),
+ 'Admin menu action should be registered in the admin area.'
+ );
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_cache_clear_tool' ) ),
+ 'Cache clear tool filter should be registered in the admin area.'
+ );
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_regenerate_order_fulfillment_status_tool' ) ),
+ 'Regenerate fulfillment status tool filter should be registered in the admin area.'
+ );
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_refund_double_count_tool' ) ),
+ 'Refund double-count tool filter should be registered in the admin area.'
+ );
+ } finally {
+ remove_filter( 'woocommerce_component_settings_preload_endpoints', array( $analytics, 'add_preload_endpoints' ) );
+ remove_filter( 'woocommerce_admin_get_user_data_fields', array( $analytics, 'add_user_data_fields' ) );
+ remove_action( 'admin_menu', array( $analytics, 'register_pages' ) );
+ remove_filter( 'woocommerce_debug_tools', array( $analytics, 'register_cache_clear_tool' ) );
+ remove_filter( 'woocommerce_debug_tools', array( $analytics, 'register_regenerate_order_fulfillment_status_tool' ), 12 );
+ remove_filter( 'woocommerce_debug_tools', array( $analytics, 'register_refund_double_count_tool' ) );
+ remove_action( 'woocommerce_analytics_refund_fix_batch', array( $analytics, 'process_refund_fix_batch' ) );
+ remove_action( Analytics::REFUND_DOUBLE_COUNT_FIX_HOOK, array( $analytics, 'process_refund_double_count_fix_batch' ) );
+ remove_action( 'woocommerce_analytics_regenerate_init', array( $analytics, 'maybe_cancel_refund_double_count_fix_on_regenerate' ) );
+ }
+ }
+
+ /**
+ * Verify that user data and debug tools are registered in REST context, while admin UI is not.
+ *
+ * @testdox User data fields and debug tools are registered in REST context.
+ */
+ public function test_integrations_registered_in_rest_context(): void {
+ set_current_screen( 'front' );
+ Constants::set_constant( 'REST_REQUEST', true );
+
+ $analytics = new Analytics();
+
+ try {
+ // Debug tools must be available in REST.
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_cache_clear_tool' ) ),
+ 'Cache clear tool filter should be registered in REST context.'
+ );
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_regenerate_order_fulfillment_status_tool' ) ),
+ 'Regenerate fulfillment status tool filter should be registered in REST context.'
+ );
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_refund_double_count_tool' ) ),
+ 'Refund double-count tool filter should be registered in REST context.'
+ );
+
+ // User data fields must be available in REST.
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_admin_get_user_data_fields', array( $analytics, 'add_user_data_fields' ) ),
+ 'User data fields filter should be registered in REST context.'
+ );
+
+ // Admin UI must not be registered in REST.
+ $this->assertFalse(
+ has_filter( 'woocommerce_component_settings_preload_endpoints', array( $analytics, 'add_preload_endpoints' ) ),
+ 'Preload endpoints filter should not be registered in REST context.'
+ );
+ $this->assertFalse(
+ has_action( 'admin_menu', array( $analytics, 'register_pages' ) ),
+ 'Admin menu action should not be registered in REST context.'
+ );
+ $this->assertFalse(
+ has_action( 'admin_footer', array( $analytics, 'output_refund_fix_tool_js' ) ),
+ 'Admin footer action should not be registered in REST context.'
+ );
+ } finally {
+ Constants::clear_single_constant( 'REST_REQUEST' );
+ remove_filter( 'woocommerce_debug_tools', array( $analytics, 'register_cache_clear_tool' ) );
+ remove_filter( 'woocommerce_debug_tools', array( $analytics, 'register_regenerate_order_fulfillment_status_tool' ), 12 );
+ remove_filter( 'woocommerce_debug_tools', array( $analytics, 'register_refund_double_count_tool' ) );
+ remove_filter( 'woocommerce_admin_get_user_data_fields', array( $analytics, 'add_user_data_fields' ) );
+ remove_action( 'woocommerce_analytics_refund_fix_batch', array( $analytics, 'process_refund_fix_batch' ) );
+ remove_action( Analytics::REFUND_DOUBLE_COUNT_FIX_HOOK, array( $analytics, 'process_refund_double_count_fix_batch' ) );
+ remove_action( 'woocommerce_analytics_regenerate_init', array( $analytics, 'maybe_cancel_refund_double_count_fix_on_regenerate' ) );
+ set_current_screen( 'dashboard' );
+ }
+ }
+
+ /**
+ * Verify that debug tools are registered in WP-CLI context, while user data and admin UI are not.
+ *
+ * @testdox Debug tools are registered in WP-CLI context.
+ */
+ public function test_integrations_registered_in_cli_context(): void {
+ set_current_screen( 'front' );
+ Constants::set_constant( 'WP_CLI', true );
+
+ $analytics = new Analytics();
+
+ try {
+ // Debug tools must be available in WP-CLI.
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_cache_clear_tool' ) ),
+ 'Cache clear tool filter should be registered in WP-CLI context.'
+ );
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_regenerate_order_fulfillment_status_tool' ) ),
+ 'Regenerate fulfillment status tool filter should be registered in WP-CLI context.'
+ );
+ $this->assertNotFalse(
+ has_filter( 'woocommerce_debug_tools', array( $analytics, 'register_refund_double_count_tool' ) ),
+ 'Refund double-count tool filter should be registered in WP-CLI context.'
+ );
+
+ // User data fields and admin UI must not be registered in WP-CLI.
+ $this->assertFalse(
+ has_filter( 'woocommerce_admin_get_user_data_fields', array( $analytics, 'add_user_data_fields' ) ),
+ 'User data fields filter should not be registered in WP-CLI context.'
+ );
+ $this->assertFalse(
+ has_filter( 'woocommerce_component_settings_preload_endpoints', array( $analytics, 'add_preload_endpoints' ) ),
+ 'Preload endpoints filter should not be registered in WP-CLI context.'
+ );
+ $this->assertFalse(
+ has_action( 'admin_menu', array( $analytics, 'register_pages' ) ),
+ 'Admin menu action should not be registered in WP-CLI context.'
+ );
+ $this->assertFalse(
+ has_action( 'admin_footer', array( $analytics, 'output_refund_fix_tool_js' ) ),
+ 'Admin footer action should not be registered in WP-CLI context.'
+ );
+ } finally {
+ Constants::clear_single_constant( 'WP_CLI' );
+ remove_filter( 'woocommerce_debug_tools', array( $analytics, 'register_cache_clear_tool' ) );
+ remove_filter( 'woocommerce_debug_tools', array( $analytics, 'register_regenerate_order_fulfillment_status_tool' ), 12 );
+ remove_filter( 'woocommerce_debug_tools', array( $analytics, 'register_refund_double_count_tool' ) );
+ remove_action( 'woocommerce_analytics_refund_fix_batch', array( $analytics, 'process_refund_fix_batch' ) );
+ remove_action( Analytics::REFUND_DOUBLE_COUNT_FIX_HOOK, array( $analytics, 'process_refund_double_count_fix_batch' ) );
+ remove_action( 'woocommerce_analytics_regenerate_init', array( $analytics, 'maybe_cancel_refund_double_count_fix_on_regenerate' ) );
+ set_current_screen( 'dashboard' );
+ }
+ }
}