Commit cf12552aba7 for woocommerce
commit cf12552aba7761eb6408bd07d5e6603481264c39
Author: Seun Olorunsola <30554163+triple0t@users.noreply.github.com>
Date: Mon Apr 27 10:50:25 2026 +0100
Fix early textdomain loading from dual code API feature check (#64332)
Co-authored-by: Néstor Soriano <konamiman@konamiman.com>
diff --git a/plugins/woocommerce/changelog/64332-fix-load-textdomain-notice b/plugins/woocommerce/changelog/64332-fix-load-textdomain-notice
new file mode 100644
index 00000000000..c14beb31e4e
--- /dev/null
+++ b/plugins/woocommerce/changelog/64332-fix-load-textdomain-notice
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix a `_load_textdomain_just_in_time` notice for the `woocommerce` domain on WordPress 6.7+ caused by the new dual code / GraphQL API checking its feature flag too early during plugin load.
\ No newline at end of file
diff --git a/plugins/woocommerce/src/Internal/Api/Main.php b/plugins/woocommerce/src/Internal/Api/Main.php
index 58754922b25..fe20cf7e2b4 100644
--- a/plugins/woocommerce/src/Internal/Api/Main.php
+++ b/plugins/woocommerce/src/Internal/Api/Main.php
@@ -27,26 +27,16 @@ class Main {
*/
public const OPTION_GET_ENDPOINT_ENABLED = 'woocommerce_graphql_get_endpoint_enabled';
- /**
- * Cached result of the feature-enabled check, null until first evaluated.
- *
- * @var ?bool
- */
- private static ?bool $enabled = null;
-
/**
* Check whether the Dual Code & GraphQL API feature is active.
*
* Requires PHP 8.1+ and the dual_code_graphql_api feature flag to be
- * enabled. The result is cached for the lifetime of the request.
+ * enabled.
*
* @return bool
*/
public static function is_enabled(): bool {
- if ( null === self::$enabled ) {
- self::$enabled = PHP_VERSION_ID >= 80100 && FeaturesUtil::feature_is_enabled( self::FEATURE_SLUG );
- }
- return self::$enabled;
+ return PHP_VERSION_ID >= 80100 && FeaturesUtil::feature_is_enabled( self::FEATURE_SLUG );
}
/**
@@ -91,12 +81,13 @@ class Main {
* that want to know whether the feature is active should check
* FeaturesUtil::feature_is_enabled( 'dual_code_graphql_api' ) rather
* than class_exists() on the Api namespace.
+ *
+ * The feature-enabled check is deferred to the `rest_api_init` callback
+ * to avoid triggering translation loading (via FeaturesController) before
+ * the `init` action has fired, which would cause a
+ * `_load_textdomain_just_in_time` notice on WordPress 6.7+.
*/
public static function register(): void {
- if ( ! self::is_enabled() ) {
- return;
- }
-
add_action( 'rest_api_init', array( self::class, 'handle_rest_api_init_for_core' ) );
$settings = wc_get_container()->get( Settings::class );
@@ -106,13 +97,13 @@ class Main {
/**
* Hook callback: register WooCommerce core's GraphQL endpoint.
*
- * Extracted from {@see self::register()} so the hook target is a named
- * class method rather than an inline closure, matching WooCommerce's
- * usual hook-registration style.
- *
* @internal
*/
public static function handle_rest_api_init_for_core(): void {
+ if ( ! self::is_enabled() ) {
+ return;
+ }
+
wc_get_container()->get( Autogenerated\GraphQLController::class )->register();
}
diff --git a/plugins/woocommerce/src/Internal/Api/Settings.php b/plugins/woocommerce/src/Internal/Api/Settings.php
index 3b1678c549b..a40ff8345c8 100644
--- a/plugins/woocommerce/src/Internal/Api/Settings.php
+++ b/plugins/woocommerce/src/Internal/Api/Settings.php
@@ -32,7 +32,9 @@ class Settings {
* @return array
*/
public function add_section( array $sections ): array {
- $sections[ self::SECTION_ID ] = __( 'GraphQL', 'woocommerce' );
+ if ( Main::is_enabled() ) {
+ $sections[ self::SECTION_ID ] = __( 'GraphQL', 'woocommerce' );
+ }
return $sections;
}
@@ -44,7 +46,7 @@ class Settings {
* @return array
*/
public function add_settings( array $settings, string $section_id ): array {
- if ( self::SECTION_ID !== $section_id ) {
+ if ( self::SECTION_ID !== $section_id || ! Main::is_enabled() ) {
return $settings;
}
diff --git a/plugins/woocommerce/tests/php/src/Internal/Api/SettingsTest.php b/plugins/woocommerce/tests/php/src/Internal/Api/SettingsTest.php
index bd786f59f96..455a302fe07 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Api/SettingsTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Api/SettingsTest.php
@@ -5,6 +5,7 @@ namespace Automattic\WooCommerce\Tests\Internal\Api;
use Automattic\WooCommerce\Internal\Api\Main;
use Automattic\WooCommerce\Internal\Api\Settings;
+use Automattic\WooCommerce\Internal\Features\FeaturesController;
use WC_Unit_Test_Case;
/**
@@ -23,6 +24,7 @@ class SettingsTest extends WC_Unit_Test_Case {
*/
public function setUp(): void {
parent::setUp();
+ $this->enable_or_disable_feature( true );
$this->sut = new Settings();
}
@@ -30,11 +32,22 @@ class SettingsTest extends WC_Unit_Test_Case {
* Clean up filters registered by tests so global state doesn't leak.
*/
public function tearDown(): void {
- remove_filter( 'woocommerce_get_sections_advanced', array( $this->sut, 'add_section' ) );
- remove_filter( 'woocommerce_get_settings_advanced', array( $this->sut, 'add_settings' ), 10 );
+ $this->enable_or_disable_feature( false );
parent::tearDown();
}
+ /**
+ * Enable or disable the GraphQL API feature.
+ *
+ * @param bool $enable True to enable, false to disable.
+ */
+ private function enable_or_disable_feature( bool $enable ): void {
+ update_option(
+ wc_get_container()->get( FeaturesController::class )->feature_enable_option_name( 'dual_code_graphql_api' ),
+ $enable ? 'yes' : 'no'
+ );
+ }
+
/**
* @testdox register hooks add_section and add_settings into WooCommerce's advanced settings filters.
*/
@@ -52,9 +65,13 @@ class SettingsTest extends WC_Unit_Test_Case {
}
/**
- * @testdox add_section appends the graphql section while preserving existing ones.
+ * @testdox add_section appends the graphql section while preserving existing ones (PHP 8.1+).
*/
public function test_add_section_appends_graphql_section(): void {
+ if ( PHP_VERSION_ID < 80100 ) {
+ $this->markTestSkipped( 'GraphQL settings require PHP 8.1+.' );
+ }
+
$result = $this->sut->add_section( array( 'features' => 'Features' ) );
$this->assertArrayHasKey( Settings::SECTION_ID, $result );
@@ -62,9 +79,27 @@ class SettingsTest extends WC_Unit_Test_Case {
}
/**
- * @testdox add_settings defines the GET endpoint checkbox with a 'yes' default.
+ * @testdox add_section is a no-op on PHP < 8.1.
+ */
+ public function test_add_section_is_noop_on_unsupported_php(): void {
+ if ( PHP_VERSION_ID >= 80100 ) {
+ $this->markTestSkipped( 'Only relevant on PHP < 8.1.' );
+ }
+
+ $input = array( 'features' => 'Features' );
+ $result = $this->sut->add_section( $input );
+
+ $this->assertSame( $input, $result );
+ }
+
+ /**
+ * @testdox add_settings defines the GET endpoint checkbox with a 'yes' default (PHP 8.1+).
*/
public function test_add_settings_defines_get_endpoint_checkbox(): void {
+ if ( PHP_VERSION_ID < 80100 ) {
+ $this->markTestSkipped( 'GraphQL settings require PHP 8.1+.' );
+ }
+
$fields = $this->sut->add_settings( array(), Settings::SECTION_ID );
$by_id = array_column( $fields, null, 'id' );
@@ -72,4 +107,18 @@ class SettingsTest extends WC_Unit_Test_Case {
$this->assertSame( 'checkbox', $by_id[ Main::OPTION_GET_ENDPOINT_ENABLED ]['type'] );
$this->assertSame( 'yes', $by_id[ Main::OPTION_GET_ENDPOINT_ENABLED ]['default'] );
}
+
+ /**
+ * @testdox add_settings returns the input unchanged on PHP < 8.1.
+ */
+ public function test_add_settings_is_noop_on_unsupported_php(): void {
+ if ( PHP_VERSION_ID >= 80100 ) {
+ $this->markTestSkipped( 'Only relevant on PHP < 8.1.' );
+ }
+
+ $input = array( array( 'id' => 'existing' ) );
+ $result = $this->sut->add_settings( $input, Settings::SECTION_ID );
+
+ $this->assertSame( $input, $result );
+ }
}