2017-05-01 21:30:45 +00:00
< ? php
2018-03-09 20:24:44 +00:00
/**
* Class WC_Product_CSV_Importer_Controller file .
*
* @ package WooCommerce\Admin\Importers
*/
2017-05-01 21:30:45 +00:00
if ( ! defined ( 'ABSPATH' ) ) {
exit ;
}
if ( ! class_exists ( 'WP_Importer' ) ) {
return ;
}
/**
2017-05-17 13:16:38 +00:00
* Product importer controller - handles file upload and forms in admin .
2017-05-01 21:30:45 +00:00
*
* @ package WooCommerce / Admin / Importers
* @ version 3.1 . 0
*/
2017-05-17 13:16:38 +00:00
class WC_Product_CSV_Importer_Controller {
2017-05-01 21:30:45 +00:00
/**
2017-05-17 13:16:38 +00:00
* The path to the current file .
2017-05-01 21:30:45 +00:00
*
2017-05-17 13:16:38 +00:00
* @ var string
2017-05-01 21:30:45 +00:00
*/
2017-05-17 13:16:38 +00:00
protected $file = '' ;
2017-05-01 21:30:45 +00:00
/**
2017-05-17 13:16:38 +00:00
* The current import step .
2017-05-01 21:30:45 +00:00
*
* @ var string
*/
2017-05-17 13:16:38 +00:00
protected $step = '' ;
2017-05-01 21:30:45 +00:00
/**
2017-05-17 13:16:38 +00:00
* Progress steps .
2017-05-01 21:30:45 +00:00
*
2017-05-17 13:16:38 +00:00
* @ var array
*/
protected $steps = array ();
/**
* Errors .
*
* @ var array
2017-05-01 21:30:45 +00:00
*/
2017-05-17 13:16:38 +00:00
protected $errors = array ();
2017-05-01 21:30:45 +00:00
/**
2017-05-17 13:16:38 +00:00
* The current delimiter for the file being read .
2017-05-01 21:30:45 +00:00
*
* @ var string
*/
2017-05-17 13:16:38 +00:00
protected $delimiter = ',' ;
2017-05-01 21:30:45 +00:00
2017-12-09 08:58:07 +00:00
/**
* Whether to use previous mapping selections .
*
2017-12-12 05:12:53 +00:00
* @ var bool
2017-12-09 08:58:07 +00:00
*/
protected $map_preferences = false ;
2017-05-19 17:58:31 +00:00
/**
* Whether to skip existing products .
*
* @ var bool
*/
2017-05-23 14:05:32 +00:00
protected $update_existing = false ;
2017-05-19 17:58:31 +00:00
2017-05-18 16:49:58 +00:00
/**
* Get importer instance .
*
* @ param string $file File to import .
* @ param array $args Importer arguments .
* @ return WC_Product_CSV_Importer
*/
public static function get_importer ( $file , $args = array () ) {
$importer_class = apply_filters ( 'woocommerce_product_csv_importer_class' , 'WC_Product_CSV_Importer' );
2018-03-05 18:59:17 +00:00
$args = apply_filters ( 'woocommerce_product_csv_importer_args' , $args , $importer_class );
2017-05-18 16:49:58 +00:00
return new $importer_class ( $file , $args );
}
2018-09-18 18:06:34 +00:00
/**
* Check whether a file is a valid CSV file .
*
* @ param string $file File path .
2018-09-21 17:16:59 +00:00
* @ param bool $check_path Whether to also check the file is located in a valid location ( Default : true ) .
2018-09-18 18:06:34 +00:00
* @ return bool
*/
2018-09-21 17:16:59 +00:00
public static function is_file_valid_csv ( $file , $check_path = true ) {
2018-10-15 20:50:34 +00:00
if ( $check_path && apply_filters ( 'woocommerce_product_csv_importer_check_import_file_path' , true ) && false !== stripos ( $file , '://' ) ) {
2018-09-21 17:16:59 +00:00
return false ;
}
2018-09-18 18:06:34 +00:00
2018-09-21 17:16:59 +00:00
$valid_filetypes = self :: get_valid_csv_filetypes ();
2018-11-21 13:01:37 +00:00
$filetype = wp_check_filetype ( $file , $valid_filetypes );
2018-09-18 18:06:34 +00:00
if ( in_array ( $filetype [ 'type' ], $valid_filetypes , true ) ) {
return true ;
}
return false ;
}
2018-09-21 17:16:59 +00:00
/**
* Get all the valid filetypes for a CSV file .
*
* @ return array
*/
protected static function get_valid_csv_filetypes () {
return apply_filters (
2018-11-21 13:01:37 +00:00
'woocommerce_csv_product_import_valid_filetypes' ,
array (
2018-09-21 17:16:59 +00:00
'csv' => 'text/csv' ,
'txt' => 'text/plain' ,
)
);
}
2017-05-01 21:30:45 +00:00
/**
* Constructor .
*/
public function __construct () {
2017-09-13 18:26:15 +00:00
$default_steps = array (
2018-03-05 18:59:17 +00:00
'upload' => array (
2017-05-17 13:16:38 +00:00
'name' => __ ( 'Upload CSV file' , 'woocommerce' ),
'view' => array ( $this , 'upload_form' ),
'handler' => array ( $this , 'upload_form_handler' ),
),
'mapping' => array (
'name' => __ ( 'Column mapping' , 'woocommerce' ),
'view' => array ( $this , 'mapping_form' ),
'handler' => '' ,
),
2018-03-05 18:59:17 +00:00
'import' => array (
2017-05-17 13:16:38 +00:00
'name' => __ ( 'Import' , 'woocommerce' ),
'view' => array ( $this , 'import' ),
'handler' => '' ,
),
2018-03-05 18:59:17 +00:00
'done' => array (
2017-05-17 13:16:38 +00:00
'name' => __ ( 'Done!' , 'woocommerce' ),
'view' => array ( $this , 'done' ),
'handler' => '' ,
),
);
2017-09-13 18:26:15 +00:00
$this -> steps = apply_filters ( 'woocommerce_product_csv_importer_steps' , $default_steps );
2018-11-21 13:07:05 +00:00
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
2017-06-12 20:47:20 +00:00
$this -> step = isset ( $_REQUEST [ 'step' ] ) ? sanitize_key ( $_REQUEST [ 'step' ] ) : current ( array_keys ( $this -> steps ) );
2018-03-09 20:24:44 +00:00
$this -> file = isset ( $_REQUEST [ 'file' ] ) ? wc_clean ( wp_unslash ( $_REQUEST [ 'file' ] ) ) : '' ;
2017-05-23 14:05:32 +00:00
$this -> update_existing = isset ( $_REQUEST [ 'update_existing' ] ) ? ( bool ) $_REQUEST [ 'update_existing' ] : false ;
2018-03-09 20:24:44 +00:00
$this -> delimiter = ! empty ( $_REQUEST [ 'delimiter' ] ) ? wc_clean ( wp_unslash ( $_REQUEST [ 'delimiter' ] ) ) : ',' ;
2017-12-09 08:58:07 +00:00
$this -> map_preferences = isset ( $_REQUEST [ 'map_preferences' ] ) ? ( bool ) $_REQUEST [ 'map_preferences' ] : false ;
2018-03-09 20:24:44 +00:00
// phpcs:enable
2018-02-28 19:40:26 +00:00
if ( $this -> map_preferences ) {
add_filter ( 'woocommerce_csv_product_import_mapped_columns' , array ( $this , 'auto_map_user_preferences' ), 9999 );
}
2017-05-01 21:30:45 +00:00
}
/**
2017-05-17 13:16:38 +00:00
* Get the URL for the next step ' s screen .
2018-03-05 18:59:17 +00:00
*
2018-03-09 20:24:44 +00:00
* @ param string $step slug ( default : current step ) .
2017-05-17 13:16:38 +00:00
* @ return string URL for next step if a next step exists .
* Admin URL if it ' s the last step .
* Empty string on failure .
2017-05-01 21:30:45 +00:00
*/
2017-05-17 13:16:38 +00:00
public function get_next_step_link ( $step = '' ) {
if ( ! $step ) {
$step = $this -> step ;
}
2017-05-01 21:30:45 +00:00
2017-05-17 13:16:38 +00:00
$keys = array_keys ( $this -> steps );
2017-05-01 21:30:45 +00:00
2017-05-17 13:16:38 +00:00
if ( end ( $keys ) === $step ) {
return admin_url ();
}
2017-05-01 21:30:45 +00:00
2018-03-09 20:24:44 +00:00
$step_index = array_search ( $step , $keys , true );
2017-05-01 21:30:45 +00:00
2017-05-17 13:16:38 +00:00
if ( false === $step_index ) {
return '' ;
}
2017-05-01 21:30:45 +00:00
2017-05-17 13:16:38 +00:00
$params = array (
2017-05-25 15:41:11 +00:00
'step' => $keys [ $step_index + 1 ],
2017-06-13 04:07:27 +00:00
'file' => str_replace ( DIRECTORY_SEPARATOR , '/' , $this -> file ),
2017-05-25 15:41:11 +00:00
'delimiter' => $this -> delimiter ,
2017-05-23 14:05:32 +00:00
'update_existing' => $this -> update_existing ,
2017-12-09 08:58:07 +00:00
'map_preferences' => $this -> map_preferences ,
2017-05-25 15:41:11 +00:00
'_wpnonce' => wp_create_nonce ( 'woocommerce-csv-importer' ), // wp_nonce_url() escapes & to & breaking redirects.
2017-05-17 13:16:38 +00:00
);
2017-05-01 21:30:45 +00:00
2017-05-17 13:16:38 +00:00
return add_query_arg ( $params );
}
2017-05-10 20:15:28 +00:00
2017-05-17 13:16:38 +00:00
/**
* Output header view .
*/
protected function output_header () {
2018-03-05 18:59:17 +00:00
include dirname ( __FILE__ ) . '/views/html-csv-import-header.php' ;
2017-05-17 13:16:38 +00:00
}
/**
* Output steps view .
*/
protected function output_steps () {
2018-03-05 18:59:17 +00:00
include dirname ( __FILE__ ) . '/views/html-csv-import-steps.php' ;
2017-05-17 13:16:38 +00:00
}
/**
* Output footer view .
*/
protected function output_footer () {
2018-03-05 18:59:17 +00:00
include dirname ( __FILE__ ) . '/views/html-csv-import-footer.php' ;
2017-05-17 13:16:38 +00:00
}
/**
* Add error message .
2017-09-26 20:48:37 +00:00
*
* @ param string $message Error message .
* @ param array $actions List of actions with 'url' and 'label' .
2017-05-17 13:16:38 +00:00
*/
2017-09-26 20:48:37 +00:00
protected function add_error ( $message , $actions = array () ) {
$this -> errors [] = array (
'message' => $message ,
'actions' => $actions ,
);
2017-05-17 13:16:38 +00:00
}
/**
* Add error message .
*/
protected function output_errors () {
2017-09-26 20:48:37 +00:00
if ( ! $this -> errors ) {
return ;
}
foreach ( $this -> errors as $error ) {
echo '<div class="error inline">' ;
echo '<p>' . esc_html ( $error [ 'message' ] ) . '</p>' ;
if ( ! empty ( $error [ 'actions' ] ) ) {
echo '<p>' ;
foreach ( $error [ 'actions' ] as $action ) {
echo '<a class="button button-primary" href="' . esc_url ( $action [ 'url' ] ) . '">' . esc_html ( $action [ 'label' ] ) . '</a> ' ;
}
echo '</p>' ;
2017-05-17 13:16:38 +00:00
}
2017-09-26 20:48:37 +00:00
echo '</div>' ;
2017-05-17 13:16:38 +00:00
}
}
/**
* Dispatch current step and show correct view .
*/
public function dispatch () {
2018-11-21 13:07:05 +00:00
// phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
2017-05-17 21:34:49 +00:00
if ( ! empty ( $_POST [ 'save_step' ] ) && ! empty ( $this -> steps [ $this -> step ][ 'handler' ] ) ) {
2017-05-17 13:16:38 +00:00
call_user_func ( $this -> steps [ $this -> step ][ 'handler' ], $this );
}
$this -> output_header ();
$this -> output_steps ();
$this -> output_errors ();
call_user_func ( $this -> steps [ $this -> step ][ 'view' ], $this );
$this -> output_footer ();
}
2017-05-01 21:30:45 +00:00
2017-05-17 13:16:38 +00:00
/**
* Output information about the uploading process .
*/
protected function upload_form () {
$bytes = apply_filters ( 'import_upload_size_limit' , wp_max_upload_size () );
$size = size_format ( $bytes );
$upload_dir = wp_upload_dir ();
2018-03-05 18:59:17 +00:00
include dirname ( __FILE__ ) . '/views/html-product-csv-import-form.php' ;
2017-05-01 21:30:45 +00:00
}
/**
2017-05-17 13:16:38 +00:00
* Handle the upload form and store options .
2017-05-01 21:30:45 +00:00
*/
2017-05-17 13:16:38 +00:00
public function upload_form_handler () {
check_admin_referer ( 'woocommerce-csv-importer' );
$file = $this -> handle_upload ();
if ( is_wp_error ( $file ) ) {
2017-05-17 16:15:49 +00:00
$this -> add_error ( $file -> get_error_message () );
2017-05-17 13:16:38 +00:00
return ;
} else {
$this -> file = $file ;
2017-05-01 21:30:45 +00:00
}
2017-05-17 13:16:38 +00:00
wp_redirect ( esc_url_raw ( $this -> get_next_step_link () ) );
exit ;
2017-05-01 21:30:45 +00:00
}
/**
2017-05-24 06:26:17 +00:00
* Handles the CSV upload and initial parsing of the file to prepare for
2017-05-17 13:16:38 +00:00
* displaying author import options .
2017-05-01 21:30:45 +00:00
*
2017-05-17 13:16:38 +00:00
* @ return string | WP_Error
2017-05-01 21:30:45 +00:00
*/
2017-05-17 13:16:38 +00:00
public function handle_upload () {
2018-11-21 13:07:05 +00:00
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification -- Nonce already verified in WC_Product_CSV_Importer_Controller::upload_form_handler()
2018-05-25 10:57:01 +00:00
$file_url = isset ( $_POST [ 'file_url' ] ) ? wc_clean ( wp_unslash ( $_POST [ 'file_url' ] ) ) : '' ;
2018-03-09 20:24:44 +00:00
if ( empty ( $file_url ) ) {
2017-05-17 13:16:38 +00:00
if ( ! isset ( $_FILES [ 'import' ] ) ) {
2017-05-24 06:26:17 +00:00
return new WP_Error ( 'woocommerce_product_csv_importer_upload_file_empty' , __ ( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.' , 'woocommerce' ) );
2017-05-17 13:16:38 +00:00
}
2018-09-21 17:16:59 +00:00
if ( ! self :: is_file_valid_csv ( wc_clean ( wp_unslash ( $_FILES [ 'import' ][ 'name' ] ) ), false ) ) {
2017-06-21 18:50:03 +00:00
return new WP_Error ( 'woocommerce_product_csv_importer_upload_file_invalid' , __ ( 'Invalid file type. The importer supports CSV and TXT file formats.' , 'woocommerce' ) );
}
2018-03-05 18:59:17 +00:00
$overrides = array (
'test_form' => false ,
2018-09-21 17:16:59 +00:00
'mimes' => self :: get_valid_csv_filetypes (),
2018-03-05 18:59:17 +00:00
);
2018-05-29 14:25:11 +00:00
$import = $_FILES [ 'import' ]; // WPCS: sanitization ok, input var ok.
2018-04-04 18:50:08 +00:00
$upload = wp_handle_upload ( $import , $overrides );
2017-05-17 13:16:38 +00:00
if ( isset ( $upload [ 'error' ] ) ) {
2017-05-17 17:57:03 +00:00
return new WP_Error ( 'woocommerce_product_csv_importer_upload_error' , $upload [ 'error' ] );
2017-05-17 13:16:38 +00:00
}
2017-05-24 06:26:17 +00:00
// Construct the object array.
2017-05-17 13:16:38 +00:00
$object = array (
'post_title' => basename ( $upload [ 'file' ] ),
'post_content' => $upload [ 'url' ],
'post_mime_type' => $upload [ 'type' ],
'guid' => $upload [ 'url' ],
'context' => 'import' ,
'post_status' => 'private' ,
);
2017-05-24 06:26:17 +00:00
// Save the data.
2017-05-17 13:16:38 +00:00
$id = wp_insert_attachment ( $object , $upload [ 'file' ] );
/*
* Schedule a cleanup for one day from now in case of failed
* import or missing wp_import_cleanup () call .
*/
wp_schedule_single_event ( time () + DAY_IN_SECONDS , 'importer_scheduled_cleanup' , array ( $id ) );
return $upload [ 'file' ];
2018-03-09 20:24:44 +00:00
} elseif ( file_exists ( ABSPATH . $file_url ) ) {
2018-09-21 17:16:59 +00:00
if ( ! self :: is_file_valid_csv ( ABSPATH . $file_url ) ) {
2017-06-21 18:50:03 +00:00
return new WP_Error ( 'woocommerce_product_csv_importer_upload_file_invalid' , __ ( 'Invalid file type. The importer supports CSV and TXT file formats.' , 'woocommerce' ) );
}
2018-03-09 20:24:44 +00:00
return ABSPATH . $file_url ;
2017-05-01 21:30:45 +00:00
}
2018-03-09 20:24:44 +00:00
// phpcs:enable
2017-05-01 21:30:45 +00:00
2017-05-17 17:57:03 +00:00
return new WP_Error ( 'woocommerce_product_csv_importer_upload_invalid_file' , __ ( 'Please upload or provide the link to a valid CSV file.' , 'woocommerce' ) );
2017-05-17 13:16:38 +00:00
}
/**
2017-05-24 11:14:10 +00:00
* Mapping step .
2017-05-17 13:16:38 +00:00
*/
protected function mapping_form () {
2018-03-05 18:59:17 +00:00
$args = array (
2017-06-12 20:47:20 +00:00
'lines' => 1 ,
'delimiter' => $this -> delimiter ,
);
$importer = self :: get_importer ( $this -> file , $args );
2017-05-17 20:55:28 +00:00
$headers = $importer -> get_raw_keys ();
2017-05-17 23:59:36 +00:00
$mapped_items = $this -> auto_map_columns ( $headers );
2017-05-17 20:55:28 +00:00
$sample = current ( $importer -> get_raw_data () );
2017-05-17 13:16:38 +00:00
if ( empty ( $sample ) ) {
2017-09-26 20:48:37 +00:00
$this -> add_error (
__ ( 'The file is empty or using a different encoding than UTF-8, please try again with a new file.' , 'woocommerce' ),
array (
array (
'url' => admin_url ( 'edit.php?post_type=product&page=product_importer' ),
'label' => __ ( 'Upload a new file' , 'woocommerce' ),
),
)
);
// Force output the errors in the same page.
$this -> output_errors ();
2017-05-17 13:16:38 +00:00
return ;
}
2018-03-05 18:59:17 +00:00
include_once dirname ( __FILE__ ) . '/views/html-csv-import-mapping.php' ;
2017-05-17 13:16:38 +00:00
}
/**
2017-05-17 21:43:03 +00:00
* Import the file if it exists and is valid .
2017-05-17 13:16:38 +00:00
*/
public function import () {
2018-09-18 18:06:34 +00:00
if ( ! self :: is_file_valid_csv ( $this -> file ) ) {
$this -> add_error ( __ ( 'Invalid file type. The importer supports CSV and TXT file formats.' , 'woocommerce' ) );
$this -> output_errors ();
return ;
}
2017-05-17 13:16:38 +00:00
if ( ! is_file ( $this -> file ) ) {
$this -> add_error ( __ ( 'The file does not exist, please try again.' , 'woocommerce' ) );
2018-09-18 18:06:34 +00:00
$this -> output_errors ();
2017-05-17 13:16:38 +00:00
return ;
}
2017-05-01 21:30:45 +00:00
2018-11-21 13:07:05 +00:00
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification -- Nonce already verified in WC_Admin_Importers::do_ajax_product_import()
2018-03-09 20:24:44 +00:00
if ( ! empty ( $_POST [ 'map_from' ] ) && ! empty ( $_POST [ 'map_to' ] ) ) {
2018-02-28 19:36:35 +00:00
$mapping_from = wc_clean ( wp_unslash ( $_POST [ 'map_from' ] ) );
$mapping_to = wc_clean ( wp_unslash ( $_POST [ 'map_to' ] ) );
2017-12-09 08:58:07 +00:00
// Save mapping preferences for future imports.
2018-02-28 19:04:20 +00:00
update_user_option ( get_current_user_id (), 'woocommerce_product_import_mapping' , $mapping_to );
2017-05-19 14:06:36 +00:00
} else {
wp_redirect ( esc_url_raw ( $this -> get_next_step_link ( 'upload' ) ) );
exit ;
2017-05-10 20:15:28 +00:00
}
2018-03-09 20:24:44 +00:00
// phpcs:enable
2017-05-10 20:15:28 +00:00
2018-03-05 18:59:17 +00:00
wp_localize_script (
2018-11-21 13:01:37 +00:00
'wc-product-import' ,
'wc_product_import_params' ,
array (
2018-03-05 18:59:17 +00:00
'import_nonce' => wp_create_nonce ( 'wc-product-import' ),
'mapping' => array (
'from' => $mapping_from ,
'to' => $mapping_to ,
),
'file' => $this -> file ,
'update_existing' => $this -> update_existing ,
'delimiter' => $this -> delimiter ,
)
);
2017-05-17 21:34:49 +00:00
wp_enqueue_script ( 'wc-product-import' );
2017-05-19 12:25:03 +00:00
2018-03-05 18:59:17 +00:00
include_once dirname ( __FILE__ ) . '/views/html-csv-import-progress.php' ;
2017-05-17 21:34:49 +00:00
}
/**
* Done step .
*/
protected function done () {
2018-11-21 13:07:05 +00:00
// phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification
2017-05-23 14:05:32 +00:00
$imported = isset ( $_GET [ 'products-imported' ] ) ? absint ( $_GET [ 'products-imported' ] ) : 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' ) );
2018-03-09 20:24:44 +00:00
// phpcs:enable
2017-05-15 23:41:19 +00:00
2018-03-05 18:59:17 +00:00
include_once dirname ( __FILE__ ) . '/views/html-csv-import-done.php' ;
2017-05-01 21:30:45 +00:00
}
2017-10-26 10:20:06 +00:00
/**
* Columns to normalize .
*
* @ param array $columns List of columns names and keys .
* @ return array
*/
protected function normalize_columns_names ( $columns ) {
$normalized = array ();
foreach ( $columns as $key => $value ) {
$normalized [ strtolower ( $key ) ] = $value ;
}
return $normalized ;
}
2017-05-17 23:59:36 +00:00
/**
* Auto map column names .
*
2017-05-24 00:38:27 +00:00
* @ param array $raw_headers Raw header columns .
2017-05-24 18:11:16 +00:00
* @ param bool $num_indexes If should use numbers or raw header columns as indexes .
2017-05-17 23:59:36 +00:00
* @ return array
*/
2017-05-24 00:38:27 +00:00
protected function auto_map_columns ( $raw_headers , $num_indexes = true ) {
2018-03-05 18:59:17 +00:00
$weight_unit = get_option ( 'woocommerce_weight_unit' );
$dimension_unit = get_option ( 'woocommerce_dimension_unit' );
2017-05-29 18:16:44 +00:00
2018-03-05 18:59:17 +00:00
include dirname ( __FILE__ ) . '/mappings/mappings.php' ;
2017-05-29 18:16:44 +00:00
2018-03-09 20:24:44 +00:00
/*
2017-05-30 16:03:17 +00:00
* @ hooked wc_importer_generic_mappings - 10
* @ hooked wc_importer_wordpress_mappings - 10
2017-10-26 10:20:06 +00:00
* @ hooked wc_importer_default_english_mappings - 100
2017-05-30 16:03:17 +00:00
*/
2018-03-05 18:59:17 +00:00
$default_columns = $this -> normalize_columns_names (
apply_filters (
2018-11-21 13:01:37 +00:00
'woocommerce_csv_product_import_mapping_default_columns' ,
array (
2018-03-05 18:59:17 +00:00
__ ( 'ID' , 'woocommerce' ) => 'id' ,
__ ( 'Type' , 'woocommerce' ) => 'type' ,
__ ( 'SKU' , 'woocommerce' ) => 'sku' ,
__ ( 'Name' , 'woocommerce' ) => 'name' ,
__ ( 'Published' , 'woocommerce' ) => 'published' ,
__ ( 'Is featured?' , 'woocommerce' ) => 'featured' ,
__ ( 'Visibility in catalog' , 'woocommerce' ) => 'catalog_visibility' ,
__ ( 'Short description' , 'woocommerce' ) => 'short_description' ,
__ ( 'Description' , 'woocommerce' ) => 'description' ,
__ ( 'Date sale price starts' , 'woocommerce' ) => 'date_on_sale_from' ,
__ ( 'Date sale price ends' , 'woocommerce' ) => 'date_on_sale_to' ,
__ ( 'Tax status' , 'woocommerce' ) => 'tax_status' ,
__ ( 'Tax class' , 'woocommerce' ) => 'tax_class' ,
__ ( 'In stock?' , 'woocommerce' ) => 'stock_status' ,
__ ( 'Stock' , 'woocommerce' ) => 'stock_quantity' ,
__ ( 'Backorders allowed?' , 'woocommerce' ) => 'backorders' ,
2018-05-27 05:00:20 +00:00
__ ( 'Low stock amount' , 'woocommerce' ) => 'low_stock_amount' ,
2018-03-05 18:59:17 +00:00
__ ( 'Sold individually?' , 'woocommerce' ) => 'sold_individually' ,
2018-03-09 20:24:44 +00:00
/* translators: %s: Weight unit */
2018-03-05 18:59:17 +00:00
sprintf ( __ ( 'Weight (%s)' , 'woocommerce' ), $weight_unit ) => 'weight' ,
2018-03-09 20:24:44 +00:00
/* translators: %s: Length unit */
2018-03-05 18:59:17 +00:00
sprintf ( __ ( 'Length (%s)' , 'woocommerce' ), $dimension_unit ) => 'length' ,
2018-03-09 20:24:44 +00:00
/* translators: %s: Width unit */
2018-03-05 18:59:17 +00:00
sprintf ( __ ( 'Width (%s)' , 'woocommerce' ), $dimension_unit ) => 'width' ,
2018-03-09 20:24:44 +00:00
/* translators: %s: Height unit */
2018-03-05 18:59:17 +00:00
sprintf ( __ ( 'Height (%s)' , 'woocommerce' ), $dimension_unit ) => 'height' ,
__ ( 'Allow customer reviews?' , 'woocommerce' ) => 'reviews_allowed' ,
__ ( 'Purchase note' , 'woocommerce' ) => 'purchase_note' ,
__ ( 'Sale price' , 'woocommerce' ) => 'sale_price' ,
__ ( 'Regular price' , 'woocommerce' ) => 'regular_price' ,
__ ( 'Categories' , 'woocommerce' ) => 'category_ids' ,
__ ( 'Tags' , 'woocommerce' ) => 'tag_ids' ,
__ ( 'Shipping class' , 'woocommerce' ) => 'shipping_class_id' ,
__ ( 'Images' , 'woocommerce' ) => 'images' ,
__ ( 'Download limit' , 'woocommerce' ) => 'download_limit' ,
__ ( 'Download expiry days' , 'woocommerce' ) => 'download_expiry' ,
__ ( 'Parent' , 'woocommerce' ) => 'parent_id' ,
__ ( 'Upsells' , 'woocommerce' ) => 'upsell_ids' ,
__ ( 'Cross-sells' , 'woocommerce' ) => 'cross_sell_ids' ,
__ ( 'Grouped products' , 'woocommerce' ) => 'grouped_products' ,
__ ( 'External URL' , 'woocommerce' ) => 'product_url' ,
__ ( 'Button text' , 'woocommerce' ) => 'button_text' ,
__ ( 'Position' , 'woocommerce' ) => 'menu_order' ,
2019-04-15 13:24:56 +00:00
),
$raw_headers
2017-05-18 00:10:26 +00:00
)
2018-03-05 18:59:17 +00:00
);
$special_columns = $this -> get_special_columns (
$this -> normalize_columns_names (
apply_filters (
'woocommerce_csv_product_import_mapping_special_columns' ,
array (
2018-03-09 20:24:44 +00:00
/* translators: %d: Attribute number */
2018-03-05 18:59:17 +00:00
__ ( 'Attribute %d name' , 'woocommerce' ) => 'attributes:name' ,
2018-03-09 20:24:44 +00:00
/* translators: %d: Attribute number */
2018-03-05 18:59:17 +00:00
__ ( 'Attribute %d value(s)' , 'woocommerce' ) => 'attributes:value' ,
2018-03-09 20:24:44 +00:00
/* translators: %d: Attribute number */
2018-03-05 18:59:17 +00:00
__ ( 'Attribute %d visible' , 'woocommerce' ) => 'attributes:visible' ,
2018-03-09 20:24:44 +00:00
/* translators: %d: Attribute number */
2018-03-05 18:59:17 +00:00
__ ( 'Attribute %d global' , 'woocommerce' ) => 'attributes:taxonomy' ,
2018-03-09 20:24:44 +00:00
/* translators: %d: Attribute number */
2018-03-05 18:59:17 +00:00
__ ( 'Attribute %d default' , 'woocommerce' ) => 'attributes:default' ,
2018-03-09 20:24:44 +00:00
/* translators: %d: Download number */
2018-03-05 18:59:17 +00:00
__ ( 'Download %d name' , 'woocommerce' ) => 'downloads:name' ,
2018-03-09 20:24:44 +00:00
/* translators: %d: Download number */
2018-03-05 18:59:17 +00:00
__ ( 'Download %d URL' , 'woocommerce' ) => 'downloads:url' ,
2018-03-09 20:24:44 +00:00
/* translators: %d: Meta number */
2018-03-05 18:59:17 +00:00
__ ( 'Meta: %s' , 'woocommerce' ) => 'meta:' ,
2019-04-15 13:24:56 +00:00
),
$raw_headers
2018-03-05 18:59:17 +00:00
)
)
);
2017-05-17 20:55:28 +00:00
2017-05-24 00:38:27 +00:00
$headers = array ();
foreach ( $raw_headers as $key => $field ) {
2017-09-17 17:18:03 +00:00
$field = strtolower ( $field );
2017-05-24 00:38:27 +00:00
$index = $num_indexes ? $key : $field ;
$headers [ $index ] = $field ;
2017-05-17 23:59:36 +00:00
2017-10-26 10:20:06 +00:00
if ( isset ( $default_columns [ $field ] ) ) {
$headers [ $index ] = $default_columns [ $field ];
2017-05-17 23:59:36 +00:00
} else {
2017-06-22 21:06:10 +00:00
foreach ( $special_columns as $regex => $special_key ) {
2017-05-17 23:59:36 +00:00
if ( preg_match ( $regex , $field , $matches ) ) {
2017-05-24 00:38:27 +00:00
$headers [ $index ] = $special_key . $matches [ 1 ];
2017-05-17 23:59:36 +00:00
break ;
}
}
}
2017-05-17 20:55:28 +00:00
}
2017-05-24 00:38:27 +00:00
return apply_filters ( 'woocommerce_csv_product_import_mapped_columns' , $headers , $raw_headers );
2017-05-17 23:59:36 +00:00
}
2017-12-09 08:58:07 +00:00
/**
* Map columns using the user ' s lastest import mappings .
*
* @ param array $headers Header columns .
* @ return array
*/
public function auto_map_user_preferences ( $headers ) {
2018-02-28 19:04:20 +00:00
$mapping_preferences = get_user_option ( 'woocommerce_product_import_mapping' );
2017-12-09 08:58:07 +00:00
2018-02-28 19:46:52 +00:00
if ( ! empty ( $mapping_preferences ) && is_array ( $mapping_preferences ) ) {
2017-12-09 08:58:07 +00:00
return $mapping_preferences ;
}
return $headers ;
}
2017-05-17 23:59:36 +00:00
/**
* Sanitize special column name regex .
*
* @ param string $value Raw special column name .
* @ return string
*/
protected function sanitize_special_column_name_regex ( $value ) {
2018-06-11 13:55:36 +00:00
return '/' . str_replace ( array ( '%d' , '%s' ), '(.*)' , trim ( quotemeta ( $value ) ) ) . '/' ;
2017-05-17 20:55:28 +00:00
}
2017-06-22 21:06:10 +00:00
/**
* Get special columns .
*
* @ param array $columns Raw special columns .
* @ return array
*/
protected function get_special_columns ( $columns ) {
$formatted = array ();
foreach ( $columns as $key => $value ) {
$regex = $this -> sanitize_special_column_name_regex ( $key );
$formatted [ $regex ] = $value ;
}
return $formatted ;
}
2017-05-10 20:15:28 +00:00
/**
* Get mapping options .
*
2018-03-09 20:24:44 +00:00
* @ param string $item Item name .
2017-05-10 20:15:28 +00:00
* @ return array
*/
2017-05-10 21:56:29 +00:00
protected function get_mapping_options ( $item = '' ) {
2017-05-18 00:10:26 +00:00
// Get index for special column names.
$index = $item ;
2017-05-19 12:25:03 +00:00
2017-05-18 21:28:24 +00:00
if ( preg_match ( '/\d+$/' , $item , $matches ) ) {
2017-05-18 00:10:26 +00:00
$index = $matches [ 0 ];
2017-05-17 23:59:36 +00:00
}
2017-05-19 12:25:03 +00:00
2017-05-18 00:10:26 +00:00
// Properly format for meta field.
2017-05-17 23:59:36 +00:00
$meta = str_replace ( 'meta:' , '' , $item );
2017-05-18 00:10:26 +00:00
// Available options.
2017-05-10 20:15:28 +00:00
$weight_unit = get_option ( 'woocommerce_weight_unit' );
$dimension_unit = get_option ( 'woocommerce_dimension_unit' );
$options = array (
'id' => __ ( 'ID' , 'woocommerce' ),
'type' => __ ( 'Type' , 'woocommerce' ),
'sku' => __ ( 'SKU' , 'woocommerce' ),
'name' => __ ( 'Name' , 'woocommerce' ),
2017-05-17 20:55:28 +00:00
'published' => __ ( 'Published' , 'woocommerce' ),
2017-05-10 20:15:28 +00:00
'featured' => __ ( 'Is featured?' , 'woocommerce' ),
'catalog_visibility' => __ ( 'Visibility in catalog' , 'woocommerce' ),
2017-05-26 21:01:15 +00:00
'short_description' => __ ( 'Short description' , 'woocommerce' ),
2017-05-10 20:15:28 +00:00
'description' => __ ( 'Description' , 'woocommerce' ),
2017-06-12 21:08:23 +00:00
'price' => array (
'name' => __ ( 'Price' , 'woocommerce' ),
'options' => array (
'regular_price' => __ ( 'Regular price' , 'woocommerce' ),
'sale_price' => __ ( 'Sale price' , 'woocommerce' ),
'date_on_sale_from' => __ ( 'Date sale price starts' , 'woocommerce' ),
'date_on_sale_to' => __ ( 'Date sale price ends' , 'woocommerce' ),
),
),
2017-05-26 21:01:15 +00:00
'tax_status' => __ ( 'Tax status' , 'woocommerce' ),
'tax_class' => __ ( 'Tax class' , 'woocommerce' ),
2017-05-10 20:15:28 +00:00
'stock_status' => __ ( 'In stock?' , 'woocommerce' ),
2017-06-12 21:08:23 +00:00
'stock_quantity' => _x ( 'Stock' , 'Quantity in stock' , 'woocommerce' ),
2017-05-10 20:15:28 +00:00
'backorders' => __ ( 'Backorders allowed?' , 'woocommerce' ),
2018-05-27 05:00:20 +00:00
'low_stock_amount' => __ ( 'Low stock amount' , 'woocommerce' ),
2017-05-10 20:15:28 +00:00
'sold_individually' => __ ( 'Sold individually?' , 'woocommerce' ),
/* translators: %s: weight unit */
'weight' => sprintf ( __ ( 'Weight (%s)' , 'woocommerce' ), $weight_unit ),
2017-05-17 23:59:36 +00:00
'dimensions' => array (
'name' => __ ( 'Dimensions' , 'woocommerce' ),
'options' => array (
/* translators: %s: dimension unit */
2018-03-05 18:59:17 +00:00
'length' => sprintf ( __ ( 'Length (%s)' , 'woocommerce' ), $dimension_unit ),
2017-05-17 23:59:36 +00:00
/* translators: %s: dimension unit */
2018-03-05 18:59:17 +00:00
'width' => sprintf ( __ ( 'Width (%s)' , 'woocommerce' ), $dimension_unit ),
2017-05-17 23:59:36 +00:00
/* translators: %s: dimension unit */
2018-03-05 18:59:17 +00:00
'height' => sprintf ( __ ( 'Height (%s)' , 'woocommerce' ), $dimension_unit ),
2017-05-17 23:59:36 +00:00
),
),
2017-05-10 20:15:28 +00:00
'category_ids' => __ ( 'Categories' , 'woocommerce' ),
'tag_ids' => __ ( 'Tags' , 'woocommerce' ),
2017-05-26 21:01:15 +00:00
'shipping_class_id' => __ ( 'Shipping class' , 'woocommerce' ),
2017-05-26 22:30:42 +00:00
'images' => __ ( 'Images' , 'woocommerce' ),
2017-05-17 20:55:28 +00:00
'parent_id' => __ ( 'Parent' , 'woocommerce' ),
'upsell_ids' => __ ( 'Upsells' , 'woocommerce' ),
'cross_sell_ids' => __ ( 'Cross-sells' , 'woocommerce' ),
2017-05-30 17:50:54 +00:00
'grouped_products' => __ ( 'Grouped products' , 'woocommerce' ),
2017-05-22 23:18:39 +00:00
'external' => array (
'name' => __ ( 'External product' , 'woocommerce' ),
'options' => array (
2018-03-05 18:59:17 +00:00
'product_url' => __ ( 'External URL' , 'woocommerce' ),
'button_text' => __ ( 'Button text' , 'woocommerce' ),
2017-05-22 23:18:39 +00:00
),
),
2017-05-17 23:59:36 +00:00
'downloads' => array (
'name' => __ ( 'Downloads' , 'woocommerce' ),
'options' => array (
2017-05-26 21:01:15 +00:00
'downloads:name' . $index => __ ( 'Download name' , 'woocommerce' ),
2017-05-18 00:10:26 +00:00
'downloads:url' . $index => __ ( 'Download URL' , 'woocommerce' ),
2017-05-26 21:01:15 +00:00
'download_limit' => __ ( 'Download limit' , 'woocommerce' ),
'download_expiry' => __ ( 'Download expiry days' , 'woocommerce' ),
2017-05-17 23:59:36 +00:00
),
),
2017-05-10 20:15:28 +00:00
'attributes' => array (
'name' => __ ( 'Attributes' , 'woocommerce' ),
'options' => array (
2017-05-30 21:46:32 +00:00
'attributes:name' . $index => __ ( 'Attribute name' , 'woocommerce' ),
'attributes:value' . $index => __ ( 'Attribute value(s)' , 'woocommerce' ),
'attributes:taxonomy' . $index => __ ( 'Is a global attribute?' , 'woocommerce' ),
'attributes:visible' . $index => __ ( 'Attribute visibility' , 'woocommerce' ),
'attributes:default' . $index => __ ( 'Default attribute' , 'woocommerce' ),
2017-05-10 20:15:28 +00:00
),
),
2017-06-12 21:08:23 +00:00
'reviews_allowed' => __ ( 'Allow customer reviews?' , 'woocommerce' ),
'purchase_note' => __ ( 'Purchase note' , 'woocommerce' ),
2017-05-17 23:59:36 +00:00
'meta:' . $meta => __ ( 'Import as meta' , 'woocommerce' ),
2017-08-22 20:22:39 +00:00
'menu_order' => __ ( 'Position' , 'woocommerce' ),
2017-05-10 20:15:28 +00:00
);
2017-05-15 22:49:53 +00:00
return apply_filters ( 'woocommerce_csv_product_import_mapping_options' , $options , $item );
2017-05-10 20:15:28 +00:00
}
2017-05-01 21:30:45 +00:00
}