Add a string encoding selector to the product importer (#36819)
This commit is contained in:
commit
af7c3f380d
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: add
|
||||||
|
|
||||||
|
Add an encoding selector to the product importer
|
|
@ -5,14 +5,15 @@
|
||||||
* productImportForm handles the import process.
|
* productImportForm handles the import process.
|
||||||
*/
|
*/
|
||||||
var productImportForm = function( $form ) {
|
var productImportForm = function( $form ) {
|
||||||
this.$form = $form;
|
this.$form = $form;
|
||||||
this.xhr = false;
|
this.xhr = false;
|
||||||
this.mapping = wc_product_import_params.mapping;
|
this.mapping = wc_product_import_params.mapping;
|
||||||
this.position = 0;
|
this.position = 0;
|
||||||
this.file = wc_product_import_params.file;
|
this.file = wc_product_import_params.file;
|
||||||
this.update_existing = wc_product_import_params.update_existing;
|
this.update_existing = wc_product_import_params.update_existing;
|
||||||
this.delimiter = wc_product_import_params.delimiter;
|
this.delimiter = wc_product_import_params.delimiter;
|
||||||
this.security = wc_product_import_params.import_nonce;
|
this.security = wc_product_import_params.import_nonce;
|
||||||
|
this.character_encoding = wc_product_import_params.character_encoding;
|
||||||
|
|
||||||
// Number of import successes/failures.
|
// Number of import successes/failures.
|
||||||
this.imported = 0;
|
this.imported = 0;
|
||||||
|
@ -39,13 +40,14 @@
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: ajaxurl,
|
url: ajaxurl,
|
||||||
data: {
|
data: {
|
||||||
action : 'woocommerce_do_ajax_product_import',
|
action : 'woocommerce_do_ajax_product_import',
|
||||||
position : $this.position,
|
position : $this.position,
|
||||||
mapping : $this.mapping,
|
mapping : $this.mapping,
|
||||||
file : $this.file,
|
file : $this.file,
|
||||||
update_existing : $this.update_existing,
|
update_existing : $this.update_existing,
|
||||||
delimiter : $this.delimiter,
|
delimiter : $this.delimiter,
|
||||||
security : $this.security
|
security : $this.security,
|
||||||
|
character_encoding: $this.character_encoding
|
||||||
},
|
},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function( response ) {
|
success: function( response ) {
|
||||||
|
|
|
@ -147,11 +147,13 @@ class WC_Admin_Importers {
|
||||||
public function post_importer_compatibility() {
|
public function post_importer_compatibility() {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
|
|
||||||
if ( empty( $_POST['import_id'] ) || ! class_exists( 'WXR_Parser' ) ) { // PHPCS: input var ok, CSRF ok.
|
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||||
|
if ( empty( $_POST['import_id'] ) || ! class_exists( 'WXR_Parser' ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$id = absint( $_POST['import_id'] ); // PHPCS: input var ok.
|
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||||
|
$id = absint( $_POST['import_id'] );
|
||||||
$file = get_attached_file( $id );
|
$file = get_attached_file( $id );
|
||||||
$parser = new WXR_Parser();
|
$parser = new WXR_Parser();
|
||||||
$import_data = $parser->parse( $file );
|
$import_data = $parser->parse( $file );
|
||||||
|
@ -216,12 +218,21 @@ class WC_Admin_Importers {
|
||||||
|
|
||||||
$file = wc_clean( wp_unslash( $_POST['file'] ) ); // PHPCS: input var ok.
|
$file = wc_clean( wp_unslash( $_POST['file'] ) ); // PHPCS: input var ok.
|
||||||
$params = array(
|
$params = array(
|
||||||
'delimiter' => ! empty( $_POST['delimiter'] ) ? wc_clean( wp_unslash( $_POST['delimiter'] ) ) : ',', // PHPCS: input var ok.
|
'delimiter' => ! empty( $_POST['delimiter'] ) ? wc_clean( wp_unslash( $_POST['delimiter'] ) ) : ',', // PHPCS: input var ok.
|
||||||
'start_pos' => isset( $_POST['position'] ) ? absint( $_POST['position'] ) : 0, // PHPCS: input var ok.
|
'start_pos' => isset( $_POST['position'] ) ? absint( $_POST['position'] ) : 0, // PHPCS: input var ok.
|
||||||
'mapping' => isset( $_POST['mapping'] ) ? (array) wc_clean( wp_unslash( $_POST['mapping'] ) ) : array(), // PHPCS: input var ok.
|
'mapping' => isset( $_POST['mapping'] ) ? (array) wc_clean( wp_unslash( $_POST['mapping'] ) ) : array(), // PHPCS: input var ok.
|
||||||
'update_existing' => isset( $_POST['update_existing'] ) ? (bool) $_POST['update_existing'] : false, // PHPCS: input var ok.
|
'update_existing' => isset( $_POST['update_existing'] ) ? (bool) $_POST['update_existing'] : false, // PHPCS: input var ok.
|
||||||
'lines' => apply_filters( 'woocommerce_product_import_batch_size', 30 ),
|
'character_encoding' => isset( $_POST['character_encoding'] ) ? wc_clean( wp_unslash( $_POST['character_encoding'] ) ) : '',
|
||||||
'parse' => true,
|
|
||||||
|
/**
|
||||||
|
* Batch size for the product import process.
|
||||||
|
*
|
||||||
|
* @param int $size Batch size.
|
||||||
|
*
|
||||||
|
* @since
|
||||||
|
*/
|
||||||
|
'lines' => apply_filters( 'woocommerce_product_import_batch_size', 30 ),
|
||||||
|
'parse' => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Log failures.
|
// Log failures.
|
||||||
|
|
|
@ -72,6 +72,13 @@ class WC_Product_CSV_Importer_Controller {
|
||||||
*/
|
*/
|
||||||
protected $update_existing = false;
|
protected $update_existing = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The character encoding to use to interpret the input file, or empty string for autodetect.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $character_encoding = 'UTF-8';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get importer instance.
|
* Get importer instance.
|
||||||
*
|
*
|
||||||
|
@ -141,11 +148,12 @@ class WC_Product_CSV_Importer_Controller {
|
||||||
$this->steps = apply_filters( 'woocommerce_product_csv_importer_steps', $default_steps );
|
$this->steps = apply_filters( 'woocommerce_product_csv_importer_steps', $default_steps );
|
||||||
|
|
||||||
// phpcs:disable WordPress.Security.NonceVerification.Recommended
|
// phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||||
$this->step = isset( $_REQUEST['step'] ) ? sanitize_key( $_REQUEST['step'] ) : current( array_keys( $this->steps ) );
|
$this->step = isset( $_REQUEST['step'] ) ? sanitize_key( $_REQUEST['step'] ) : current( array_keys( $this->steps ) );
|
||||||
$this->file = isset( $_REQUEST['file'] ) ? wc_clean( wp_unslash( $_REQUEST['file'] ) ) : '';
|
$this->file = isset( $_REQUEST['file'] ) ? wc_clean( wp_unslash( $_REQUEST['file'] ) ) : '';
|
||||||
$this->update_existing = isset( $_REQUEST['update_existing'] ) ? (bool) $_REQUEST['update_existing'] : false;
|
$this->update_existing = isset( $_REQUEST['update_existing'] ) ? (bool) $_REQUEST['update_existing'] : false;
|
||||||
$this->delimiter = ! empty( $_REQUEST['delimiter'] ) ? wc_clean( wp_unslash( $_REQUEST['delimiter'] ) ) : ',';
|
$this->delimiter = ! empty( $_REQUEST['delimiter'] ) ? wc_clean( wp_unslash( $_REQUEST['delimiter'] ) ) : ',';
|
||||||
$this->map_preferences = isset( $_REQUEST['map_preferences'] ) ? (bool) $_REQUEST['map_preferences'] : false;
|
$this->map_preferences = isset( $_REQUEST['map_preferences'] ) ? (bool) $_REQUEST['map_preferences'] : false;
|
||||||
|
$this->character_encoding = isset( $_REQUEST['character_encoding'] ) ? wc_clean( wp_unslash( $_REQUEST['character_encoding'] ) ) : 'UTF-8';
|
||||||
// phpcs:enable
|
// phpcs:enable
|
||||||
|
|
||||||
// Import mappings for CSV data.
|
// Import mappings for CSV data.
|
||||||
|
@ -182,12 +190,13 @@ class WC_Product_CSV_Importer_Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
$params = array(
|
$params = array(
|
||||||
'step' => $keys[ $step_index + 1 ],
|
'step' => $keys[ $step_index + 1 ],
|
||||||
'file' => str_replace( DIRECTORY_SEPARATOR, '/', $this->file ),
|
'file' => str_replace( DIRECTORY_SEPARATOR, '/', $this->file ),
|
||||||
'delimiter' => $this->delimiter,
|
'delimiter' => $this->delimiter,
|
||||||
'update_existing' => $this->update_existing,
|
'update_existing' => $this->update_existing,
|
||||||
'map_preferences' => $this->map_preferences,
|
'map_preferences' => $this->map_preferences,
|
||||||
'_wpnonce' => wp_create_nonce( 'woocommerce-csv-importer' ), // wp_nonce_url() escapes & to & breaking redirects.
|
'character_encoding' => $this->character_encoding,
|
||||||
|
'_wpnonce' => wp_create_nonce( 'woocommerce-csv-importer' ), // wp_nonce_url() escapes & to & breaking redirects.
|
||||||
);
|
);
|
||||||
|
|
||||||
return add_query_arg( $params );
|
return add_query_arg( $params );
|
||||||
|
@ -367,8 +376,9 @@ class WC_Product_CSV_Importer_Controller {
|
||||||
protected function mapping_form() {
|
protected function mapping_form() {
|
||||||
check_admin_referer( 'woocommerce-csv-importer' );
|
check_admin_referer( 'woocommerce-csv-importer' );
|
||||||
$args = array(
|
$args = array(
|
||||||
'lines' => 1,
|
'lines' => 1,
|
||||||
'delimiter' => $this->delimiter,
|
'delimiter' => $this->delimiter,
|
||||||
|
'character_encoding' => $this->character_encoding,
|
||||||
);
|
);
|
||||||
|
|
||||||
$importer = self::get_importer( $this->file, $args );
|
$importer = self::get_importer( $this->file, $args );
|
||||||
|
@ -430,14 +440,15 @@ class WC_Product_CSV_Importer_Controller {
|
||||||
'wc-product-import',
|
'wc-product-import',
|
||||||
'wc_product_import_params',
|
'wc_product_import_params',
|
||||||
array(
|
array(
|
||||||
'import_nonce' => wp_create_nonce( 'wc-product-import' ),
|
'import_nonce' => wp_create_nonce( 'wc-product-import' ),
|
||||||
'mapping' => array(
|
'mapping' => array(
|
||||||
'from' => $mapping_from,
|
'from' => $mapping_from,
|
||||||
'to' => $mapping_to,
|
'to' => $mapping_to,
|
||||||
),
|
),
|
||||||
'file' => $this->file,
|
'file' => $this->file,
|
||||||
'update_existing' => $this->update_existing,
|
'update_existing' => $this->update_existing,
|
||||||
'delimiter' => $this->delimiter,
|
'delimiter' => $this->delimiter,
|
||||||
|
'character_encoding' => $this->character_encoding,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
wp_enqueue_script( 'wc-product-import' );
|
wp_enqueue_script( 'wc-product-import' );
|
||||||
|
|
|
@ -60,6 +60,9 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
<input type="hidden" name="file" value="<?php echo esc_attr( $this->file ); ?>" />
|
<input type="hidden" name="file" value="<?php echo esc_attr( $this->file ); ?>" />
|
||||||
<input type="hidden" name="delimiter" value="<?php echo esc_attr( $this->delimiter ); ?>" />
|
<input type="hidden" name="delimiter" value="<?php echo esc_attr( $this->delimiter ); ?>" />
|
||||||
<input type="hidden" name="update_existing" value="<?php echo (int) $this->update_existing; ?>" />
|
<input type="hidden" name="update_existing" value="<?php echo (int) $this->update_existing; ?>" />
|
||||||
|
<?php if ( $args['character_encoding'] ) { ?>
|
||||||
|
<input type="hidden" name="character_encoding" value="<?php echo esc_html( $args['character_encoding'] ); ?>" />
|
||||||
|
<?php } ?>
|
||||||
<?php wp_nonce_field( 'woocommerce-csv-importer' ); ?>
|
<?php wp_nonce_field( 'woocommerce-csv-importer' ); ?>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -78,6 +78,20 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
<th><label><?php esc_html_e( 'Use previous column mapping preferences?', 'woocommerce' ); ?></label><br/></th>
|
<th><label><?php esc_html_e( 'Use previous column mapping preferences?', 'woocommerce' ); ?></label><br/></th>
|
||||||
<td><input type="checkbox" id="woocommerce-importer-map-preferences" name="map_preferences" value="1" /></td>
|
<td><input type="checkbox" id="woocommerce-importer-map-preferences" name="map_preferences" value="1" /></td>
|
||||||
</tr>
|
</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>
|
||||||
|
<?php
|
||||||
|
$encodings = mb_list_encodings();
|
||||||
|
sort( $encodings, SORT_NATURAL );
|
||||||
|
foreach ( $encodings as $encoding ) {
|
||||||
|
echo '<option>' . esc_html( $encoding ) . '</option>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
* @version 3.1.0
|
* @version 3.1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Utilities\ArrayUtil;
|
||||||
|
|
||||||
if ( ! defined( 'ABSPATH' ) ) {
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
@ -66,6 +68,17 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
|
||||||
$this->read_file();
|
$this->read_file();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a string from the input encoding to UTF-8.
|
||||||
|
*
|
||||||
|
* @param string $value The string to convert.
|
||||||
|
* @return string The converted string.
|
||||||
|
*/
|
||||||
|
private function adjust_character_encoding( $value ) {
|
||||||
|
$encoding = $this->params['character_encoding'];
|
||||||
|
return 'UTF-8' === $encoding ? $value : mb_convert_encoding( $value, 'UTF-8', $encoding );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read file.
|
* Read file.
|
||||||
*/
|
*/
|
||||||
|
@ -77,7 +90,11 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
|
||||||
$handle = fopen( $this->file, 'r' ); // @codingStandardsIgnoreLine.
|
$handle = fopen( $this->file, 'r' ); // @codingStandardsIgnoreLine.
|
||||||
|
|
||||||
if ( false !== $handle ) {
|
if ( false !== $handle ) {
|
||||||
$this->raw_keys = version_compare( PHP_VERSION, '5.3', '>=' ) ? array_map( 'trim', fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'], $this->params['escape'] ) ) : array_map( 'trim', fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'] ) ); // @codingStandardsIgnoreLine
|
$this->raw_keys = array_map( 'trim', fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'], $this->params['escape'] ) ); // @codingStandardsIgnoreLine
|
||||||
|
|
||||||
|
if ( ArrayUtil::is_truthy( $this->params, 'character_encoding' ) ) {
|
||||||
|
$this->raw_keys = array_map( array( $this, 'adjust_character_encoding' ), $this->raw_keys );
|
||||||
|
}
|
||||||
|
|
||||||
// Remove line breaks in keys, to avoid mismatch mapping of keys.
|
// Remove line breaks in keys, to avoid mismatch mapping of keys.
|
||||||
$this->raw_keys = wc_clean( wp_unslash( $this->raw_keys ) );
|
$this->raw_keys = wc_clean( wp_unslash( $this->raw_keys ) );
|
||||||
|
@ -92,9 +109,13 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( 1 ) {
|
while ( 1 ) {
|
||||||
$row = version_compare( PHP_VERSION, '5.3', '>=' ) ? fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'], $this->params['escape'] ) : fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'] ); // @codingStandardsIgnoreLine
|
$row = fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'], $this->params['escape'] ); // @codingStandardsIgnoreLine
|
||||||
|
|
||||||
if ( false !== $row ) {
|
if ( false !== $row ) {
|
||||||
|
if ( ArrayUtil::is_truthy( $this->params, 'character_encoding' ) ) {
|
||||||
|
$row = array_map( array( $this, 'adjust_character_encoding' ), $row );
|
||||||
|
}
|
||||||
|
|
||||||
$this->raw_data[] = $row;
|
$this->raw_data[] = $row;
|
||||||
$this->file_positions[ count( $this->raw_data ) ] = ftell( $handle );
|
$this->file_positions[ count( $this->raw_data ) ] = ftell( $handle );
|
||||||
|
|
||||||
|
@ -1005,6 +1026,8 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
|
||||||
*
|
*
|
||||||
* @param array $parsed_data Parsed data.
|
* @param array $parsed_data Parsed data.
|
||||||
* @param WC_Product_Importer $importer Importer instance.
|
* @param WC_Product_Importer $importer Importer instance.
|
||||||
|
*
|
||||||
|
* @since
|
||||||
*/
|
*/
|
||||||
$this->parsed_data[] = apply_filters( 'woocommerce_product_importer_parsed_data', $this->expand_data( $data ), $this );
|
$this->parsed_data[] = apply_filters( 'woocommerce_product_importer_parsed_data', $this->expand_data( $data ), $this );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue