Commit a85d3946e42 for woocommerce
commit a85d3946e4289350bec458202636b5a550108923
Author: Thomas Roberts <5656702+opr@users.noreply.github.com>
Date: Mon Aug 17 09:48:05 2026 +0100
fix: accept Latvian postcodes without the LV prefix hyphen (#67684)
* fix: accept Latvian postcodes without the LV prefix hyphen
WC_Validation::is_postcode() does not normalise its input, so a Latvian
postcode can reach it as "LV1050" or "LV 1050" rather than "LV-1050".
The rule added in #67460 required the literal hyphen, so it rejected
both. Before that PR they fell through to the fail-open default and were
accepted.
POST /wc/store/v1/checkout reaches this on a normal request.
AbstractAddressSchema::sanitize_callback() formats the postcode with the
raw country value but validates against the uppercased one, so a client
sending country "lv" skips the LV case in wc_format_postcode() (which
would reinsert the hyphen) and then hits the LV case in is_postcode().
Verified against a local store: rejected on trunk, accepted here.
The separator is a literal space rather than \s, so a newline or tab
between the prefix and the digits is still rejected.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs: document the LV postcode pattern and cover its edges
Explain the optional prefix, the single hyphen or space separator, and
why the pattern uses a literal space and \z rather than \s and $.
Add rows for repeated and invalid separators, the top of the four digit
range, and trailing characters. No behaviour change; every one of these
already validated this way.
Raised by CodeRabbit on #67684.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
diff --git a/plugins/woocommerce/changelog/fix-lv-postcode-separator b/plugins/woocommerce/changelog/fix-lv-postcode-separator
new file mode 100644
index 00000000000..263f3e2903b
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-lv-postcode-separator
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Accept Latvian postcodes that carry the LV prefix without a hyphen, restoring values that validated before postcode rules were added for Latvia.
diff --git a/plugins/woocommerce/includes/class-wc-validation.php b/plugins/woocommerce/includes/class-wc-validation.php
index 330dd93acc4..fecdebb7f94 100644
--- a/plugins/woocommerce/includes/class-wc-validation.php
+++ b/plugins/woocommerce/includes/class-wc-validation.php
@@ -144,7 +144,10 @@ class WC_Validation {
$valid = (bool) preg_match( '/^(94[8-9][0-9])$/', $postcode );
break;
case 'LV':
- $valid = (bool) preg_match( '/^(?:LV-)?[1-9][0-9]{3}\z/i', $postcode );
+ // An optional case-insensitive LV prefix, followed by at most one hyphen or
+ // space, then four digits that do not start with a zero. A literal space
+ // rather than \s, and \z rather than $, so newlines and tabs are rejected.
+ $valid = (bool) preg_match( '/^(?:LV[- ]?)?[1-9][0-9]{3}\z/i', $postcode );
break;
default:
$valid = true;
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-validation-test.php b/plugins/woocommerce/tests/php/includes/class-wc-validation-test.php
index 640ec71c6b3..20e3b975b67 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-validation-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-validation-test.php
@@ -97,6 +97,25 @@ class WC_Validation_Test extends \WC_Unit_Test_Case {
array( false, 'ZZ-1050', 'LV' ),
array( false, 'LV-ABCD', 'LV' ),
array( false, "LV-1050\n", 'LV' ),
+ // The country prefix without a separator, as produced by wc_normalize_postcode().
+ array( true, 'LV1050', 'LV' ),
+ array( true, 'lv1050', 'LV' ),
+ array( false, 'LV0123', 'LV' ),
+ array( false, "LV1050\n", 'LV' ),
+ // A space is accepted as the prefix separator, but only a literal space.
+ array( true, 'LV 1050', 'LV' ),
+ array( true, 'lv 1050', 'LV' ),
+ array( false, "LV\n1050", 'LV' ),
+ array( false, "LV\t1050", 'LV' ),
+ // At most one separator, and only a hyphen or a space.
+ array( false, 'LV--1050', 'LV' ),
+ array( false, 'LV 1050', 'LV' ),
+ array( false, 'LV_1050', 'LV' ),
+ // The bounds of the four digit range, and trailing characters.
+ array( true, '9999', 'LV' ),
+ array( false, '0999', 'LV' ),
+ array( false, 'LV-1050x', 'LV' ),
+ array( false, 'LV-1050 ', 'LV' ),
);
return array_merge( $cz, $se, $li, $lv );