Merge pull request #15233 from woocommerce/feature/product-csv-import-done-step
Feature/product csv import done step
This commit is contained in:
commit
54cc0b34b3
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -5487,6 +5487,7 @@ table.bar_chart {
|
||||||
border-top: 1px solid #eee;
|
border-top: 1px solid #eee;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 23px 24px 24px;
|
padding: 23px 24px 24px;
|
||||||
|
line-height: 3em;
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
float: right;
|
float: right;
|
||||||
|
@ -5512,6 +5513,10 @@ table.bar_chart {
|
||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 0 #a36597;
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 0 #a36597;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.woocommerce-importer-toggle-advanced-options {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.woocommerce-exporter,
|
.woocommerce-exporter,
|
||||||
|
@ -5583,11 +5588,42 @@ table.bar_chart {
|
||||||
height: auto;
|
height: auto;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.woocommerce-importer-file-url-field-wrapper {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
-webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.07);
|
||||||
|
box-shadow: inset 0 1px 2px rgba(0,0,0,.07);
|
||||||
|
background-color: #fff;
|
||||||
|
color: #32373c;
|
||||||
|
outline: 0;
|
||||||
|
line-height: 1;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: none;
|
||||||
|
font-size: smaller;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
color: #999;
|
||||||
|
padding: 7px 0 0 7px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
font-family: Consolas,Monaco,monospace;
|
||||||
|
border: 0;
|
||||||
|
margin: 0;
|
||||||
|
outline: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 25%;
|
||||||
|
box-sizing: borde
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.woocommerce-exporter-options th,
|
.woocommerce-exporter-options th,
|
||||||
.woocommerce-importer-options th {
|
.woocommerce-importer-options th {
|
||||||
width: 40%;
|
width: 35%;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5634,11 +5670,13 @@ table.bar_chart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wc-importer-mapping-table-wrapper {
|
.wc-importer-mapping-table-wrapper,
|
||||||
|
.wc-importer-error-log {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wc-importer-mapping-table {
|
.wc-importer-mapping-table,
|
||||||
|
.wc-importer-error-log-table {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
@ -5653,7 +5691,8 @@ table.bar_chart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tr:nth-child(odd) td {
|
tbody tr:nth-child(odd) td,
|
||||||
|
tbody tr:nth-child(odd) th {
|
||||||
background: #fbfbfb;
|
background: #fbfbfb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5689,6 +5728,7 @@ table.bar_chart {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 48px 24px;
|
padding: 48px 24px;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
|
line-height: 1.75em;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
@include icon( '\e015' );
|
@include icon( '\e015' );
|
||||||
|
|
|
@ -10,12 +10,14 @@
|
||||||
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.skip_existing = wc_product_import_params.skip_existing;
|
this.update_existing = wc_product_import_params.update_existing;
|
||||||
this.security = wc_product_import_params.import_nonce;
|
this.security = wc_product_import_params.import_nonce;
|
||||||
|
|
||||||
// Number of import successes/failures.
|
// Number of import successes/failures.
|
||||||
this.imported = 0;
|
this.imported = 0;
|
||||||
this.failed = 0;
|
this.failed = 0;
|
||||||
|
this.updated = 0;
|
||||||
|
this.skipped = 0;
|
||||||
|
|
||||||
// Initial state.
|
// Initial state.
|
||||||
this.$form.find('.woocommerce-importer-progress').val( 0 );
|
this.$form.find('.woocommerce-importer-progress').val( 0 );
|
||||||
|
@ -40,7 +42,7 @@
|
||||||
position : $this.position,
|
position : $this.position,
|
||||||
mapping : $this.mapping,
|
mapping : $this.mapping,
|
||||||
file : $this.file,
|
file : $this.file,
|
||||||
skip_existing : $this.skip_existing,
|
update_existing : $this.update_existing,
|
||||||
security : $this.security
|
security : $this.security
|
||||||
},
|
},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
|
@ -49,10 +51,12 @@
|
||||||
$this.position = response.data.position;
|
$this.position = response.data.position;
|
||||||
$this.imported += response.data.imported;
|
$this.imported += response.data.imported;
|
||||||
$this.failed += response.data.failed;
|
$this.failed += response.data.failed;
|
||||||
|
$this.updated += response.data.updated;
|
||||||
|
$this.skipped += response.data.skipped;
|
||||||
$this.$form.find('.woocommerce-importer-progress').val( response.data.percentage );
|
$this.$form.find('.woocommerce-importer-progress').val( response.data.percentage );
|
||||||
|
|
||||||
if ( 'done' === response.data.position ) {
|
if ( 'done' === response.data.position ) {
|
||||||
window.location = response.data.url + '&imported=' + parseInt( $this.imported, 10 ) + '&failed=' + parseInt( $this.failed, 10 );
|
window.location = response.data.url + '&products-imported=' + parseInt( $this.imported, 10 ) + '&products-failed=' + parseInt( $this.failed, 10 ) + '&products-updated=' + parseInt( $this.updated, 10 ) + '&products-skipped=' + parseInt( $this.skipped, 10 );
|
||||||
} else {
|
} else {
|
||||||
$this.run_import();
|
$this.run_import();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
!function(a,b){var c=function(a){this.$form=a,this.xhr=!1,this.mapping=wc_product_import_params.mapping,this.position=0,this.file=wc_product_import_params.file,this.skip_existing=wc_product_import_params.skip_existing,this.security=wc_product_import_params.import_nonce,this.imported=0,this.failed=0,this.$form.find(".woocommerce-importer-progress").val(0),this.run_import=this.run_import.bind(this),this.run_import()};c.prototype.run_import=function(){var c=this;a.ajax({type:"POST",url:ajaxurl,data:{action:"woocommerce_do_ajax_product_import",position:c.position,mapping:c.mapping,file:c.file,skip_existing:c.skip_existing,security:c.security},dataType:"json",success:function(a){a.success&&(c.position=a.data.position,c.imported+=a.data.imported,c.failed+=a.data.failed,c.$form.find(".woocommerce-importer-progress").val(a.data.percentage),"done"===a.data.position?b.location=a.data.url+"&imported="+parseInt(c.imported,10)+"&failed="+parseInt(c.failed,10):c.run_import())}}).fail(function(a){b.console.log(a)})},a.fn.wc_product_importer=function(){return new c(this),this},a(".woocommerce-importer").wc_product_importer()}(jQuery,window);
|
!function(a,b){var c=function(a){this.$form=a,this.xhr=!1,this.mapping=wc_product_import_params.mapping,this.position=0,this.file=wc_product_import_params.file,this.update_existing=wc_product_import_params.update_existing,this.security=wc_product_import_params.import_nonce,this.imported=0,this.failed=0,this.updated=0,this.skipped=0,this.$form.find(".woocommerce-importer-progress").val(0),this.run_import=this.run_import.bind(this),this.run_import()};c.prototype.run_import=function(){var c=this;a.ajax({type:"POST",url:ajaxurl,data:{action:"woocommerce_do_ajax_product_import",position:c.position,mapping:c.mapping,file:c.file,update_existing:c.update_existing,security:c.security},dataType:"json",success:function(a){a.success&&(c.position=a.data.position,c.imported+=a.data.imported,c.failed+=a.data.failed,c.updated+=a.data.updated,c.skipped+=a.data.skipped,c.$form.find(".woocommerce-importer-progress").val(a.data.percentage),"done"===a.data.position?b.location=a.data.url+"&products-imported="+parseInt(c.imported,10)+"&products-failed="+parseInt(c.failed,10)+"&products-updated="+parseInt(c.updated,10)+"&products-skipped="+parseInt(c.skipped,10):c.run_import())}}).fail(function(a){b.console.log(a)})},a.fn.wc_product_importer=function(){return new c(this),this},a(".woocommerce-importer").wc_product_importer()}(jQuery,window);
|
|
@ -205,22 +205,34 @@ class WC_Admin_Importers {
|
||||||
$params = array(
|
$params = array(
|
||||||
'start_pos' => isset( $_POST['position'] ) ? absint( $_POST['position'] ) : 0,
|
'start_pos' => isset( $_POST['position'] ) ? absint( $_POST['position'] ) : 0,
|
||||||
'mapping' => isset( $_POST['mapping'] ) ? (array) $_POST['mapping'] : array(),
|
'mapping' => isset( $_POST['mapping'] ) ? (array) $_POST['mapping'] : array(),
|
||||||
'skip_existing' => isset( $_POST['skip_existing'] ) ? (bool) $_POST['skip_existing'] : false,
|
'update_existing' => isset( $_POST['update_existing'] ) ? (bool) $_POST['update_existing'] : false,
|
||||||
'lines' => apply_filters( 'woocommerce_product_import_batch_size', 10 ),
|
'lines' => apply_filters( 'woocommerce_product_import_batch_size', 10 ),
|
||||||
'parse' => true,
|
'parse' => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Log failures.
|
||||||
|
if ( 0 !== $params['start_pos'] ) {
|
||||||
|
$error_log = array_filter( (array) get_user_option( 'product_import_error_log' ) );
|
||||||
|
} else {
|
||||||
|
$error_log = array();
|
||||||
|
}
|
||||||
|
|
||||||
$importer = WC_Product_CSV_Importer_Controller::get_importer( $file, $params );
|
$importer = WC_Product_CSV_Importer_Controller::get_importer( $file, $params );
|
||||||
$results = $importer->import();
|
$results = $importer->import();
|
||||||
$percent_complete = $importer->get_percent_complete();
|
$percent_complete = $importer->get_percent_complete();
|
||||||
|
$error_log = array_merge( $error_log, $results['failed'], $results['skipped'] );
|
||||||
|
|
||||||
if ( 100 == $percent_complete ) {
|
update_user_option( get_current_user_id(), 'product_import_error_log', $error_log );
|
||||||
|
|
||||||
|
if ( 100 === $percent_complete ) {
|
||||||
wp_send_json_success( array(
|
wp_send_json_success( array(
|
||||||
'position' => 'done',
|
'position' => 'done',
|
||||||
'percentage' => 100,
|
'percentage' => 100,
|
||||||
'url' => add_query_arg( array( 'nonce' => wp_create_nonce( 'product-csv' ) ), admin_url( 'edit.php?post_type=product&page=product_importer&step=done' ) ),
|
'url' => add_query_arg( array( 'nonce' => wp_create_nonce( 'product-csv' ) ), admin_url( 'edit.php?post_type=product&page=product_importer&step=done' ) ),
|
||||||
'imported' => count( $results['imported'] ),
|
'imported' => count( $results['imported'] ),
|
||||||
'failed' => count( $results['failed'] ),
|
'failed' => count( $results['failed'] ),
|
||||||
|
'updated' => count( $results['updated'] ),
|
||||||
|
'skipped' => count( $results['skipped'] ),
|
||||||
) );
|
) );
|
||||||
} else {
|
} else {
|
||||||
wp_send_json_success( array(
|
wp_send_json_success( array(
|
||||||
|
@ -228,6 +240,8 @@ class WC_Admin_Importers {
|
||||||
'percentage' => $percent_complete,
|
'percentage' => $percent_complete,
|
||||||
'imported' => count( $results['imported'] ),
|
'imported' => count( $results['imported'] ),
|
||||||
'failed' => count( $results['failed'] ),
|
'failed' => count( $results['failed'] ),
|
||||||
|
'updated' => count( $results['updated'] ),
|
||||||
|
'skipped' => count( $results['skipped'] ),
|
||||||
) );
|
) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ class WC_Product_CSV_Importer_Controller {
|
||||||
*
|
*
|
||||||
* @var bool
|
* @var bool
|
||||||
*/
|
*/
|
||||||
protected $skip_existing = false;
|
protected $update_existing = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get importer instance.
|
* Get importer instance.
|
||||||
|
@ -99,7 +99,7 @@ class WC_Product_CSV_Importer_Controller {
|
||||||
);
|
);
|
||||||
$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( $_REQUEST['file'] ) : '';
|
$this->file = isset( $_REQUEST['file'] ) ? wc_clean( $_REQUEST['file'] ) : '';
|
||||||
$this->skip_existing = isset( $_REQUEST['skip_existing'] ) ? (bool) $_REQUEST['skip_existing'] : false;
|
$this->update_existing = isset( $_REQUEST['update_existing'] ) ? (bool) $_REQUEST['update_existing'] : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,7 +130,7 @@ class WC_Product_CSV_Importer_Controller {
|
||||||
'step' => $keys[ $step_index + 1 ],
|
'step' => $keys[ $step_index + 1 ],
|
||||||
'file' => $this->file,
|
'file' => $this->file,
|
||||||
'delimiter' => $this->delimiter,
|
'delimiter' => $this->delimiter,
|
||||||
'skip_existing' => $this->skip_existing,
|
'update_existing' => $this->update_existing,
|
||||||
'_wpnonce' => wp_create_nonce( 'woocommerce-csv-importer' ), // wp_nonce_url() escapes & to & breaking redirects.
|
'_wpnonce' => wp_create_nonce( 'woocommerce-csv-importer' ), // wp_nonce_url() escapes & to & breaking redirects.
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -312,7 +312,7 @@ class WC_Product_CSV_Importer_Controller {
|
||||||
'import_nonce' => wp_create_nonce( 'wc-product-import' ),
|
'import_nonce' => wp_create_nonce( 'wc-product-import' ),
|
||||||
'mapping' => $mapping,
|
'mapping' => $mapping,
|
||||||
'file' => $this->file,
|
'file' => $this->file,
|
||||||
'skip_existing' => $this->skip_existing,
|
'update_existing' => $this->update_existing,
|
||||||
) );
|
) );
|
||||||
wp_enqueue_script( 'wc-product-import' );
|
wp_enqueue_script( 'wc-product-import' );
|
||||||
|
|
||||||
|
@ -324,8 +324,11 @@ class WC_Product_CSV_Importer_Controller {
|
||||||
* @todo Make this better.
|
* @todo Make this better.
|
||||||
*/
|
*/
|
||||||
protected function done() {
|
protected function done() {
|
||||||
$imported = isset( $_GET['imported'] ) ? absint( $_GET['imported'] ) : 0;
|
$imported = isset( $_GET['products-imported'] ) ? absint( $_GET['products-imported'] ) : 0;
|
||||||
$failed = isset( $_GET['failed'] ) ? absint( $_GET['failed'] ) : 0;
|
$updated = isset( $_GET['products-updated'] ) ? absint( $_GET['products-updated'] ) : 0;
|
||||||
|
$failed = isset( $_GET['products-failed'] ) ? absint( $_GET['products-failed'] ) : 0;
|
||||||
|
$skipped = isset( $_GET['products-skipped'] ) ? absint( $_GET['products-skipped'] ) : 0;
|
||||||
|
$errors = array_filter( (array) get_user_option( 'product_import_error_log' ) );
|
||||||
|
|
||||||
include_once( dirname( __FILE__ ) . '/views/html-csv-import-done.php' );
|
include_once( dirname( __FILE__ ) . '/views/html-csv-import-done.php' );
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,25 +9,84 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
<div class="wc-progress-form-content woocommerce-importer">
|
<div class="wc-progress-form-content woocommerce-importer">
|
||||||
<section class="woocommerce-importer-done">
|
<section class="woocommerce-importer-done">
|
||||||
<?php
|
<?php
|
||||||
$results = sprintf(
|
$results = array();
|
||||||
|
|
||||||
|
if ( 0 < $imported ) {
|
||||||
|
$results[] = sprintf(
|
||||||
/* translators: %d: products count */
|
/* translators: %d: products count */
|
||||||
_n( 'Imported %s product.', 'Imported %s products.', $imported, 'woocommerce' ),
|
_n( '%s product imported', '%s products imported', $imported, 'woocommerce' ),
|
||||||
'<strong>' . number_format_i18n( $imported ) . '</strong>'
|
'<strong>' . number_format_i18n( $imported ) . '</strong>'
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// @todo create a view to display errors or log with WC_Logger.
|
if ( 0 < $updated ) {
|
||||||
if ( 0 < $failed ) {
|
$results[] = sprintf(
|
||||||
$results .= ' ' . sprintf(
|
|
||||||
/* translators: %d: products count */
|
/* translators: %d: products count */
|
||||||
_n( 'Failed %s product.', 'Failed %s products.', $failed, 'woocommerce' ),
|
_n( '%s product updated', '%s products updated', $updated, 'woocommerce' ),
|
||||||
|
'<strong>' . number_format_i18n( $updated ) . '</strong>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( 0 < $skipped ) {
|
||||||
|
$results[] = sprintf(
|
||||||
|
/* translators: %d: products count */
|
||||||
|
_n( '%s product was skipped', '%s products were skipped', $skipped, 'woocommerce' ),
|
||||||
|
'<strong>' . number_format_i18n( $skipped ) . '</strong>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( 0 < $failed ) {
|
||||||
|
$results [] = sprintf(
|
||||||
|
/* translators: %d: products count */
|
||||||
|
_n( 'Failed to import %s product.', 'Failed to import %s products.', $failed, 'woocommerce' ),
|
||||||
'<strong>' . number_format_i18n( $failed ) . '</strong>'
|
'<strong>' . number_format_i18n( $failed ) . '</strong>'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( 0 < $failed || 0 < $skipped ) {
|
||||||
|
$results[] = '<a href="#" class="woocommerce-importer-done-view-errors">' . __( 'View import log', 'woocommerce' ) . '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
/* translators: %d: import results */
|
/* translators: %d: import results */
|
||||||
echo wp_kses_post( sprintf( __( 'Import complete: %s', 'woocommerce' ), $results ) );
|
echo wp_kses_post( __( 'Import complete!', 'woocommerce' ) . ' ' . implode( '. ', $results ) );
|
||||||
?>
|
?>
|
||||||
</section>
|
</section>
|
||||||
|
<section class="wc-importer-error-log" style="display:none">
|
||||||
|
<table class="widefat wc-importer-error-log-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><?php esc_html_e( 'Product', 'woocommerce' ); ?></th>
|
||||||
|
<th><?php esc_html_e( 'Reason for failure', 'woocommerce' ); ?></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php
|
||||||
|
if ( count( $errors ) ) {
|
||||||
|
foreach ( $errors as $error ) {
|
||||||
|
if ( ! is_wp_error( $error ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$error_data = $error->get_error_data();
|
||||||
|
?>
|
||||||
|
<tr>
|
||||||
|
<th><code><?php echo esc_html( $error_data['row'] ); ?></code></th>
|
||||||
|
<td><?php echo esc_html( $error->get_error_message() ); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
<script type="text/javascript">
|
||||||
|
jQuery(function() {
|
||||||
|
jQuery( '.woocommerce-importer-done-view-errors' ).on( 'click', function() {
|
||||||
|
jQuery( '.wc-importer-error-log' ).slideToggle();
|
||||||
|
return false;
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
</script>
|
||||||
<div class="wc-actions">
|
<div class="wc-actions">
|
||||||
<a class="button button-primary" href="<?php echo esc_url( admin_url( 'edit.php?post_type=product' ) ); ?>"><?php esc_html_e( 'View products', 'woocommerce' ); ?></a>
|
<a class="button button-primary" href="<?php echo esc_url( admin_url( 'edit.php?post_type=product' ) ); ?>"><?php esc_html_e( 'View products', 'woocommerce' ); ?></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -32,6 +32,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
<td class="wc-importer-mapping-table-field">
|
<td class="wc-importer-mapping-table-field">
|
||||||
<select name="map_to[<?php echo esc_attr( $name ); ?>]">
|
<select name="map_to[<?php echo esc_attr( $name ); ?>]">
|
||||||
<option value=""><?php esc_html_e( 'Do not import', 'woocommerce' ); ?></option>
|
<option value=""><?php esc_html_e( 'Do not import', 'woocommerce' ); ?></option>
|
||||||
|
<option value="">--------------</option>
|
||||||
<?php foreach ( $this->get_mapping_options( $mapped_value ) as $key => $value ) : ?>
|
<?php foreach ( $this->get_mapping_options( $mapped_value ) as $key => $value ) : ?>
|
||||||
<?php if ( is_array( $value ) ) : ?>
|
<?php if ( is_array( $value ) ) : ?>
|
||||||
<optgroup label="<?php echo esc_attr( $value['name'] ); ?>">
|
<optgroup label="<?php echo esc_attr( $value['name'] ); ?>">
|
||||||
|
@ -54,7 +55,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
<input type="submit" class="button button-primary button-next" value="<?php esc_attr_e( 'Run the importer', 'woocommerce' ); ?>" name="save_step" />
|
<input type="submit" class="button button-primary button-next" value="<?php esc_attr_e( 'Run the importer', 'woocommerce' ); ?>" name="save_step" />
|
||||||
<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="skip_existing" value="<?php echo (int) $this->skip_existing; ?>" />
|
<input type="hidden" name="update_existing" value="<?php echo (int) $this->update_existing; ?>" />
|
||||||
<?php wp_nonce_field( 'woocommerce-csv-importer' ); ?>
|
<?php wp_nonce_field( 'woocommerce-csv-importer' ); ?>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -17,7 +17,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">
|
<th scope="row">
|
||||||
<label for="upload">
|
<label for="upload">
|
||||||
<?php _e( 'Choose a file from your computer:', 'woocommerce' ); ?>
|
<?php _e( 'Choose a CSV file from your computer:', 'woocommerce' ); ?>
|
||||||
</label>
|
</label>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
|
@ -45,28 +45,47 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th><label for="woocommerce-importer-update-existing"><?php _e( 'Update existing products', 'woocommerce' ); ?></label><br/></th>
|
||||||
|
<td>
|
||||||
|
<input type="hidden" name="update_existing" value="0" />
|
||||||
|
<input type="checkbox" id="woocommerce-importer-update-existing" name="update_existing" value="1" />
|
||||||
|
<label for="woocommerce-importer-update-existing"><?php esc_html_e( 'If a product being imported matches an existing product ID or SKU, update the existing product data.', 'woocommerce' ); ?></label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="woocommerce-importer-advanced hidden">
|
||||||
<th>
|
<th>
|
||||||
<label for="file_url"><?php _e( 'OR enter the path to file on your server:', 'woocommerce' ); ?></label>
|
<label for="woocommerce-importer-file-url"><?php _e( '<em>or</em> enter the path to a CSV file on your server:', 'woocommerce' ); ?></label>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<code><?php echo esc_html( ABSPATH ) . ' '; ?></code><input type="text" id="file_url" name="file_url" size="25" />
|
<label for="woocommerce-importer-file-url" class="woocommerce-importer-file-url-field-wrapper">
|
||||||
|
<code><?php echo esc_html( ABSPATH ) . ' '; ?></code><input type="text" id="woocommerce-importer-file-url" name="file_url" />
|
||||||
|
</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr class="woocommerce-importer-advanced hidden">
|
||||||
<th><label><?php _e( 'CSV Delimiter', 'woocommerce' ); ?></label><br/></th>
|
<th><label><?php _e( 'CSV Delimiter', 'woocommerce' ); ?></label><br/></th>
|
||||||
<td><input type="text" name="delimiter" placeholder="," size="2" /></td>
|
<td><input type="text" name="delimiter" placeholder="," size="2" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<th><label><?php _e( 'Skip existing products', 'woocommerce' ); ?></label><br/></th>
|
|
||||||
<td>
|
|
||||||
<input type="hidden" name="skip_existing" value="0" />
|
|
||||||
<input type="checkbox" name="skip_existing" value="1" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</section>
|
</section>
|
||||||
|
<script type="text/javascript">
|
||||||
|
jQuery(function() {
|
||||||
|
jQuery( '.woocommerce-importer-toggle-advanced-options' ).on( 'click', function() {
|
||||||
|
var elements = jQuery( '.woocommerce-importer-advanced' );
|
||||||
|
if ( elements.is( '.hidden' ) ) {
|
||||||
|
elements.removeClass( 'hidden' );
|
||||||
|
jQuery( this ).text( jQuery( this ).data( 'hidetext' ) );
|
||||||
|
} else {
|
||||||
|
elements.addClass( 'hidden' );
|
||||||
|
jQuery( this ).text( jQuery( this ).data( 'showtext' ) );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} );
|
||||||
|
});
|
||||||
|
</script>
|
||||||
<div class="wc-actions">
|
<div class="wc-actions">
|
||||||
|
<a href="#" class="woocommerce-importer-toggle-advanced-options" data-hidetext="<?php esc_html_e( 'Hide advanced options', 'woocommerce' ); ?>" data-showtext="<?php esc_html_e( 'Hide advanced options', 'woocommerce' ); ?>"><?php esc_html_e( 'Show advanced options', 'woocommerce' ); ?></a>
|
||||||
<input type="submit" class="button button-primary button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step" />
|
<input type="submit" class="button button-primary button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step" />
|
||||||
<?php wp_nonce_field( 'woocommerce-csv-importer' ); ?>
|
<?php wp_nonce_field( 'woocommerce-csv-importer' ); ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -128,7 +128,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return min( round( ( $this->file_position / $size ) * 100 ), 100 );
|
return absint( min( round( ( $this->file_position / $size ) * 100 ), 100 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -196,7 +196,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
|
||||||
} elseif ( in_array( $type, array_keys( wc_get_product_types() ), true ) || 'variation' === $type ) {
|
} elseif ( in_array( $type, array_keys( wc_get_product_types() ), true ) || 'variation' === $type ) {
|
||||||
$product_type = $type;
|
$product_type = $type;
|
||||||
} else {
|
} else {
|
||||||
return new WP_Error( 'woocommerce_product_csv_importer_invalid_type', __( 'Invalid product type.', 'woocommerce' ), array( 'status' => 401 ) );
|
return new WP_Error( 'woocommerce_product_csv_importer_invalid_type', sprintf( __( 'Invalid product type %s.', 'woocommerce' ), $type ), array( 'type' => $type, 'status' => 401 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,6 +209,10 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
|
||||||
$product = new $classname( $id );
|
$product = new $classname( $id );
|
||||||
} elseif ( isset( $data['id'] ) ) {
|
} elseif ( isset( $data['id'] ) ) {
|
||||||
$product = wc_get_product( $id );
|
$product = wc_get_product( $id );
|
||||||
|
|
||||||
|
if ( ! $product ) {
|
||||||
|
return new WP_Error( 'woocommerce_product_csv_importer_invalid_id', sprintf( __( 'Invalid product ID %d.', 'woocommerce' ), $id ), array( 'id' => $id, 'status' => 401 ) );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$product = new WC_Product_Simple();
|
$product = new WC_Product_Simple();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
|
||||||
'lines' => -1, // Max lines to read.
|
'lines' => -1, // Max lines to read.
|
||||||
'mapping' => array(), // Column mapping. csv_heading => schema_heading.
|
'mapping' => array(), // Column mapping. csv_heading => schema_heading.
|
||||||
'parse' => false, // Whether to sanitize and format data.
|
'parse' => false, // Whether to sanitize and format data.
|
||||||
'skip_existing' => false, // Whether to skip existing items.
|
'update_existing' => false, // Whether to update existing items.
|
||||||
'delimiter' => ',', // CSV delimiter.
|
'delimiter' => ',', // CSV delimiter.
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -259,6 +259,31 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a string to identify the row from parsed data.
|
||||||
|
*
|
||||||
|
* @param array $parsed_data
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function get_row_id( $parsed_data ) {
|
||||||
|
$id = isset( $parsed_data['id'] ) ? absint( $parsed_data['id'] ) : 0;
|
||||||
|
$sku = isset( $parsed_data['sku'] ) ? esc_attr( $parsed_data['sku'] ) : '';
|
||||||
|
$name = isset( $parsed_data['name'] ) ? esc_attr( $parsed_data['name'] ) : '';
|
||||||
|
$row_data = array();
|
||||||
|
|
||||||
|
if ( $name ) {
|
||||||
|
$row_data[] = $name;
|
||||||
|
}
|
||||||
|
if ( $id ) {
|
||||||
|
$row_data[] = __( 'ID: ', 'woocommerce' ) . $id;
|
||||||
|
}
|
||||||
|
if ( $sku ) {
|
||||||
|
$row_data[] = __( 'SKU: ', 'woocommerce' ) . $sku;
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode( ', ', $row_data );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process importer.
|
* Process importer.
|
||||||
*
|
*
|
||||||
|
@ -268,20 +293,22 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
|
||||||
$data = array(
|
$data = array(
|
||||||
'imported' => array(),
|
'imported' => array(),
|
||||||
'failed' => array(),
|
'failed' => array(),
|
||||||
|
'updated' => array(),
|
||||||
|
'skipped' => array(),
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ( $this->parsed_data as $parsed_data ) {
|
foreach ( $this->parsed_data as $parsed_data_key => $parsed_data ) {
|
||||||
|
|
||||||
// Don't import products with IDs or SKUs that already exist if option is true.
|
// Don't import products with IDs or SKUs that already exist if option is true.
|
||||||
if ( $this->params['skip_existing'] ) {
|
if ( ! $this->params['update_existing'] ) {
|
||||||
$id = isset( $parsed_data['id'] ) ? absint( $parsed_data['id'] ) : 0;
|
$id = isset( $parsed_data['id'] ) ? absint( $parsed_data['id'] ) : 0;
|
||||||
$sku = isset( $parsed_data['sku'] ) ? esc_attr( $parsed_data['sku'] ) : '';
|
$sku = isset( $parsed_data['sku'] ) ? esc_attr( $parsed_data['sku'] ) : '';
|
||||||
|
|
||||||
if ( $id && wc_get_product( $id ) ) {
|
if ( $id && wc_get_product( $id ) ) {
|
||||||
$data['failed'][] = new WP_Error( 'woocommerce_product_csv_importer_error', __( 'A product with this ID already exists.', 'woocommerce' ), array( 'id' => $id ) );
|
$data['skipped'][] = new WP_Error( 'woocommerce_product_csv_importer_error', __( 'A product with this ID already exists.', 'woocommerce' ), array( 'id' => $id, 'row' => $this->get_row_id( $parsed_data ) ) );
|
||||||
continue;
|
continue;
|
||||||
} elseif ( $sku && wc_get_product_id_by_sku( $sku ) ) {
|
} elseif ( $sku && wc_get_product_id_by_sku( $sku ) ) {
|
||||||
$data['failed'][] = new WP_Error( 'woocommerce_product_csv_importer_error', __( 'A product with this SKU already exists.', 'woocommerce' ), array( 'sku' => $sku ) );
|
$data['skipped'][] = new WP_Error( 'woocommerce_product_csv_importer_error', __( 'A product with this SKU already exists.', 'woocommerce' ), array( 'sku' => $sku, 'row' => $this->get_row_id( $parsed_data ) ) );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,7 +316,10 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
|
||||||
$result = $this->process_item( $parsed_data );
|
$result = $this->process_item( $parsed_data );
|
||||||
|
|
||||||
if ( is_wp_error( $result ) ) {
|
if ( is_wp_error( $result ) ) {
|
||||||
|
$result->add_data( array( 'row' => $this->get_row_id( $parsed_data ) ) );
|
||||||
$data['failed'][] = $result;
|
$data['failed'][] = $result;
|
||||||
|
} elseif ( ! empty( $parsed_data['id'] ) ) {
|
||||||
|
$data['updated'][] = $result;
|
||||||
} else {
|
} else {
|
||||||
$data['imported'][] = $result;
|
$data['imported'][] = $result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue