Commit 2567b1ed31 for woocommerce
commit 2567b1ed31be8e842143f84d245603c1e5ed30fe
Author: Rostislav Wolný <1082140+costasovo@users.noreply.github.com>
Date: Fri Dec 12 08:36:12 2025 +0100
Prevent PHP notices about actions scheduler and translations on init (#62394)
* Prevent notice about uninitialized action scheduler
The notice uses the translation function and also causes:
PHP Notice: Function _load_textdomain_just_in_time was called incorrectly
* Add changelog
* Fix error reported by PHP Stan
* Fix lint error
* Update `@since`
---------
Co-authored-by: Ján Mikláš <neosinner@gmail.com>
diff --git a/plugins/woocommerce/changelog/wooplug-5969-improve-translation-loading-to-avoid-wordpress-php-warning b/plugins/woocommerce/changelog/wooplug-5969-improve-translation-loading-to-avoid-wordpress-php-warning
new file mode 100644
index 0000000000..aa99275a93
--- /dev/null
+++ b/plugins/woocommerce/changelog/wooplug-5969-improve-translation-loading-to-avoid-wordpress-php-warning
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Prevent notice as_unschedule_all_actions() was called before the Action Scheduler data store was initialized
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 0d2fa402c5..3b37fbdd47 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -77439,12 +77439,6 @@ parameters:
count: 1
path: src/Blocks/Patterns/PTKPatternsStore.php
- -
- message: '#^Function as_unschedule_all_actions not found\.$#'
- identifier: function.notFound
- count: 1
- path: src/Blocks/Patterns/PTKPatternsStore.php
-
-
message: '#^Method Automattic\\WooCommerce\\Blocks\\Patterns\\PTKPatternsStore\:\:get_patterns\(\) should return array but returns mixed\.$#'
identifier: return.type
diff --git a/plugins/woocommerce/src/Blocks/Patterns/PTKPatternsStore.php b/plugins/woocommerce/src/Blocks/Patterns/PTKPatternsStore.php
index b675a9aa3f..2179f39050 100644
--- a/plugins/woocommerce/src/Blocks/Patterns/PTKPatternsStore.php
+++ b/plugins/woocommerce/src/Blocks/Patterns/PTKPatternsStore.php
@@ -187,13 +187,28 @@ class PTKPatternsStore {
/**
* Reset the cached patterns to fetch them again from the PTK.
*
+ * @since 10.4.1 Unscheduling is deferred if Action Scheduler hasn't initialized yet.
* @return void
*/
public function flush_cached_patterns() {
delete_option( self::OPTION_NAME );
+ if ( ! function_exists( 'as_unschedule_all_actions' ) ) {
+ return;
+ }
+
// Unschedule any existing fetch_patterns actions.
- as_unschedule_all_actions( self::FETCH_PATTERNS_ACTION, array(), 'woocommerce' );
+ // Defer unscheduling until Action Scheduler is ready to avoid errors during early initialization.
+ if ( did_action( 'action_scheduler_init' ) ) {
+ as_unschedule_all_actions( self::FETCH_PATTERNS_ACTION, array(), 'woocommerce' );
+ } else {
+ add_action(
+ 'action_scheduler_init',
+ function () {
+ as_unschedule_all_actions( self::FETCH_PATTERNS_ACTION, array(), 'woocommerce' );
+ }
+ );
+ }
}
/**
diff --git a/plugins/woocommerce/tests/php/src/Blocks/Patterns/PTKPatternsStoreTest.php b/plugins/woocommerce/tests/php/src/Blocks/Patterns/PTKPatternsStoreTest.php
index 7d6cd2fbf6..9f3245944d 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/Patterns/PTKPatternsStoreTest.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/Patterns/PTKPatternsStoreTest.php
@@ -471,4 +471,53 @@ class PTKPatternsStoreTest extends \WP_UnitTestCase {
$this->assertFalse( as_has_scheduled_action( 'fetch_patterns', array(), 'woocommerce' ), 'All fetch_patterns actions should be unscheduled after flush' );
}
+
+ /**
+ * Test flush_cached_patterns defers unscheduling when called before action_scheduler_init.
+ *
+ * This test simulates the scenario where flush_cached_patterns is called during early
+ * initialization, before Action Scheduler has been initialized.
+ */
+ public function test_flush_cached_patterns_defers_unscheduling_before_action_scheduler_init() {
+ global $wp_actions;
+
+ // Schedule an action.
+ as_schedule_single_action( time(), 'fetch_patterns', array(), 'woocommerce' );
+ $this->assertTrue( as_has_scheduled_action( 'fetch_patterns', array(), 'woocommerce' ), 'Action should be scheduled initially' );
+
+ // Save the original action_scheduler_init count.
+ $original_count = $wp_actions['action_scheduler_init'] ?? 0;
+
+ // Simulate that action_scheduler_init has not yet fired by unsetting it.
+ if ( isset( $wp_actions['action_scheduler_init'] ) ) {
+ unset( $wp_actions['action_scheduler_init'] ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
+ }
+
+ // Verify did_action returns 0 (not fired).
+ $this->assertEquals( 0, did_action( 'action_scheduler_init' ), 'action_scheduler_init should appear not fired' );
+
+ // Call flush_cached_patterns before action_scheduler_init has fired.
+ $this->pattern_store->flush_cached_patterns();
+
+ // The option should be deleted immediately.
+ $patterns = get_option( PTKPatternsStore::OPTION_NAME );
+ $this->assertFalse( $patterns, 'Patterns option should be deleted immediately' );
+
+ // The action should still be scheduled (unscheduling is deferred).
+ $this->assertTrue( as_has_scheduled_action( 'fetch_patterns', array(), 'woocommerce' ), 'Action should still be scheduled before action_scheduler_init fires' );
+
+ /**
+ * Simulate action_scheduler_init firing.
+ *
+ * @since 10.4.1
+ * @return void
+ */
+ do_action( 'action_scheduler_init' );
+
+ // After action_scheduler_init fires, the action should be unscheduled.
+ $this->assertFalse( as_has_scheduled_action( 'fetch_patterns', array(), 'woocommerce' ), 'Action should be unscheduled after action_scheduler_init fires' );
+
+ // Restore the original action count.
+ $wp_actions['action_scheduler_init'] = $original_count; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
+ }
}