Commit 9a3a1a1dc41 for woocommerce
commit 9a3a1a1dc41183c133e1ae8307a9310dc8e7cbc1
Author: Peter Petrov <peter.petrov89@gmail.com>
Date: Thu Jul 16 15:28:26 2026 +0300
Fix CSV importer HTML-encoding attribute names (#66656)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
diff --git a/plugins/woocommerce/changelog/fix-28172-csv-importer-attribute-name-sanitization b/plugins/woocommerce/changelog/fix-28172-csv-importer-attribute-name-sanitization
new file mode 100644
index 00000000000..0b84f784838
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-28172-csv-importer-attribute-name-sanitization
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix CSV importer HTML-encoding attribute names, which prevented matching existing global attributes and caused duplicate attributes or slug-too-long import errors.
diff --git a/plugins/woocommerce/includes/import/class-wc-product-csv-importer.php b/plugins/woocommerce/includes/import/class-wc-product-csv-importer.php
index 4d2c76e1e0e..b16650628e7 100644
--- a/plugins/woocommerce/includes/import/class-wc-product-csv-importer.php
+++ b/plugins/woocommerce/includes/import/class-wc-product-csv-importer.php
@@ -844,9 +844,9 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
if ( isset( $data_formatting[ $heading ] ) ) {
$callback = $data_formatting[ $heading ];
} else {
- foreach ( $regex_match_data_formatting as $regex => $callback ) {
+ foreach ( $regex_match_data_formatting as $regex => $regex_callback ) {
if ( preg_match( $regex, $heading ) ) {
- $callback = $callback;
+ $callback = $regex_callback;
break;
}
}
diff --git a/plugins/woocommerce/tests/php/includes/importer/class-wc-product-csv-importer-test.php b/plugins/woocommerce/tests/php/includes/importer/class-wc-product-csv-importer-test.php
index 52a39c1a736..631d9bc4778 100644
--- a/plugins/woocommerce/tests/php/includes/importer/class-wc-product-csv-importer-test.php
+++ b/plugins/woocommerce/tests/php/includes/importer/class-wc-product-csv-importer-test.php
@@ -293,6 +293,53 @@ class WC_Product_CSV_Importer_Test extends \WC_Unit_Test_Case {
);
}
+ /**
+ * @testdox Attribute names with special characters should match existing global attributes on import instead of creating duplicates (issue #28172).
+ */
+ public function test_import_matches_existing_attribute_with_special_characters_in_name_28172() {
+ // Set admin user to allow term creation.
+ wp_set_current_user( self::factory()->user->create( array( 'role' => 'administrator' ) ) );
+
+ $attribute_id = wc_create_attribute(
+ array(
+ 'name' => 'ARC Flash > Gloves > CE Category',
+ 'slug' => 'arc-glove-ce',
+ )
+ );
+ $taxonomy = wc_attribute_taxonomy_name_by_id( $attribute_id );
+ register_taxonomy( $taxonomy, 'product' );
+ wp_insert_term( 'Meeny', $taxonomy );
+
+ $csv_file = __DIR__ . '/import-attribute-special-chars-28172-data.csv';
+ $args = array(
+ 'parse' => true,
+ 'mapping' => array(
+ 'Name' => 'name',
+ 'Type' => 'type',
+ 'Attribute 1 name' => 'attributes:name1',
+ 'Attribute 1 value(s)' => 'attributes:value1',
+ 'Attribute 1 visible' => 'attributes:visible1',
+ 'Attribute 1 global' => 'attributes:taxonomy1',
+ ),
+ );
+ $importer = new WC_Product_CSV_Importer( $csv_file, $args );
+
+ $parsed = $importer->get_parsed_data();
+ $this->assertSame( 'ARC Flash > Gloves > CE Category', $parsed[0]['raw_attributes'][0]['name'], 'The attribute name should not be HTML-encoded during parsing' );
+
+ $data = $importer->import();
+ $this->assertCount( 1, $data['imported'], 'Expected 1 imported product' );
+ $this->assertEmpty( $data['failed'], 'Expected 0 failed products' );
+
+ $this->assertSame( 0, wc_attribute_taxonomy_id_by_name( 'arc-flash-gloves-ce-category' ), 'A duplicate attribute should not be created' );
+
+ $product = wc_get_product( $data['imported'][0] );
+ $this->assertArrayHasKey( 'pa_arc-glove-ce', $product->get_attributes(), 'The product should use the existing attribute' );
+
+ WC_Helper_Product::delete_product( $product->get_id() );
+ wc_delete_attribute( $attribute_id );
+ }
+
/**
* @testdox parse_float_field should return an empty string unchanged.
*/
diff --git a/plugins/woocommerce/tests/php/includes/importer/import-attribute-special-chars-28172-data.csv b/plugins/woocommerce/tests/php/includes/importer/import-attribute-special-chars-28172-data.csv
new file mode 100644
index 00000000000..1d00c458dfe
--- /dev/null
+++ b/plugins/woocommerce/tests/php/includes/importer/import-attribute-special-chars-28172-data.csv
@@ -0,0 +1,2 @@
+Name,Type,Attribute 1 name,Attribute 1 value(s),Attribute 1 visible,Attribute 1 global
+Special Chars Attribute Product,simple,ARC Flash > Gloves > CE Category,Meeny,1,1