Commit 52079b2458b for woocommerce

commit 52079b2458b57039a99760e94681ac602618aad5
Author: Miroslav Mitev <m1r0@users.noreply.github.com>
Date:   Fri Jul 24 16:38:22 2026 +0300

    Fix product CSV importer crash when mbstring is unavailable (#66732)

diff --git a/plugins/woocommerce/changelog/38541-fix-csv-importer-mbstring-fallback b/plugins/woocommerce/changelog/38541-fix-csv-importer-mbstring-fallback
new file mode 100644
index 00000000000..5262c379372
--- /dev/null
+++ b/plugins/woocommerce/changelog/38541-fix-csv-importer-mbstring-fallback
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix product CSV importer form crashing when the mbstring extension is unavailable.
diff --git a/plugins/woocommerce/includes/admin/importers/views/html-product-csv-import-form.php b/plugins/woocommerce/includes/admin/importers/views/html-product-csv-import-form.php
index a3af9e8e45f..e4eba75cc9b 100644
--- a/plugins/woocommerce/includes/admin/importers/views/html-product-csv-import-form.php
+++ b/plugins/woocommerce/includes/admin/importers/views/html-product-csv-import-form.php
@@ -79,17 +79,30 @@ if ( ! defined( 'ABSPATH' ) ) {
 					<td><input type="checkbox" id="woocommerce-importer-map-preferences" name="map_preferences" value="1" /></td>
 				</tr>
 				<tr class="woocommerce-importer-advanced hidden">
-					<th><label><?php esc_html_e( 'Character encoding of the file', 'woocommerce' ); ?></label><br/></th>
-					<td><select id="woocommerce-importer-character-encoding" name="character_encoding">
-							<option value="" selected><?php esc_html_e( 'Autodetect', 'woocommerce' ); ?></option>
+					<th><label for="woocommerce-importer-character-encoding"><?php esc_html_e( 'Character encoding of the file', 'woocommerce' ); ?></label><br/></th>
+					<td>
+						<?php
+						if ( function_exists( 'mb_list_encodings' ) ) {
+							?>
+							<select id="woocommerce-importer-character-encoding" name="character_encoding">
+								<option value="" selected><?php esc_html_e( 'Autodetect', 'woocommerce' ); ?></option>
+								<?php
+								$encodings = mb_list_encodings();
+								sort( $encodings, SORT_NATURAL );
+								foreach ( $encodings as $encoding ) {
+									echo '<option>' . esc_html( $encoding ) . '</option>';
+								}
+								?>
+							</select>
 							<?php
-							$encodings = mb_list_encodings();
-							sort( $encodings, SORT_NATURAL );
-							foreach ( $encodings as $encoding ) {
-								echo '<option>' . esc_html( $encoding ) . '</option>';
-							}
+						} else {
 							?>
-						</select>
+							<div class="notice notice-warning inline">
+								<p><?php esc_html_e( 'Your server does not support the mbstring PHP extension, so the file will be treated as UTF-8. Characters in other encodings may be removed.', 'woocommerce' ); ?></p>
+							</div>
+							<?php
+						}
+						?>
 					</td>
 				</tr>
 			</tbody>
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 c480bf6fa2b..cd44bfb115d 100644
--- a/plugins/woocommerce/includes/import/class-wc-product-csv-importer.php
+++ b/plugins/woocommerce/includes/import/class-wc-product-csv-importer.php
@@ -90,7 +90,13 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
 	 */
 	private function adjust_character_encoding( $value ) {
 		$encoding = $this->params['character_encoding'];
-		return 'UTF-8' === $encoding ? $value : mb_convert_encoding( $value, 'UTF-8', $encoding );
+
+		// Skip conversion when the value is already UTF-8 or when mbstring is unavailable.
+		if ( 'UTF-8' === $encoding || ! function_exists( 'mb_convert_encoding' ) ) {
+			return $value;
+		}
+
+		return mb_convert_encoding( $value, 'UTF-8', $encoding );
 	}

 	/**
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 e56e4985db9..8a272072ab9 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
@@ -470,4 +470,45 @@ class WC_Product_CSV_Importer_Test extends \WC_Unit_Test_Case {

 		$this->assertSame( '', $importer->parse_float_field( '' ), 'Empty values should be returned unchanged.' );
 	}
+
+	/**
+	 * @testdox adjust_character_encoding should convert values from the configured encoding to UTF-8 (issue #38541).
+	 * @dataProvider provider_adjust_character_encoding
+	 *
+	 * @param string $encoding The configured character encoding.
+	 * @param string $value    The raw value expressed in that encoding.
+	 * @param string $expected The expected UTF-8 value.
+	 */
+	public function test_adjust_character_encoding_converts_to_utf8( string $encoding, string $value, string $expected ) {
+		if ( ! function_exists( 'mb_convert_encoding' ) ) {
+			$this->markTestSkipped( 'The mbstring extension is required for this test.' );
+		}
+
+		$importer = new WC_Product_CSV_Importer( __DIR__ . '/sample.csv', array( 'character_encoding' => $encoding ) );
+
+		$method = new ReflectionMethod( WC_Product_CSV_Importer::class, 'adjust_character_encoding' );
+		$method->setAccessible( true );
+
+		$this->assertSame(
+			$expected,
+			$method->invoke( $importer, $value ),
+			"Expected a '{$encoding}' value to be converted to UTF-8."
+		);
+	}
+
+	/**
+	 * Data provider for test_adjust_character_encoding_converts_to_utf8.
+	 *
+	 * The é character is the single byte 0xE9 in both ISO-8859-1 and Windows-1252, and the
+	 * two-byte sequence 0xC3 0xA9 in UTF-8.
+	 *
+	 * @return array
+	 */
+	public function provider_adjust_character_encoding(): array {
+		return array(
+			'UTF-8 is returned unchanged' => array( 'UTF-8', 'Café', 'Café' ),
+			'ISO-8859-1 is converted'     => array( 'ISO-8859-1', "Caf\xE9", 'Café' ),
+			'Windows-1252 is converted'   => array( 'Windows-1252', "Caf\xE9", 'Café' ),
+		);
+	}
 }