Commit b49d11b9e46 for woocommerce
commit b49d11b9e46e5b7e24298dc49c7cb6507d21debc
Author: Michal Iwanow <4765119+mcliwanow@users.noreply.github.com>
Date: Wed Sep 30 13:08:10 2026 +0200
Keep price separators as plain text after decoding (#69238)
PriceSeparators decodes HTML entities in the stored decimal and thousand
separators for the Store API, block settings and admin payloads. A stored
value such as "<b>x</b>" decoded into markup. Separators are
plain text, so markup characters are now dropped after decoding. Values
already saved are covered too, since the change is on the read side.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
diff --git a/plugins/woocommerce/changelog/fix-price-separator-plain-text b/plugins/woocommerce/changelog/fix-price-separator-plain-text
new file mode 100644
index 00000000000..25a101a483a
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-price-separator-plain-text
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Keep price separators as plain text in the Store API and block settings.
diff --git a/plugins/woocommerce/src/Internal/Utilities/PriceSeparators.php b/plugins/woocommerce/src/Internal/Utilities/PriceSeparators.php
index a0a3f5ff8c2..977d814bdcc 100644
--- a/plugins/woocommerce/src/Internal/Utilities/PriceSeparators.php
+++ b/plugins/woocommerce/src/Internal/Utilities/PriceSeparators.php
@@ -20,7 +20,7 @@ class PriceSeparators {
* @return string
*/
public static function get_decimal(): string {
- return html_entity_decode( wc_get_price_decimal_separator(), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5 );
+ return self::to_plain_text( wc_get_price_decimal_separator() );
}
/**
@@ -29,6 +29,16 @@ class PriceSeparators {
* @return string
*/
public static function get_thousand(): string {
- return html_entity_decode( wc_get_price_thousand_separator(), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5 );
+ return self::to_plain_text( wc_get_price_thousand_separator() );
+ }
+
+ /**
+ * Decode HTML entities in a separator. Separators are plain text, so markup characters are dropped.
+ *
+ * @param string $separator The stored separator.
+ * @return string
+ */
+ private static function to_plain_text( string $separator ): string {
+ return str_replace( array( '<', '>' ), '', html_entity_decode( $separator, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5 ) );
}
}
diff --git a/plugins/woocommerce/tests/php/src/Internal/Utilities/PriceSeparatorsTest.php b/plugins/woocommerce/tests/php/src/Internal/Utilities/PriceSeparatorsTest.php
index d62e85f884d..24e1f350ec1 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Utilities/PriceSeparatorsTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Utilities/PriceSeparatorsTest.php
@@ -12,7 +12,7 @@ use WC_Unit_Test_Case;
class PriceSeparatorsTest extends WC_Unit_Test_Case {
/**
- * @testdox Should decode HTML entities stored as separators, including HTML5-only entities.
+ * @testdox Should decode HTML entities stored as separators and drop markup characters.
* @dataProvider separator_entity_data
*
* @param string $stored The raw option value.
@@ -33,12 +33,17 @@ class PriceSeparatorsTest extends WC_Unit_Test_Case {
*/
public function separator_entity_data(): array {
return array(
+ 'plain period' => array( '.', '.' ),
'plain comma' => array( ',', ',' ),
'plain space' => array( ' ', ' ' ),
'non-breaking space char' => array( "\u{00A0}", "\u{00A0}" ),
'named entity nbsp' => array( ' ', "\u{00A0}" ),
'numeric entity comma' => array( ',', ',' ),
'HTML5-only entity apos' => array( ''', "'" ),
+ 'numeric entity apos' => array( ''', "'" ),
+ 'padded numeric apos' => array( ''', "'" ),
+ 'narrow nbsp entity' => array( ' ', "\u{202F}" ),
+ 'encoded markup' => array( '<b>x</b>', 'bx/b' ),
);
}