woocommerce/includes/import/class-wc-product-csv-import...

724 lines
20 KiB
PHP
Raw Normal View History

2017-05-15 22:49:53 +00:00
<?php
/**
* WooCommerce Product CSV importer
*
* @author Automattic
* @category Admin
* @package WooCommerce/Import
* @version 3.1.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Include dependencies.
*/
2017-05-16 04:02:46 +00:00
if ( ! class_exists( 'WC_Product_Importer', false ) ) {
include_once( dirname( __FILE__ ) . '/abstract-wc-product-importer.php' );
2017-05-15 22:49:53 +00:00
}
/**
* WC_Product_CSV_Importer Class.
2017-05-15 22:49:53 +00:00
*/
2017-05-16 04:02:46 +00:00
class WC_Product_CSV_Importer extends WC_Product_Importer {
2017-05-15 22:49:53 +00:00
/**
* Initialize importer.
*
* @param string $file File to read.
* @param array $args Arguments for the parser.
*/
public function __construct( $file, $params = array() ) {
$default_args = array(
2017-06-14 18:35:22 +00:00
'start_pos' => 0, // File pointer start.
'end_pos' => -1, // File pointer end.
'lines' => -1, // Max lines to read.
'mapping' => array(), // Column mapping. csv_heading => schema_heading.
'parse' => false, // Whether to sanitize and format data.
'update_existing' => false, // Whether to update existing items.
'delimiter' => ',', // CSV delimiter.
'prevent_timeouts' => true, // Check memory and time usage and abort if reaching limit.
2017-05-15 22:49:53 +00:00
);
$this->params = wp_parse_args( $params, $default_args );
$this->file = $file;
$this->read_file();
}
/**
* Read file.
*
* @return array
*/
protected function read_file() {
if ( false !== ( $handle = fopen( $this->file, 'r' ) ) ) {
$this->raw_keys = fgetcsv( $handle, 0, $this->params['delimiter'] );
if ( 0 !== $this->params['start_pos'] ) {
fseek( $handle, (int) $this->params['start_pos'] );
}
while ( false !== ( $row = fgetcsv( $handle, 0, $this->params['delimiter'] ) ) ) {
2017-06-14 13:02:47 +00:00
$this->raw_data[] = $row;
$this->file_positions[ count( $this->raw_data ) ] = ftell( $handle );
2017-05-15 22:49:53 +00:00
2017-05-19 13:33:40 +00:00
if ( ( $this->params['end_pos'] > 0 && ftell( $handle ) >= $this->params['end_pos'] ) || 0 === --$this->params['lines'] ) {
break;
2017-05-15 22:49:53 +00:00
}
}
$this->file_position = ftell( $handle );
2017-05-15 22:49:53 +00:00
}
if ( ! empty( $this->params['mapping'] ) ) {
$this->set_mapped_keys();
}
if ( $this->params['parse'] ) {
$this->set_parsed_data();
}
}
/**
* Set file mapped keys.
*
* @return array
*/
protected function set_mapped_keys() {
$mapping = $this->params['mapping'];
foreach ( $this->raw_keys as $key ) {
$this->mapped_keys[] = isset( $mapping[ $key ] ) ? $mapping[ $key ] : $key;
}
}
2017-05-18 21:32:03 +00:00
/**
* Parse relative field and return product ID.
2017-05-25 13:54:49 +00:00
*
* Handles `id:xx` and SKUs.
*
* If mapping to an id: and the product ID does not exist, this link is not
* valid.
*
* If mapping to a SKU and the product ID does not exist, a temporary object
* will be created so it can be updated later.
2017-05-18 21:32:03 +00:00
*
* @param string $field Field value.
2017-05-18 23:15:42 +00:00
* @return int|string
2017-05-18 21:32:03 +00:00
*/
protected function parse_relative_field( $field ) {
global $wpdb;
2017-05-18 23:15:42 +00:00
if ( empty( $field ) ) {
return '';
}
2017-05-18 21:32:03 +00:00
if ( preg_match( '/^id:(\d+)$/', $field, $matches ) ) {
$id = intval( $matches[1] );
$original_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_original_id' AND meta_value = %s;", $id ) );
return $original_id ? $original_id : $id;
2017-05-18 21:32:03 +00:00
}
2017-05-25 13:54:49 +00:00
if ( $id = wc_get_product_id_by_sku( $field ) ) {
return $id;
}
try {
$product = new WC_Product_Simple();
$product->set_name( 'Import placeholder for ' . $field );
$product->set_status( 'importing' );
$product->set_sku( $field );
$id = $product->save();
if ( $id && ! is_wp_error( $id ) ) {
return $id;
}
} catch ( Exception $e ) {
return '';
}
return '';
2017-05-18 21:32:03 +00:00
}
/**
* Parse the ID field.
*
* If we're not doing an update, create a placeholder product so mapping works
* for rows following this one.
*
* @return int
*/
protected function parse_id_field( $field ) {
$field = absint( $field );
// Not updating? Make sure we have a new placeholder for this ID.
if ( $field && ! $this->params['update_existing'] ) {
$product = new WC_Product_Simple();
$product->set_name( 'Import placeholder for ' . $field );
$product->set_status( 'importing' );
$product->add_meta_data( '_original_id', $field, true );
$field = $product->save();
}
return $field && ! is_wp_error( $field ) ? $field : 0;
}
2017-05-18 21:32:03 +00:00
/**
* Parse reletive comma-delineated field and return product ID.
*
* @param string $field Field value.
* @return array
*/
protected function parse_relative_comma_field( $field ) {
if ( empty( $field ) ) {
return array();
}
return array_filter( array_map( array( $this, 'parse_relative_field' ), array_map( 'trim', explode( ',', $field ) ) ) );
}
2017-05-15 22:49:53 +00:00
/**
* Parse a comma-delineated field from a CSV.
*
* @param string $field Field value.
2017-05-15 22:49:53 +00:00
* @return array
*/
protected function parse_comma_field( $field ) {
if ( empty( $field ) ) {
return array();
}
return array_map( 'wc_clean', array_map( 'trim', explode( ',', $field ) ) );
2017-05-15 22:49:53 +00:00
}
/**
* Parse a field that is generally '1' or '0' but can be something else.
*
* @param string $field Field value.
2017-05-15 22:49:53 +00:00
* @return bool|string
*/
protected function parse_bool_field( $field ) {
if ( '0' === $field ) {
return false;
}
if ( '1' === $field ) {
return true;
}
// Don't return explicit true or false for empty fields or values like 'notify'.
return wc_clean( $field );
2017-05-15 22:49:53 +00:00
}
/**
* Parse a float value field.
*
* @param string $field Field value.
2017-05-15 22:49:53 +00:00
* @return float|string
*/
protected function parse_float_field( $field ) {
if ( '' === $field ) {
return $field;
}
return floatval( $field );
}
/**
* Parse a category field from a CSV.
* Categories are separated by commas and subcategories are "parent > subcategory".
*
* @param string $field Field value.
2017-05-15 22:49:53 +00:00
* @return array of arrays with "parent" and "name" keys.
*/
2017-05-24 06:14:54 +00:00
protected function parse_categories_field( $field ) {
2017-05-15 22:49:53 +00:00
if ( empty( $field ) ) {
return array();
}
2017-05-24 00:06:16 +00:00
$row_terms = array_map( 'trim', explode( ',', $field ) );
2017-05-15 22:49:53 +00:00
$categories = array();
2017-05-24 00:06:16 +00:00
foreach ( $row_terms as $row_term ) {
$parent = null;
$_terms = array_map( 'trim', explode( '>', $row_term ) );
$total = count( $_terms );
foreach ( $_terms as $index => $_term ) {
// Check if category exists. Parent must be empty string or null if doesn't exists.
2017-05-24 06:26:17 +00:00
// @codingStandardsIgnoreStart
2017-05-24 00:06:16 +00:00
$term = term_exists( $_term, 'product_cat', $parent );
2017-05-24 06:26:17 +00:00
// @codingStandardsIgnoreEnd
2017-05-24 00:06:16 +00:00
if ( is_array( $term ) ) {
$term_id = $term['term_id'];
} else {
$term = wp_insert_term( $_term, 'product_cat', array( 'parent' => intval( $parent ) ) );
$term_id = $term['term_id'];
}
// Only requires assign the last category.
2017-05-24 06:26:17 +00:00
if ( ( 1 + $index ) === $total ) {
2017-05-24 00:06:16 +00:00
$categories[] = $term_id;
} else {
// Store parent to be able to insert or query categories based in parent ID.
$parent = $term_id;
}
2017-05-15 22:49:53 +00:00
}
}
return $categories;
}
2017-05-22 21:54:30 +00:00
/**
* Parse a tag field from a CSV.
*
* @param string $field Field value.
* @return array
*/
2017-05-24 06:14:54 +00:00
protected function parse_tags_field( $field ) {
2017-05-22 21:54:30 +00:00
if ( empty( $field ) ) {
return array();
}
$names = array_map( 'trim', explode( ',', $field ) );
2017-05-22 21:54:30 +00:00
$tags = array();
foreach ( $names as $name ) {
$term = get_term_by( 'name', $name, 'product_tag' );
if ( ! $term || is_wp_error( $term ) ) {
$term = (object) wp_insert_term( $name, 'product_tag' );
2017-05-22 21:54:30 +00:00
}
$tags[] = $term->term_id;
2017-05-22 21:54:30 +00:00
}
return $tags;
}
/**
* Parse a shipping class field from a CSV.
*
* @param string $field Field value.
* @return int
*/
2017-05-24 06:14:54 +00:00
protected function parse_shipping_class_field( $field ) {
2017-05-26 05:21:57 +00:00
if ( empty( $field ) ) {
return 0;
}
$term = get_term_by( 'name', $field, 'product_shipping_class' );
if ( ! $term || is_wp_error( $term ) ) {
2017-05-26 05:21:57 +00:00
$term = (object) wp_insert_term( $field, 'product_shipping_class' );
2017-05-22 21:54:30 +00:00
}
return $term->term_id;
2017-05-22 21:54:30 +00:00
}
2017-05-24 06:14:54 +00:00
/**
* Parse images list from a CSV.
*
* @param string $field Field value.
* @return array
*/
protected function parse_images_field( $field ) {
if ( empty( $field ) ) {
return array();
}
return array_map( 'esc_url_raw', array_map( 'trim', explode( ',', $field ) ) );
}
/**
* Parse dates from a CSV.
* Dates requires the format YYYY-MM-DD.
*
* @param string $field Field value.
* @return string|null
*/
protected function parse_date_field( $field ) {
if ( empty( $field ) ) {
return null;
}
if ( preg_match( '/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $field ) ) {
return $field;
}
return null;
}
2017-05-26 22:39:20 +00:00
/**
* Parse backorders from a CSV.
*
* @param string $field Field value.
* @return string
*/
protected function parse_backorders_field( $field ) {
if ( empty( $field ) ) {
return '';
}
$field = $this->parse_bool_field( $field );
if ( 'notify' === $field ) {
return 'notify';
} elseif ( is_bool( $field ) ) {
return $field ? 'yes' : 'no';
}
return '';
}
2017-05-15 22:49:53 +00:00
/**
* Get formatting callback.
2017-05-15 22:49:53 +00:00
*
* @return array
*/
protected function get_formating_callback() {
2017-05-15 22:49:53 +00:00
/**
* Columns not mentioned here will get parsed with 'wc_clean'.
2017-05-15 22:49:53 +00:00
* column_name => callback.
*/
$data_formatting = array(
'id' => array( $this, 'parse_id_field' ),
2017-05-19 00:09:25 +00:00
'type' => array( $this, 'parse_comma_field' ),
'published' => array( $this, 'parse_bool_field' ),
2017-05-15 22:49:53 +00:00
'featured' => array( $this, 'parse_bool_field' ),
'date_on_sale_from' => array( $this, 'parse_date_field' ),
'date_on_sale_to' => array( $this, 'parse_date_field' ),
2017-05-26 14:57:17 +00:00
'name' => 'wp_filter_post_kses',
'short_description' => 'wp_filter_post_kses',
'description' => 'wp_filter_post_kses',
2017-05-15 22:49:53 +00:00
'manage_stock' => array( $this, 'parse_bool_field' ),
2017-05-26 22:39:20 +00:00
'backorders' => array( $this, 'parse_backorders_field' ),
2017-05-19 00:09:25 +00:00
'stock_status' => array( $this, 'parse_bool_field' ),
2017-05-15 22:49:53 +00:00
'sold_individually' => array( $this, 'parse_bool_field' ),
'width' => array( $this, 'parse_float_field' ),
'length' => array( $this, 'parse_float_field' ),
'height' => array( $this, 'parse_float_field' ),
'weight' => array( $this, 'parse_float_field' ),
'reviews_allowed' => array( $this, 'parse_bool_field' ),
2017-05-26 14:57:17 +00:00
'purchase_note' => 'wp_filter_post_kses',
2017-05-15 22:49:53 +00:00
'price' => 'wc_format_decimal',
'regular_price' => 'wc_format_decimal',
2017-05-26 21:53:22 +00:00
'stock_quantity' => 'wc_stock_amount',
2017-05-24 06:14:54 +00:00
'category_ids' => array( $this, 'parse_categories_field' ),
'tag_ids' => array( $this, 'parse_tags_field' ),
'shipping_class_id' => array( $this, 'parse_shipping_class_field' ),
2017-05-26 14:57:17 +00:00
'images' => array( $this, 'parse_images_field' ),
2017-05-18 21:32:03 +00:00
'parent_id' => array( $this, 'parse_relative_field' ),
'grouped_products' => array( $this, 'parse_relative_comma_field' ),
2017-05-18 21:32:03 +00:00
'upsell_ids' => array( $this, 'parse_relative_comma_field' ),
'cross_sell_ids' => array( $this, 'parse_relative_comma_field' ),
2017-05-15 22:49:53 +00:00
'download_limit' => 'absint',
'download_expiry' => 'absint',
2017-05-26 18:26:55 +00:00
'product_url' => 'esc_url_raw',
2017-05-15 22:49:53 +00:00
);
/**
* Match special column names.
2017-05-15 22:49:53 +00:00
*/
$regex_match_data_formatting = array(
'/attributes:value*/' => array( $this, 'parse_comma_field' ),
'/attributes:visible*/' => array( $this, 'parse_bool_field' ),
'/attributes:taxonomy*/' => array( $this, 'parse_bool_field' ),
'/downloads:url*/' => 'esc_url',
'/meta:*/' => 'wp_kses_post', // Allow some HTML in meta fields.
2017-05-15 22:49:53 +00:00
);
$callbacks = array();
2017-05-15 22:49:53 +00:00
// Figure out the parse function for each column.
foreach ( $this->get_mapped_keys() as $index => $heading ) {
$callback = 'wc_clean';
2017-05-15 22:49:53 +00:00
if ( isset( $data_formatting[ $heading ] ) ) {
$callback = $data_formatting[ $heading ];
2017-05-15 22:49:53 +00:00
} else {
foreach ( $regex_match_data_formatting as $regex => $callback ) {
if ( preg_match( $regex, $heading ) ) {
$callback = $callback;
2017-05-15 22:49:53 +00:00
break;
}
}
}
$callbacks[] = $callback;
}
return $callbacks;
}
/**
* Check if strings starts with determined word.
*
* @param string $haystack Complete sentence.
* @param string $needle Excerpt.
* @return bool
*/
protected function starts_with( $haystack, $needle ) {
2017-05-24 06:26:17 +00:00
return substr( $haystack, 0, strlen( $needle ) ) === $needle;
}
/**
2017-05-26 14:57:17 +00:00
* Expand special and internal data into the correct formats for the product CRUD.
*
* @param array $data Data to import.
* @return array
*/
protected function expand_data( $data ) {
$data = apply_filters( 'woocommerce_product_importer_pre_expand_data', $data );
2017-05-26 14:57:17 +00:00
// Status is mapped from a special published field.
if ( isset( $data['published'] ) ) {
$data['status'] = ( $data['published'] ? 'publish' : 'draft' );
unset( $data['published'] );
}
// Images field maps to image and gallery id fields.
if ( isset( $data['images'] ) ) {
$images = $data['images'];
$data['raw_image_id'] = array_shift( $images );
2017-05-24 06:14:54 +00:00
if ( ! empty( $images ) ) {
2017-05-26 14:57:17 +00:00
$data['raw_gallery_image_ids'] = $images;
2017-05-24 06:14:54 +00:00
}
2017-05-26 14:57:17 +00:00
unset( $data['images'] );
2017-05-24 06:14:54 +00:00
}
2017-05-26 14:57:17 +00:00
// Type, virtual and downloadable are all stored in the same column.
if ( isset( $data['type'] ) ) {
2017-05-25 13:54:49 +00:00
$data['type'] = array_map( 'strtolower', $data['type'] );
$data['virtual'] = in_array( 'virtual', $data['type'], true );
$data['downloadable'] = in_array( 'downloadable', $data['type'], true );
// Convert type to string.
$data['type'] = current( array_diff( $data['type'], array( 'virtual', 'downloadable' ) ) );
}
2017-05-26 18:41:44 +00:00
if ( isset( $data['stock_quantity'] ) ) {
2017-05-26 18:26:55 +00:00
$data['manage_stock'] = 0 < $data['stock_quantity'];
}
2017-05-26 14:57:17 +00:00
// Stock is bool.
if ( isset( $data['stock_status'] ) ) {
2017-05-26 18:26:55 +00:00
$data['stock_status'] = $data['stock_status'] ? 'instock' : 'outofstock';
}
// Prepare grouped products.
if ( isset( $data['grouped_products'] ) ) {
$data['children'] = $data['grouped_products'];
unset( $data['grouped_products'] );
}
2017-05-26 14:57:17 +00:00
// Handle special column names which span multiple columns.
$attributes = array();
$downloads = array();
$meta_data = array();
foreach ( $data as $key => $value ) {
// Attributes.
if ( $this->starts_with( $key, 'attributes:name' ) ) {
if ( ! empty( $value ) ) {
2017-05-26 14:57:17 +00:00
$attributes[ str_replace( 'attributes:name', '', $key ) ]['name'] = $value;
}
unset( $data[ $key ] );
2017-05-26 15:54:43 +00:00
} elseif ( $this->starts_with( $key, 'attributes:value' ) ) {
$attributes[ str_replace( 'attributes:value', '', $key ) ]['value'] = $value;
unset( $data[ $key ] );
2017-05-26 15:54:43 +00:00
} elseif ( $this->starts_with( $key, 'attributes:taxonomy' ) ) {
$attributes[ str_replace( 'attributes:taxonomy', '', $key ) ]['taxonomy'] = wc_string_to_bool( $value );
unset( $data[ $key ] );
2017-05-26 15:54:43 +00:00
} elseif ( $this->starts_with( $key, 'attributes:visible' ) ) {
$attributes[ str_replace( 'attributes:visible', '', $key ) ]['visible'] = wc_string_to_bool( $value );
2017-05-24 06:42:15 +00:00
unset( $data[ $key ] );
2017-05-26 15:54:43 +00:00
} elseif ( $this->starts_with( $key, 'attributes:default' ) ) {
if ( ! empty( $value ) ) {
$attributes[ str_replace( 'attributes:default', '', $key ) ]['default'] = $value;
}
unset( $data[ $key ] );
// Downloads.
2017-05-26 15:54:43 +00:00
} elseif ( $this->starts_with( $key, 'downloads:name' ) ) {
if ( ! empty( $value ) ) {
2017-05-26 14:57:17 +00:00
$downloads[ str_replace( 'downloads:name', '', $key ) ]['name'] = $value;
}
unset( $data[ $key ] );
2017-05-26 15:54:43 +00:00
} elseif ( $this->starts_with( $key, 'downloads:url' ) ) {
if ( ! empty( $value ) ) {
2017-05-26 14:57:17 +00:00
$downloads[ str_replace( 'downloads:url', '', $key ) ]['url'] = $value;
}
unset( $data[ $key ] );
// Meta data.
2017-05-26 15:54:43 +00:00
} elseif ( $this->starts_with( $key, 'meta:' ) ) {
2017-05-26 14:57:17 +00:00
$meta_data[] = array(
'key' => str_replace( 'meta:', '', $key ),
'value' => $value,
);
unset( $data[ $key ] );
}
2017-05-15 22:49:53 +00:00
}
2017-05-26 14:57:17 +00:00
if ( ! empty( $attributes ) ) {
// Remove empty attributes and clear indexes.
foreach ( $attributes as $attribute ) {
if ( empty( $attribute['name'] ) ) {
continue;
}
$data['raw_attributes'][] = $attribute;
}
2017-05-26 14:57:17 +00:00
}
2017-05-26 15:54:43 +00:00
2017-05-26 14:57:17 +00:00
if ( ! empty( $downloads ) ) {
$data['downloads'] = array();
foreach ( $downloads as $key => $file ) {
if ( empty( $file['url'] ) ) {
continue;
}
$data['downloads'][] = array(
'name' => $file['name'] ? $file['name'] : wc_get_filename_from_url( $file['url'] ),
2017-05-30 18:01:48 +00:00
'file' => $file['url'],
2017-05-26 14:57:17 +00:00
);
}
}
2017-05-26 15:54:43 +00:00
2017-05-26 14:57:17 +00:00
if ( ! empty( $meta_data ) ) {
$data['meta_data'] = $meta_data;
}
return $data;
}
/**
* Map and format raw data to known fields.
*
* @return array
*/
protected function set_parsed_data() {
$parse_functions = $this->get_formating_callback();
$mapped_keys = $this->get_mapped_keys();
2017-05-15 22:49:53 +00:00
// Parse the data.
foreach ( $this->raw_data as $row ) {
2017-05-25 13:54:49 +00:00
// Skip empty rows.
if ( ! count( array_filter( $row ) ) ) {
continue;
}
$data = array();
foreach ( $row as $id => $value ) {
// Skip ignored columns.
if ( empty( $mapped_keys[ $id ] ) ) {
continue;
}
$data[ $mapped_keys[ $id ] ] = call_user_func( $parse_functions[ $id ], $value );
2017-05-15 22:49:53 +00:00
}
$this->parsed_data[] = apply_filters( 'woocommerce_product_importer_parsed_data', $this->expand_data( $data ) );
2017-05-15 22:49:53 +00:00
}
}
2017-05-16 04:22:00 +00:00
2017-05-23 14:05:32 +00:00
/**
* 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 ) {
2017-05-26 15:54:43 +00:00
$row_data[] = sprintf( __( 'ID %d', 'woocommerce' ), $id );
2017-05-23 14:05:32 +00:00
}
if ( $sku ) {
2017-05-26 15:54:43 +00:00
$row_data[] = sprintf( __( 'SKU %s', 'woocommerce' ), $sku );
2017-05-23 14:05:32 +00:00
}
return implode( ', ', $row_data );
}
2017-05-16 04:22:00 +00:00
/**
* Process importer.
*
* @return array
*/
public function import() {
2017-06-14 16:04:47 +00:00
$this->start_time = time();
$index = 0;
$data = array(
2017-06-14 13:02:47 +00:00
'imported' => array(),
'failed' => array(),
'updated' => array(),
'skipped' => array(),
2017-05-16 04:22:00 +00:00
);
2017-05-23 14:05:32 +00:00
foreach ( $this->parsed_data as $parsed_data_key => $parsed_data ) {
2017-05-25 13:54:49 +00:00
// Do not import products with IDs or SKUs that already exist if option
// is true UNLESS this is a dummy product created during this import.
2017-05-23 14:05:32 +00:00
if ( ! $this->params['update_existing'] ) {
2017-05-25 13:54:49 +00:00
$id = isset( $parsed_data['id'] ) ? absint( $parsed_data['id'] ) : 0;
$sku = isset( $parsed_data['sku'] ) ? esc_attr( $parsed_data['sku'] ) : '';
2017-05-19 17:58:31 +00:00
2017-05-25 13:54:49 +00:00
if ( $id ) {
$product = wc_get_product( $id );
if ( $product && 'importing' !== $product->get_status() ) {
2017-05-26 14:57:17 +00:00
$data['skipped'][] = new WP_Error( 'woocommerce_product_importer_error', __( 'A product with this ID already exists.', 'woocommerce' ), array( 'id' => $id, 'row' => $this->get_row_id( $parsed_data ) ) );
2017-05-25 13:54:49 +00:00
continue;
}
} elseif ( $sku && ( $id_from_sku = wc_get_product_id_by_sku( $sku ) ) ) {
$product = wc_get_product( $id_from_sku );
if ( $product && 'importing' !== $product->get_status() ) {
2017-05-26 14:57:17 +00:00
$data['skipped'][] = new WP_Error( 'woocommerce_product_importer_error', __( 'A product with this SKU already exists.', 'woocommerce' ), array( 'sku' => $sku, 'row' => $this->get_row_id( $parsed_data ) ) );
2017-05-25 13:54:49 +00:00
continue;
}
2017-05-19 17:58:31 +00:00
}
}
2017-05-16 04:22:00 +00:00
$result = $this->process_item( $parsed_data );
if ( is_wp_error( $result ) ) {
2017-05-23 14:05:32 +00:00
$result->add_data( array( 'row' => $this->get_row_id( $parsed_data ) ) );
2017-05-26 18:26:55 +00:00
$data['failed'][] = $result;
2017-05-25 13:54:49 +00:00
} elseif ( $result['updated'] ) {
2017-05-25 17:16:10 +00:00
$data['updated'][] = $result['id'];
2017-05-16 04:22:00 +00:00
} else {
2017-05-25 17:16:10 +00:00
$data['imported'][] = $result['id'];
2017-05-16 04:22:00 +00:00
}
2017-06-14 13:02:47 +00:00
$index ++;
2017-06-14 18:35:22 +00:00
if ( $this->params['prevent_timeouts'] && ( $this->time_exceeded() || $this->memory_exceeded() ) ) {
2017-06-14 13:02:47 +00:00
$this->file_position = $this->file_positions[ $index ];
break;
}
2017-05-16 04:22:00 +00:00
}
return $data;
}
2017-05-15 22:49:53 +00:00
}