2017-05-16 04:02:46 +00:00
< ? php
/**
* Abstract Product importer
*
* @ package WooCommerce / Import
* @ version 3.1 . 0
*/
2017-12-15 13:19:23 +00:00
2017-05-16 04:02:46 +00:00
if ( ! defined ( 'ABSPATH' ) ) {
exit ;
}
/**
* Include dependencies .
*/
if ( ! class_exists ( 'WC_Importer_Interface' , false ) ) {
2017-12-15 13:19:23 +00:00
include_once WC_ABSPATH . 'includes/interfaces/class-wc-importer-interface.php' ;
2017-05-16 04:02:46 +00:00
}
/**
* WC_Product_Importer Class .
*/
abstract class WC_Product_Importer implements WC_Importer_Interface {
2017-05-16 04:43:45 +00:00
/**
* CSV file .
*
* @ var string
*/
protected $file = '' ;
2017-05-18 16:59:40 +00:00
/**
* The file position after the last read .
*
* @ var int
*/
protected $file_position = 0 ;
2017-05-16 04:43:45 +00:00
/**
* Importer parameters .
*
* @ var array
*/
protected $params = array ();
/**
* Raw keys - CSV raw headers .
*
* @ var array
*/
protected $raw_keys = array ();
/**
* Mapped keys - CSV headers .
*
* @ var array
*/
protected $mapped_keys = array ();
/**
* Raw data .
*
* @ var array
*/
protected $raw_data = array ();
2017-06-14 13:02:47 +00:00
/**
* Raw data .
*
* @ var array
*/
protected $file_positions = array ();
2017-05-16 04:43:45 +00:00
/**
* Parsed data .
*
* @ var array
*/
protected $parsed_data = array ();
2017-06-14 16:04:47 +00:00
/**
* Start time of current import .
*
* ( default value : 0 )
*
* @ var int
*/
protected $start_time = 0 ;
2017-05-16 04:43:45 +00:00
/**
* Get file raw headers .
*
* @ return array
*/
public function get_raw_keys () {
return $this -> raw_keys ;
}
/**
* Get file mapped headers .
*
* @ return array
*/
public function get_mapped_keys () {
2017-05-19 21:46:42 +00:00
return ! empty ( $this -> mapped_keys ) ? $this -> mapped_keys : $this -> raw_keys ;
2017-05-16 04:43:45 +00:00
}
/**
* Get raw data .
*
* @ return array
*/
public function get_raw_data () {
return $this -> raw_data ;
}
/**
* Get parsed data .
*
* @ return array
*/
public function get_parsed_data () {
2017-05-19 21:45:58 +00:00
return apply_filters ( 'woocommerce_product_importer_parsed_data' , $this -> parsed_data , $this -> get_raw_data () );
2017-05-16 04:43:45 +00:00
}
2017-11-20 01:09:49 +00:00
/**
* Get importer parameters .
*
* @ return array
*/
public function get_params () {
return $this -> params ;
}
2017-11-22 19:48:19 +00:00
2017-05-18 16:59:40 +00:00
/**
* Get file pointer position from the last read .
*
* @ return int
*/
public function get_file_position () {
return $this -> file_position ;
}
/**
* Get file pointer position as a percentage of file size .
*
* @ return int
*/
public function get_percent_complete () {
$size = filesize ( $this -> file );
if ( ! $size ) {
return 0 ;
}
2017-05-23 14:05:32 +00:00
return absint ( min ( round ( ( $this -> file_position / $size ) * 100 ), 100 ) );
2017-05-18 16:59:40 +00:00
}
2017-05-16 04:02:46 +00:00
/**
* Prepare a single product for create or update .
*
2017-05-26 21:42:07 +00:00
* @ param array $data Item data .
2017-05-16 04:02:46 +00:00
* @ return WC_Product | WP_Error
*/
2017-05-25 13:54:49 +00:00
protected function get_product_object ( $data ) {
2017-05-19 00:09:25 +00:00
$id = isset ( $data [ 'id' ] ) ? absint ( $data [ 'id' ] ) : 0 ;
2017-05-16 04:02:46 +00:00
// Type is the most important part here because we need to be using the correct class and methods.
if ( isset ( $data [ 'type' ] ) ) {
2017-05-24 10:26:57 +00:00
$types = array_keys ( wc_get_product_types () );
$types [] = 'variation' ;
if ( ! in_array ( $data [ 'type' ], $types , true ) ) {
2017-05-19 21:45:58 +00:00
return new WP_Error ( 'woocommerce_product_importer_invalid_type' , __ ( 'Invalid product type.' , 'woocommerce' ), array ( 'status' => 401 ) );
2017-05-16 04:02:46 +00:00
}
2017-05-19 21:45:58 +00:00
$classname = WC_Product_Factory :: get_classname_from_product_type ( $data [ 'type' ] );
2017-05-16 04:02:46 +00:00
if ( ! class_exists ( $classname ) ) {
$classname = 'WC_Product_Simple' ;
}
$product = new $classname ( $id );
2017-12-15 12:59:54 +00:00
} elseif ( ! empty ( $data [ 'id' ] ) ) {
2017-05-16 04:02:46 +00:00
$product = wc_get_product ( $id );
2017-05-23 14:05:32 +00:00
if ( ! $product ) {
2017-12-15 13:19:23 +00:00
return new WP_Error (
'woocommerce_product_csv_importer_invalid_id' ,
/* translators: %d: product ID */
sprintf ( __ ( 'Invalid product ID %d.' , 'woocommerce' ), $id ),
array (
'id' => $id ,
'status' => 401 ,
)
);
2017-05-23 14:05:32 +00:00
}
2017-05-16 04:02:46 +00:00
} else {
2017-05-25 13:54:49 +00:00
$product = new WC_Product_Simple ( $id );
2017-05-16 04:02:46 +00:00
}
2017-05-25 13:54:49 +00:00
return apply_filters ( 'woocommerce_product_import_get_product_object' , $product , $data );
2017-05-16 04:02:46 +00:00
}
/**
2017-05-26 14:57:17 +00:00
* Process a single item and save .
2017-05-16 04:02:46 +00:00
*
2017-12-15 13:19:23 +00:00
* @ throws Exception If item cannot be processed .
2017-05-26 14:57:17 +00:00
* @ param array $data Raw CSV data .
* @ return array | WC_Error
2017-05-16 04:02:46 +00:00
*/
2017-05-26 14:57:17 +00:00
protected function process_item ( $data ) {
try {
2017-06-20 12:25:23 +00:00
do_action ( 'woocommerce_product_import_before_process_item' , $data );
2017-05-26 22:57:31 +00:00
// Get product ID from SKU if created during the importation.
2017-12-15 13:19:23 +00:00
if ( empty ( $data [ 'id' ] ) && ! empty ( $data [ 'sku' ] ) ) {
$product_id = wc_get_product_id_by_sku ( $data [ 'sku' ] );
if ( $product_id ) {
$data [ 'id' ] = $product_id ;
}
2017-05-26 22:57:31 +00:00
}
2017-05-26 14:57:17 +00:00
$object = $this -> get_product_object ( $data );
$updating = false ;
2017-05-16 04:02:46 +00:00
2017-05-26 14:57:17 +00:00
if ( is_wp_error ( $object ) ) {
return $object ;
}
2017-05-16 04:02:46 +00:00
2017-05-26 14:57:17 +00:00
if ( $object -> get_id () && 'importing' !== $object -> get_status () ) {
$updating = true ;
}
2017-05-16 04:02:46 +00:00
2017-05-26 18:26:55 +00:00
if ( 'external' === $object -> get_type () ) {
2018-05-27 04:40:58 +00:00
unset ( $data [ 'manage_stock' ], $data [ 'stock_status' ], $data [ 'backorders' ], $data [ 'low_stock_amount' ] );
2017-05-26 18:26:55 +00:00
}
2017-06-14 15:37:21 +00:00
if ( 'importing' === $object -> get_status () ) {
$object -> set_status ( 'publish' );
$object -> set_slug ( '' );
}
2017-05-26 21:53:22 +00:00
$result = $object -> set_props ( array_diff_key ( $data , array_flip ( array ( 'meta_data' , 'raw_image_id' , 'raw_gallery_image_ids' , 'raw_attributes' ) ) ) );
2017-05-16 04:02:46 +00:00
2017-05-26 14:57:17 +00:00
if ( is_wp_error ( $result ) ) {
throw new Exception ( $result -> get_error_message () );
}
2017-05-16 04:02:46 +00:00
2017-05-26 14:57:17 +00:00
if ( 'variation' === $object -> get_type () ) {
$this -> set_variation_data ( $object , $data );
} else {
$this -> set_product_data ( $object , $data );
}
2017-05-16 04:02:46 +00:00
2017-05-26 14:57:17 +00:00
$this -> set_image_data ( $object , $data );
$this -> set_meta_data ( $object , $data );
2017-05-16 04:02:46 +00:00
2017-05-26 14:57:17 +00:00
$object = apply_filters ( 'woocommerce_product_import_pre_insert_product_object' , $object , $data );
$object -> save ();
2017-05-16 04:02:46 +00:00
2017-06-09 06:30:22 +00:00
do_action ( 'woocommerce_product_import_inserted_product_object' , $object , $data );
2017-05-26 14:57:17 +00:00
return array (
'id' => $object -> get_id (),
'updated' => $updating ,
);
} catch ( Exception $e ) {
return new WP_Error ( 'woocommerce_product_importer_error' , $e -> getMessage (), array ( 'status' => $e -> getCode () ) );
2017-05-16 04:02:46 +00:00
}
2017-05-26 14:57:17 +00:00
}
2017-05-16 04:02:46 +00:00
2017-05-26 14:57:17 +00:00
/**
* Convert raw image URLs to IDs and set .
*
2017-05-26 21:42:07 +00:00
* @ param WC_Product $product Product instance .
* @ param array $data Item data .
2017-05-26 14:57:17 +00:00
*/
protected function set_image_data ( & $product , $data ) {
// Image URLs need converting to IDs before inserting.
2017-05-26 18:37:12 +00:00
if ( isset ( $data [ 'raw_image_id' ] ) ) {
$product -> set_image_id ( $this -> get_attachment_id_from_url ( $data [ 'raw_image_id' ], $product -> get_id () ) );
2017-05-16 04:02:46 +00:00
}
2017-05-26 14:57:17 +00:00
// Gallery image URLs need converting to IDs before inserting.
2017-05-26 18:37:12 +00:00
if ( isset ( $data [ 'raw_gallery_image_ids' ] ) ) {
2017-05-26 14:57:17 +00:00
$gallery_image_ids = array ();
2017-05-16 04:02:46 +00:00
2017-05-26 18:37:12 +00:00
foreach ( $data [ 'raw_gallery_image_ids' ] as $image_id ) {
2017-05-26 14:57:17 +00:00
$gallery_image_ids [] = $this -> get_attachment_id_from_url ( $image_id , $product -> get_id () );
}
$product -> set_gallery_image_ids ( $gallery_image_ids );
2017-05-16 04:02:46 +00:00
}
2017-05-26 14:57:17 +00:00
}
2017-05-16 04:02:46 +00:00
2017-05-26 14:57:17 +00:00
/**
* Append meta data .
*
2017-05-26 21:42:07 +00:00
* @ param WC_Product $product Product instance .
* @ param array $data Item data .
2017-05-26 14:57:17 +00:00
*/
protected function set_meta_data ( & $product , $data ) {
if ( isset ( $data [ 'meta_data' ] ) ) {
foreach ( $data [ 'meta_data' ] as $meta ) {
$product -> update_meta_data ( $meta [ 'key' ], $meta [ 'value' ] );
}
2017-05-16 04:02:46 +00:00
}
2017-05-26 14:57:17 +00:00
}
2017-05-16 04:02:46 +00:00
2017-05-26 14:57:17 +00:00
/**
* Set product data .
*
* @ param WC_Product $product Product instance .
2017-05-26 21:42:07 +00:00
* @ param array $data Item data .
2017-12-15 13:19:23 +00:00
* @ throws Exception If data cannot be set .
2017-05-26 14:57:17 +00:00
*/
protected function set_product_data ( & $product , $data ) {
if ( isset ( $data [ 'raw_attributes' ] ) ) {
2018-03-15 12:18:31 +00:00
$attributes = array ();
$default_attributes = array ();
$existing_attributes = $product -> get_attributes ();
2017-05-16 04:02:46 +00:00
2017-05-26 14:57:17 +00:00
foreach ( $data [ 'raw_attributes' ] as $position => $attribute ) {
2017-05-30 21:46:32 +00:00
$attribute_id = 0 ;
2017-05-24 07:32:28 +00:00
// Get ID if is a global attribute.
2017-05-30 21:46:32 +00:00
if ( ! empty ( $attribute [ 'taxonomy' ] ) ) {
2017-06-20 13:15:35 +00:00
$attribute_id = $this -> get_attribute_taxonomy_id ( $attribute [ 'name' ] );
2017-05-30 21:46:32 +00:00
}
2017-05-16 04:02:46 +00:00
2017-05-24 11:14:10 +00:00
// Set attribute visibility.
2017-05-24 08:43:15 +00:00
if ( isset ( $attribute [ 'visible' ] ) ) {
2017-05-24 11:14:10 +00:00
$is_visible = $attribute [ 'visible' ];
2017-05-24 08:43:15 +00:00
} else {
2017-05-24 11:14:10 +00:00
$is_visible = 1 ;
2017-05-24 08:43:15 +00:00
}
2018-03-15 12:18:31 +00:00
// Get name.
$attribute_name = $attribute_id ? wc_attribute_taxonomy_name_by_id ( $attribute_id ) : $attribute [ 'name' ];
// Set if is a variation attribute based on existing attributes if possible so updates via CSV do not change this.
2017-05-24 11:14:10 +00:00
$is_variation = 0 ;
2018-03-15 12:18:31 +00:00
if ( $existing_attributes ) {
foreach ( $existing_attributes as $existing_attribute ) {
if ( $existing_attribute -> get_name () === $attribute_name ) {
$is_variation = $existing_attribute -> get_variation ();
break ;
}
}
}
2017-05-24 11:14:10 +00:00
2018-03-15 12:18:31 +00:00
if ( $attribute_id ) {
2017-05-24 07:32:28 +00:00
if ( isset ( $attribute [ 'value' ] ) ) {
2017-05-24 11:14:10 +00:00
$options = array_map ( 'wc_sanitize_term_text_based' , $attribute [ 'value' ] );
$options = array_filter ( $options , 'strlen' );
} else {
$options = array ();
}
2017-05-16 04:02:46 +00:00
2017-05-24 11:14:10 +00:00
// Check for default attributes and set "is_variation".
2017-12-15 13:19:23 +00:00
if ( ! empty ( $attribute [ 'default' ] ) && in_array ( $attribute [ 'default' ], $options , true ) ) {
2017-05-24 11:14:10 +00:00
$default_term = get_term_by ( 'name' , $attribute [ 'default' ], $attribute_name );
if ( $default_term && ! is_wp_error ( $default_term ) ) {
$default = $default_term -> slug ;
} else {
$default = sanitize_title ( $attribute [ 'default' ] );
2017-05-16 04:02:46 +00:00
}
2017-05-24 11:14:10 +00:00
$default_attributes [ $attribute_name ] = $default ;
2017-12-15 13:19:23 +00:00
$is_variation = 1 ;
2017-05-16 04:02:46 +00:00
}
2017-05-24 11:14:10 +00:00
if ( ! empty ( $options ) ) {
2017-05-16 04:02:46 +00:00
$attribute_object = new WC_Product_Attribute ();
$attribute_object -> set_id ( $attribute_id );
2017-05-24 11:14:10 +00:00
$attribute_object -> set_name ( $attribute_name );
$attribute_object -> set_options ( $options );
2017-05-24 07:32:28 +00:00
$attribute_object -> set_position ( $position );
2017-05-24 11:14:10 +00:00
$attribute_object -> set_visible ( $is_visible );
$attribute_object -> set_variation ( $is_variation );
2017-05-16 04:02:46 +00:00
$attributes [] = $attribute_object ;
}
2017-05-24 07:32:28 +00:00
} elseif ( isset ( $attribute [ 'value' ] ) ) {
2017-05-24 11:14:10 +00:00
// Check for default attributes and set "is_variation".
2017-12-15 13:19:23 +00:00
if ( ! empty ( $attribute [ 'default' ] ) && in_array ( $attribute [ 'default' ], $attribute [ 'value' ], true ) ) {
2017-05-24 11:14:10 +00:00
$default_attributes [ sanitize_title ( $attribute [ 'name' ] ) ] = $attribute [ 'default' ];
$is_variation = 1 ;
2017-05-16 04:02:46 +00:00
}
2017-05-24 07:32:28 +00:00
2017-05-16 04:02:46 +00:00
$attribute_object = new WC_Product_Attribute ();
2017-05-24 07:32:28 +00:00
$attribute_object -> set_name ( $attribute [ 'name' ] );
2017-05-24 11:14:10 +00:00
$attribute_object -> set_options ( $attribute [ 'value' ] );
2017-05-24 07:32:28 +00:00
$attribute_object -> set_position ( $position );
2017-05-24 11:14:10 +00:00
$attribute_object -> set_visible ( $is_visible );
$attribute_object -> set_variation ( $is_variation );
2017-05-16 04:02:46 +00:00
$attributes [] = $attribute_object ;
}
}
2017-05-24 07:32:28 +00:00
2017-05-16 04:02:46 +00:00
$product -> set_attributes ( $attributes );
2017-05-24 11:14:10 +00:00
// Set variable default attributes.
if ( $product -> is_type ( 'variable' ) ) {
$product -> set_default_attributes ( $default_attributes );
}
2017-05-16 04:02:46 +00:00
}
}
/**
* Set variation data .
*
* @ param WC_Product $variation Product instance .
2017-05-26 21:42:07 +00:00
* @ param array $data Item data .
2017-05-19 00:09:25 +00:00
* @ return WC_Product | WP_Error
2017-12-15 13:19:23 +00:00
* @ throws Exception If data cannot be set .
2017-05-16 04:02:46 +00:00
*/
2017-05-26 14:57:17 +00:00
protected function set_variation_data ( & $variation , $data ) {
2017-05-24 10:26:57 +00:00
$parent = false ;
2017-05-19 00:09:25 +00:00
// Check if parent exist.
2017-05-24 10:26:57 +00:00
if ( isset ( $data [ 'parent_id' ] ) ) {
$parent = wc_get_product ( $data [ 'parent_id' ] );
if ( $parent ) {
$variation -> set_parent_id ( $parent -> get_id () );
}
}
// Stop if parent does not exists.
if ( ! $parent ) {
2017-05-26 15:56:37 +00:00
return new WP_Error ( 'woocommerce_product_importer_missing_variation_parent_id' , __ ( 'Variation cannot be imported: Missing parent ID or parent does not exist yet.' , 'woocommerce' ), array ( 'status' => 401 ) );
2017-05-16 04:22:00 +00:00
}
2018-11-05 06:34:17 +00:00
// Stop if parent is a product variation.
2018-11-06 06:19:10 +00:00
if ( $parent -> is_type ( 'variation' ) ) {
return new WP_Error ( 'woocommerce_product_importer_parent_set_as_variation' , __ ( 'Variation cannot be imported: Parent product cannot be a product variation' , 'woocommerce' ), array ( 'status' => 401 ) );
2018-11-05 06:34:17 +00:00
}
2017-05-26 14:57:17 +00:00
if ( isset ( $data [ 'raw_attributes' ] ) ) {
2017-05-16 04:22:00 +00:00
$attributes = array ();
2017-05-26 14:57:17 +00:00
$parent_attributes = $this -> get_variation_parent_attributes ( $data [ 'raw_attributes' ], $parent );
2017-05-16 04:22:00 +00:00
2017-05-26 14:57:17 +00:00
foreach ( $data [ 'raw_attributes' ] as $attribute ) {
2017-12-05 18:55:56 +00:00
$attribute_id = 0 ;
2017-05-24 10:26:57 +00:00
// Get ID if is a global attribute.
2017-12-05 18:55:56 +00:00
if ( ! empty ( $attribute [ 'taxonomy' ] ) ) {
$attribute_id = $this -> get_attribute_taxonomy_id ( $attribute [ 'name' ] );
}
2017-05-16 04:22:00 +00:00
2017-05-24 10:26:57 +00:00
if ( $attribute_id ) {
2017-05-16 04:22:00 +00:00
$attribute_name = wc_attribute_taxonomy_name_by_id ( $attribute_id );
2017-05-24 10:26:57 +00:00
} else {
2017-05-25 19:53:32 +00:00
$attribute_name = sanitize_title ( $attribute [ 'name' ] );
2017-05-16 04:22:00 +00:00
}
if ( ! isset ( $parent_attributes [ $attribute_name ] ) || ! $parent_attributes [ $attribute_name ] -> get_variation () ) {
continue ;
}
$attribute_key = sanitize_title ( $parent_attributes [ $attribute_name ] -> get_name () );
2017-05-24 10:26:57 +00:00
$attribute_value = isset ( $attribute [ 'value' ] ) ? current ( $attribute [ 'value' ] ) : '' ;
2017-05-16 04:22:00 +00:00
if ( $parent_attributes [ $attribute_name ] -> is_taxonomy () ) {
// If dealing with a taxonomy, we need to get the slug from the name posted to the API.
$term = get_term_by ( 'name' , $attribute_value , $attribute_name );
if ( $term && ! is_wp_error ( $term ) ) {
$attribute_value = $term -> slug ;
} else {
$attribute_value = sanitize_title ( $attribute_value );
}
}
$attributes [ $attribute_key ] = $attribute_value ;
}
$variation -> set_attributes ( $attributes );
}
2017-05-16 04:02:46 +00:00
}
2017-05-24 10:26:57 +00:00
/**
* Get variation parent attributes and set " is_variation " .
*
* @ param array $attributes Attributes list .
* @ param WC_Product $parent Parent product data .
* @ return array
*/
protected function get_variation_parent_attributes ( $attributes , $parent ) {
$parent_attributes = $parent -> get_attributes ();
$require_save = false ;
foreach ( $attributes as $attribute ) {
2017-05-30 21:46:32 +00:00
$attribute_id = 0 ;
2017-05-24 10:26:57 +00:00
// Get ID if is a global attribute.
2017-05-30 21:46:32 +00:00
if ( ! empty ( $attribute [ 'taxonomy' ] ) ) {
2017-06-20 13:15:35 +00:00
$attribute_id = $this -> get_attribute_taxonomy_id ( $attribute [ 'name' ] );
2017-05-30 21:46:32 +00:00
}
2017-05-24 10:26:57 +00:00
if ( $attribute_id ) {
$attribute_name = wc_attribute_taxonomy_name_by_id ( $attribute_id );
} else {
2017-05-25 19:53:32 +00:00
$attribute_name = sanitize_title ( $attribute [ 'name' ] );
2017-05-24 10:26:57 +00:00
}
// Check if attribute handle variations.
if ( isset ( $parent_attributes [ $attribute_name ] ) && ! $parent_attributes [ $attribute_name ] -> get_variation () ) {
2017-07-17 10:10:52 +00:00
// Re-create the attribute to CRUD save and generate again.
2017-05-24 10:26:57 +00:00
$parent_attributes [ $attribute_name ] = clone $parent_attributes [ $attribute_name ];
$parent_attributes [ $attribute_name ] -> set_variation ( 1 );
$require_save = true ;
}
}
// Save variation attributes.
if ( $require_save ) {
$parent -> set_attributes ( array_values ( $parent_attributes ) );
$parent -> save ();
}
return $parent_attributes ;
}
2017-05-16 04:02:46 +00:00
/**
2017-05-24 06:14:54 +00:00
* Get attachment ID .
2017-05-19 00:09:25 +00:00
*
2017-05-24 06:14:54 +00:00
* @ param string $url Attachment URL .
* @ param int $product_id Product ID .
* @ return int
2017-12-15 13:19:23 +00:00
* @ throws Exception If attachment cannot be loaded .
2017-05-16 04:02:46 +00:00
*/
2017-11-27 15:22:19 +00:00
public function get_attachment_id_from_url ( $url , $product_id ) {
2017-05-24 06:14:54 +00:00
if ( empty ( $url ) ) {
return 0 ;
}
2017-05-16 04:02:46 +00:00
2017-05-24 06:14:54 +00:00
$id = 0 ;
2017-10-12 15:32:40 +00:00
$upload_dir = wp_upload_dir ( null , false );
2017-05-24 06:14:54 +00:00
$base_url = $upload_dir [ 'baseurl' ] . '/' ;
2017-10-12 15:32:40 +00:00
// Check first if attachment is inside the WordPress uploads directory, or we're given a filename only.
if ( false !== strpos ( $url , $base_url ) || false === strpos ( $url , '://' ) ) {
// Search for yyyy/mm/slug.extension or slug.extension - remove the base URL.
$file = str_replace ( $base_url , '' , $url );
2017-05-24 06:14:54 +00:00
$args = array (
'post_type' => 'attachment' ,
'post_status' => 'any' ,
'fields' => 'ids' ,
2017-12-15 13:19:23 +00:00
'meta_query' => array ( // @codingStandardsIgnoreLine.
2017-10-12 15:32:40 +00:00
'relation' => 'OR' ,
array (
'key' => '_wp_attached_file' ,
'value' => '^' . $file ,
'compare' => 'REGEXP' ,
),
2017-05-24 06:14:54 +00:00
array (
2017-08-08 14:00:03 +00:00
'key' => '_wp_attached_file' ,
2017-10-12 15:32:40 +00:00
'value' => '/' . $file ,
'compare' => 'LIKE' ,
),
array (
'key' => '_wc_attachment_source' ,
'value' => '/' . $file ,
'compare' => 'LIKE' ,
2017-05-24 06:14:54 +00:00
),
2017-05-24 06:26:17 +00:00
),
2017-05-24 06:14:54 +00:00
);
} else {
2017-10-12 15:32:40 +00:00
// This is an external URL, so compare to source.
2017-05-24 06:14:54 +00:00
$args = array (
'post_type' => 'attachment' ,
'post_status' => 'any' ,
'fields' => 'ids' ,
2017-12-15 13:19:23 +00:00
'meta_query' => array ( // @codingStandardsIgnoreLine.
2017-05-24 06:14:54 +00:00
array (
2017-05-24 06:26:17 +00:00
'value' => $url ,
'key' => '_wc_attachment_source' ,
2017-05-24 06:14:54 +00:00
),
2017-05-24 06:26:17 +00:00
),
2017-05-24 06:14:54 +00:00
);
2017-09-25 11:58:25 +00:00
}
2017-12-15 13:19:23 +00:00
$ids = get_posts ( $args ); // @codingStandardsIgnoreLine.
if ( $ids ) {
2017-09-25 11:58:25 +00:00
$id = current ( $ids );
2017-05-24 06:14:54 +00:00
}
2017-05-16 04:02:46 +00:00
2017-05-24 06:14:54 +00:00
// Upload if attachment does not exists.
2017-08-08 14:00:03 +00:00
if ( ! $id && stristr ( $url , '://' ) ) {
2017-05-24 06:14:54 +00:00
$upload = wc_rest_upload_image_from_url ( $url );
2017-05-16 04:02:46 +00:00
2017-05-24 06:14:54 +00:00
if ( is_wp_error ( $upload ) ) {
throw new Exception ( $upload -> get_error_message (), 400 );
}
2017-05-16 04:02:46 +00:00
2017-05-24 06:14:54 +00:00
$id = wc_rest_set_uploaded_image_as_attachment ( $upload , $product_id );
2017-05-16 04:02:46 +00:00
2017-05-24 06:14:54 +00:00
if ( ! wp_attachment_is_image ( $id ) ) {
2017-12-15 13:19:23 +00:00
/* translators: %s: image URL */
2017-05-24 06:14:54 +00:00
throw new Exception ( sprintf ( __ ( 'Not able to attach "%s".' , 'woocommerce' ), $url ), 400 );
2017-05-16 04:02:46 +00:00
}
2017-05-24 06:14:54 +00:00
// Save attachment source for future reference.
update_post_meta ( $id , '_wc_attachment_source' , $url );
2017-05-16 04:02:46 +00:00
}
2017-08-08 14:00:03 +00:00
if ( ! $id ) {
2017-12-15 13:19:23 +00:00
/* translators: %s: image URL */
2017-08-08 14:00:03 +00:00
throw new Exception ( sprintf ( __ ( 'Unable to use image "%s".' , 'woocommerce' ), $url ), 400 );
}
2017-05-24 06:14:54 +00:00
return $id ;
2017-05-16 04:02:46 +00:00
}
2017-05-30 21:46:32 +00:00
/**
2017-06-20 13:15:35 +00:00
* Get attribute taxonomy ID from the imported data .
2017-05-30 21:46:32 +00:00
* If does not exists register a new attribute .
*
2017-12-05 18:55:56 +00:00
* @ param string $raw_name Attribute name .
2017-05-30 21:46:32 +00:00
* @ return int
2017-12-15 13:19:23 +00:00
* @ throws Exception If taxonomy cannot be loaded .
2017-05-30 21:46:32 +00:00
*/
2017-11-27 15:22:19 +00:00
public function get_attribute_taxonomy_id ( $raw_name ) {
2017-06-20 13:15:35 +00:00
global $wpdb , $wc_product_attributes ;
2017-05-30 21:46:32 +00:00
2017-06-20 13:15:35 +00:00
// These are exported as labels, so convert the label to a name if possible first.
$attribute_labels = wp_list_pluck ( wc_get_attribute_taxonomies (), 'attribute_label' , 'attribute_name' );
2017-12-15 13:19:23 +00:00
$attribute_name = array_search ( $raw_name , $attribute_labels , true );
2017-06-20 13:15:35 +00:00
2017-12-15 13:19:23 +00:00
if ( ! $attribute_name ) {
2017-06-20 13:15:35 +00:00
$attribute_name = wc_sanitize_taxonomy_name ( $raw_name );
}
2017-12-15 13:19:23 +00:00
$attribute_id = wc_attribute_taxonomy_id_by_name ( $attribute_name );
2017-06-20 13:15:35 +00:00
// Get the ID from the name.
2017-12-15 13:19:23 +00:00
if ( $attribute_id ) {
2017-05-30 21:46:32 +00:00
return $attribute_id ;
}
2017-06-20 13:15:35 +00:00
// If the attribute does not exist, create it.
2017-08-08 01:14:10 +00:00
$attribute_id = wc_create_attribute ( array (
'name' => $raw_name ,
'slug' => $attribute_name ,
'type' => 'select' ,
'order_by' => 'menu_order' ,
'has_archives' => false ,
) );
if ( is_wp_error ( $attribute_id ) ) {
throw new Exception ( $attribute_id -> get_error_message (), 400 );
2017-05-30 21:46:32 +00:00
}
// Register as taxonomy while importing.
2017-08-08 01:14:10 +00:00
$taxonomy_name = wc_attribute_taxonomy_name ( $attribute_name );
register_taxonomy (
$taxonomy_name ,
apply_filters ( 'woocommerce_taxonomy_objects_' . $taxonomy_name , array ( 'product' ) ),
apply_filters ( 'woocommerce_taxonomy_args_' . $taxonomy_name , array (
'labels' => array (
'name' => $raw_name ,
),
'hierarchical' => true ,
'show_ui' => false ,
'query_var' => true ,
'rewrite' => false ,
) )
);
2017-05-30 21:46:32 +00:00
// Set product attributes global.
$wc_product_attributes = array ();
2017-06-20 13:15:35 +00:00
2017-08-08 01:14:10 +00:00
foreach ( wc_get_attribute_taxonomies () as $taxonomy ) {
2017-08-18 16:17:04 +00:00
$wc_product_attributes [ wc_attribute_taxonomy_name ( $taxonomy -> attribute_name ) ] = $taxonomy ;
2017-05-30 21:46:32 +00:00
}
2017-06-27 13:39:30 +00:00
return $attribute_id ;
2017-05-30 21:46:32 +00:00
}
2017-06-14 13:02:47 +00:00
/**
* Memory exceeded
*
* Ensures the batch process never exceeds 90 %
* of the maximum WordPress memory .
*
* @ return bool
*/
protected function memory_exceeded () {
$memory_limit = $this -> get_memory_limit () * 0.9 ; // 90% of max memory
$current_memory = memory_get_usage ( true );
$return = false ;
if ( $current_memory >= $memory_limit ) {
$return = true ;
}
return apply_filters ( 'woocommerce_product_importer_memory_exceeded' , $return );
}
/**
* Get memory limit
*
* @ return int
*/
protected function get_memory_limit () {
if ( function_exists ( 'ini_get' ) ) {
$memory_limit = ini_get ( 'memory_limit' );
} else {
// Sensible default.
$memory_limit = '128M' ;
}
2017-06-14 17:16:39 +00:00
if ( ! $memory_limit || - 1 === intval ( $memory_limit ) ) {
2017-06-14 13:02:47 +00:00
// Unlimited, set to 32GB.
$memory_limit = '32000M' ;
}
return intval ( $memory_limit ) * 1024 * 1024 ;
}
2017-06-14 17:16:39 +00:00
2017-06-14 13:02:47 +00:00
/**
* Time exceeded .
*
* Ensures the batch never exceeds a sensible time limit .
* A timeout limit of 30 s is common on shared hosting .
*
* @ return bool
*/
protected function time_exceeded () {
$finish = $this -> start_time + apply_filters ( 'woocommerce_product_importer_default_time_limit' , 20 ); // 20 seconds
$return = false ;
if ( time () >= $finish ) {
$return = true ;
}
return apply_filters ( 'woocommerce_product_importer_time_exceeded' , $return );
}
2017-07-03 13:47:48 +00:00
/**
* Explode CSV cell values using commas by default , and handling escaped
* separators .
*
* @ since 3.2 . 0
2017-12-15 13:19:23 +00:00
* @ param string $value Value to explode .
2017-07-03 13:47:48 +00:00
* @ return array
*/
protected function explode_values ( $value ) {
$value = str_replace ( '\\,' , '::separator::' , $value );
$values = explode ( ',' , $value );
$values = array_map ( array ( $this , 'explode_values_formatter' ), $values );
return $values ;
}
/**
* Remove formatting and trim each value .
*
* @ since 3.2 . 0
2017-12-15 13:19:23 +00:00
* @ param string $value Value to format .
2017-07-03 13:47:48 +00:00
* @ return string
*/
protected function explode_values_formatter ( $value ) {
return trim ( str_replace ( '::separator::' , ',' , $value ) );
}
2017-11-22 19:48:19 +00:00
/**
* The exporter prepends a ' to fields that start with a - which causes
* issues with negative numbers . This removes the ' if the input is still a valid
* number after removal .
*
* @ since 3.3 . 0
* @ param string $value A numeric string that may or may not have ' prepended .
* @ return string
*/
protected function unescape_negative_number ( $value ) {
2017-11-27 17:48:28 +00:00
if ( 0 === strpos ( $value , " '- " ) ) {
2018-05-11 11:16:02 +00:00
$unescaped = trim ( $value , " ' " );
2017-11-27 17:48:28 +00:00
if ( is_numeric ( $unescaped ) ) {
return $unescaped ;
}
2017-11-22 19:48:19 +00:00
}
return $value ;
}
2017-05-16 04:02:46 +00:00
}