Commit f9323fbfee for woocommerce
commit f9323fbfee87ef29312c99b0d74b3d724766a4ae
Author: Ahmed <ahmed.el.azzabi@automattic.com>
Date: Wed Dec 17 11:34:52 2025 +0100
Fix: Support state codes with country prefixes in REST API V4 General Settings (#62495)
* Remove country code format validation
* Add tests for updating country settings with state codes in WooCommerce REST API
- Implemented tests to ensure compatibility with both legacy and new state code formats when updating the default country setting.
- Added test cases for state codes with and without country prefixes to validate correct behavior in the API response.
* Update unit tests
* Add changefile(s) from automation for the following project(s): woocommerce
---------
Co-authored-by: github-actions <github-actions@github.com>
diff --git a/plugins/woocommerce/changelog/62495-fix-remove-preg-match b/plugins/woocommerce/changelog/62495-fix-remove-preg-match
new file mode 100644
index 0000000000..b5177cd8ca
--- /dev/null
+++ b/plugins/woocommerce/changelog/62495-fix-remove-preg-match
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix REST API V4 country/state validation to accept state codes with country prefixes (e.g., DE:DE-BY) for compatibility with V3 API format.
\ No newline at end of file
diff --git a/plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/General/Controller.php b/plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/General/Controller.php
index 695f28e72b..3566d5963e 100644
--- a/plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/General/Controller.php
+++ b/plugins/woocommerce/src/Internal/RestApi/Routes/V4/Settings/General/Controller.php
@@ -270,15 +270,6 @@ class Controller extends AbstractController {
break;
case 'woocommerce_default_country':
- // Validate country code format (e.g., "US" or "US:CA").
- if ( ! empty( $value ) && ! preg_match( '/^[A-Z]{2}(:[A-Z0-9]+)?$/', $value ) ) {
- return new WP_Error(
- 'rest_invalid_param',
- __( 'Invalid country/state format.', 'woocommerce' ),
- array( 'status' => 400 )
- );
- }
-
if ( ! $this->validate_country_or_state_code( $value ) ) {
return new WP_Error(
'rest_invalid_param',
diff --git a/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version4/Settings/class-wc-rest-general-settings-v4-controller-test.php b/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version4/Settings/class-wc-rest-general-settings-v4-controller-test.php
index 9cc93200e6..aae1ce1e76 100644
--- a/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version4/Settings/class-wc-rest-general-settings-v4-controller-test.php
+++ b/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version4/Settings/class-wc-rest-general-settings-v4-controller-test.php
@@ -222,6 +222,80 @@ class WC_REST_General_Settings_V4_Controller_Test extends WC_REST_Unit_Test_Case
$this->assertEquals( 'US:CA', $data['values']['woocommerce_default_country'] );
}
+ /**
+ * Test updating country with state code (e.g., DE:DE-BY).
+ * State codes in WooCommerce include the country prefix (e.g., "DE-BY" for Bavaria).
+ */
+ public function test_update_country_with_state() {
+ wp_set_current_user( $this->user_id );
+ $request = new WP_REST_Request( 'PUT', '/wc/v4/settings/general' );
+ $request->set_header( 'Content-Type', 'application/json' );
+ $request->set_body(
+ wp_json_encode(
+ array(
+ 'values' => array(
+ 'woocommerce_default_country' => 'DE:DE-BY', // Bavaria, Germany.
+ ),
+ )
+ )
+ );
+ $response = $this->server->dispatch( $request );
+ $data = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $this->assertEquals( 'DE:DE-BY', get_option( 'woocommerce_default_country' ) );
+ $this->assertArrayHasKey( 'values', $data );
+ $this->assertEquals( 'DE:DE-BY', $data['values']['woocommerce_default_country'] );
+ }
+
+ /**
+ * Test updating country with invalid state code returns error.
+ */
+ public function test_update_country_with_invalid_state() {
+ wp_set_current_user( $this->user_id );
+ $request = new WP_REST_Request( 'PUT', '/wc/v4/settings/general' );
+ $request->set_header( 'Content-Type', 'application/json' );
+ $request->set_body(
+ wp_json_encode(
+ array(
+ 'values' => array(
+ 'woocommerce_default_country' => 'DE:INVALID', // Invalid state code.
+ ),
+ )
+ )
+ );
+ $response = $this->server->dispatch( $request );
+ $data = $response->get_data();
+
+ $this->assertEquals( 400, $response->get_status() );
+ $this->assertEquals( 'rest_invalid_param', $data['code'] );
+ }
+
+ /**
+ * Test updating country without state (country only).
+ */
+ public function test_update_country_only() {
+ wp_set_current_user( $this->user_id );
+ $request = new WP_REST_Request( 'PUT', '/wc/v4/settings/general' );
+ $request->set_header( 'Content-Type', 'application/json' );
+ $request->set_body(
+ wp_json_encode(
+ array(
+ 'values' => array(
+ 'woocommerce_default_country' => 'DE', // Germany without state.
+ ),
+ )
+ )
+ );
+ $response = $this->server->dispatch( $request );
+ $data = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $this->assertEquals( 'DE', get_option( 'woocommerce_default_country' ) );
+ $this->assertArrayHasKey( 'values', $data );
+ $this->assertEquals( 'DE', $data['values']['woocommerce_default_country'] );
+ }
+
/**
* Test update_item method does not update \'title\' and \'sectionend\' settings and other non-updatable fields.
*/