Commit ee4e3beec40 for woocommerce

commit ee4e3beec40259087e6dcf80394b01be052a93cc
Author: Barry Hughes <3594411+barryhughes@users.noreply.github.com>
Date:   Thu Oct 29 12:59:36 2026 -0700

    Migrate analytics import and count cache scheduling to ActionSchedulerUtil (#70155)

    * Migrate analytics import and count cache scheduling to ActionSchedulerUtil

    OrdersScheduler and both count cache services schedule their recurring actions through the util. OrdersScheduler schedules nothing, with a doing-it-wrong notice, when the woocommerce_analytics_import_interval filter returns a non-numeric value.

    Split from #69847 (WOOPLUG-2435).

    Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

    * Fall back to the default import interval when the filter value is invalid

    * Validate the import interval after casting so sub-second values fall back

    ---------

    Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

diff --git a/plugins/woocommerce/changelog/update-wooplug-2435-migrate-as-calls-analytics-caches b/plugins/woocommerce/changelog/update-wooplug-2435-migrate-as-calls-analytics-caches
new file mode 100644
index 00000000000..015a2bb07cd
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-wooplug-2435-migrate-as-calls-analytics-caches
@@ -0,0 +1,3 @@
+Significance: patch
+Type: update
+Comment: Covered by the base PR changelog entry (#69846).
diff --git a/plugins/woocommerce/src/Caches/OrderCountCacheService.php b/plugins/woocommerce/src/Caches/OrderCountCacheService.php
index f72b5fba0f1..c8f2648eb90 100644
--- a/plugins/woocommerce/src/Caches/OrderCountCacheService.php
+++ b/plugins/woocommerce/src/Caches/OrderCountCacheService.php
@@ -6,6 +6,7 @@ namespace Automattic\WooCommerce\Caches;

 use WC_Order;
 use Automattic\WooCommerce\Enums\OrderStatus;
+use Automattic\WooCommerce\Internal\Utilities\ActionSchedulerUtil;
 use Automattic\WooCommerce\Utilities\OrderUtil;

 /**
@@ -119,7 +120,7 @@ class OrderCountCacheService {
 		$frequency   = HOUR_IN_SECONDS * 12;
 		$timestamp   = time() + $frequency;
 		foreach ( $order_types as $order_type ) {
-			as_schedule_recurring_action( $timestamp, $frequency, self::BACKGROUND_EVENT_HOOK, array( $order_type ), 'count', true );
+			ActionSchedulerUtil::schedule_recurring( $timestamp, $frequency, self::BACKGROUND_EVENT_HOOK, array( $order_type ), 'count', true );
 		}
 	}

diff --git a/plugins/woocommerce/src/Caches/ProductCountCacheService.php b/plugins/woocommerce/src/Caches/ProductCountCacheService.php
index 3a0f8a9d468..8364edb497e 100644
--- a/plugins/woocommerce/src/Caches/ProductCountCacheService.php
+++ b/plugins/woocommerce/src/Caches/ProductCountCacheService.php
@@ -4,6 +4,7 @@ declare( strict_types=1 );

 namespace Automattic\WooCommerce\Caches;

+use Automattic\WooCommerce\Internal\Utilities\ActionSchedulerUtil;
 use Automattic\WooCommerce\Internal\Utilities\ProductUtil;
 use WC_Product;
 use WP_Post;
@@ -103,7 +104,7 @@ class ProductCountCacheService {
 	public function schedule_background_actions(): void {
 		$frequency = HOUR_IN_SECONDS * 12;
 		$timestamp = time() + $frequency;
-		as_schedule_recurring_action( $timestamp, $frequency, self::BACKGROUND_EVENT_HOOK, array( 'product' ), 'count', true );
+		ActionSchedulerUtil::schedule_recurring( $timestamp, $frequency, self::BACKGROUND_EVENT_HOOK, array( 'product' ), 'count', true );
 	}

 	/**
diff --git a/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php b/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php
index 858c625fe31..e48fc96a12e 100644
--- a/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php
+++ b/plugins/woocommerce/src/Internal/Admin/Schedulers/OrdersScheduler.php
@@ -534,9 +534,7 @@ AND status NOT IN ( 'wc-auto-draft', 'trash', 'auto-draft' )
 			return;
 		}

-		$interval = self::get_import_interval();
-
-		as_schedule_recurring_action( time(), $interval, $action_hook, array(), static::$group ?? '', true );
+		ActionSchedulerUtil::schedule_recurring( time(), self::get_import_interval(), $action_hook, array(), static::$group ?? '', true );
 	}

 	/**
@@ -728,7 +726,15 @@ AND status NOT IN ( 'wc-auto-draft', 'trash', 'auto-draft' )
 		 * @since 10.4.0
 		 * @param int $interval The import interval in seconds. Default is 12 hours.
 		 */
-		return apply_filters( 'woocommerce_analytics_import_interval', 12 * HOUR_IN_SECONDS );
+		$interval = apply_filters( 'woocommerce_analytics_import_interval', 12 * HOUR_IN_SECONDS );
+		$seconds  = is_numeric( $interval ) && is_finite( (float) $interval ) && $interval <= PHP_INT_MAX ? (int) $interval : 0;
+
+		if ( $seconds < 1 ) {
+			wc_doing_it_wrong( __METHOD__, 'The woocommerce_analytics_import_interval filter must return a positive number of seconds; the 12 hour default was used.', '11.4.0' );
+			return 12 * HOUR_IN_SECONDS;
+		}
+
+		return $seconds;
 	}

 	/**
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/Schedulers/OrdersSchedulerTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/Schedulers/OrdersSchedulerTest.php
index 3e6fb605888..797c82ca3d8 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Admin/Schedulers/OrdersSchedulerTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/Schedulers/OrdersSchedulerTest.php
@@ -115,6 +115,62 @@ class OrdersSchedulerTest extends WC_Unit_Test_Case {
 		);
 	}

+	/**
+	 * Filter values that cannot be used as an import interval.
+	 *
+	 * @return array[]
+	 */
+	public function invalid_import_interval_provider(): array {
+		return array(
+			'null'               => array( null ),
+			'non-numeric string' => array( 'abc' ),
+			'zero'               => array( 0 ),
+			'negative'           => array( -5 ),
+			'below one second'   => array( 0.5 ),
+			'infinite'           => array( INF ),
+		);
+	}
+
+	/**
+	 * Test that an invalid import interval from the filter falls back to the 12 hour default.
+	 *
+	 * @dataProvider invalid_import_interval_provider
+	 *
+	 * @param mixed $value The filter return value.
+	 */
+	public function test_invalid_import_interval_falls_back_to_default( $value ) {
+		$this->clear_scheduled_batch_processor();
+		$this->setExpectedIncorrectUsage( OrdersScheduler::class . '::get_import_interval' );
+
+		$filter = fn() => $value;
+		add_filter( 'woocommerce_analytics_import_interval', $filter );
+
+		$interval = OrdersScheduler::get_import_interval();
+		OrdersScheduler::schedule_recurring_batch_processor();
+
+		remove_filter( 'woocommerce_analytics_import_interval', $filter );
+
+		$this->assertSame( 12 * HOUR_IN_SECONDS, $interval, 'An invalid import interval should fall back to 12 hours' );
+		$this->assertTrue(
+			$this->is_batch_processor_scheduled(),
+			'An invalid import interval should still schedule the batch processor'
+		);
+	}
+
+	/**
+	 * Test that a numeric string from the filter is returned as an integer.
+	 */
+	public function test_numeric_string_import_interval_is_cast_to_int() {
+		$filter = fn() => '3600';
+		add_filter( 'woocommerce_analytics_import_interval', $filter );
+
+		$interval = OrdersScheduler::get_import_interval();
+
+		remove_filter( 'woocommerce_analytics_import_interval', $filter );
+
+		$this->assertSame( 3600, $interval );
+	}
+
 	/**
 	 * Test that handle_scheduled_import_option_change unschedules batch processor when switching to immediate import.
 	 */