File "import.php"
Full Path: /home/vantageo/public_html/cache/cache/cache/cache/.wp-cli/wp-content/plugins/product-import-export-for-woo/admin/modules/product/import/import.php
File size: 87.21 KB
MIME-type: text/x-php
Charset: utf-8
<?php
if (!defined('WPINC')) {
exit;
}
if(!class_exists('Wt_Import_Export_For_Woo_Basic_Product_Import')){
class Wt_Import_Export_For_Woo_Basic_Product_Import {
public $post_type = 'product';
public $parent_module = null;
public $parsed_data = array();
public $import_columns = array();
public $merge;
public $skip_new;
public $merge_empty_cells;
public $delete_products;
public $use_sku_upsell_crosssell;
public $prod_use_chidren_sku;
public $pro_stop_thumbnail_regen;
public $merge_with = 'id';
public $found_action = 'skip';
public $id_conflict = 'skip';
public $delete_existing = "";
public $product_id = "";
var $processed_posts = array();
var $post_orphans = array();
var $attachments = array();
var $upsell_skus = array();
var $crosssell_skus = array();
// Results
var $import_results = array();
public $item_data = array();
public $is_product_exist = false;
public function __construct($parent_object) {
$this->parent_module = $parent_object;
}
/* WC object based import */
public function prepare_data_to_import($import_data,$form_data,$batch_offset,$is_last_batch){
$this->merge_with = !empty($form_data['advanced_form_data']['wt_iew_merge_with']) ? $form_data['advanced_form_data']['wt_iew_merge_with'] : 'id';
$this->found_action = !empty($form_data['advanced_form_data']['wt_iew_found_action']) ? $form_data['advanced_form_data']['wt_iew_found_action'] : 'skip';
$this->id_conflict = !empty($form_data['advanced_form_data']['wt_iew_id_conflict']) ? $form_data['advanced_form_data']['wt_iew_id_conflict'] : 'skip';
$this->merge_empty_cells = !empty($form_data['advanced_form_data']['wt_iew_merge_empty_cells']) ? 1 : 0;
$this->skip_new = !empty($form_data['advanced_form_data']['wt_iew_skip_new']) ? 1 : 0;
$this->use_sku_upsell_crosssell = !empty($form_data['advanced_form_data']['wt_iew_use_sku_upsell_crosssell']) ? 1 : 0;
$this->prod_use_chidren_sku = !empty($form_data['advanced_form_data']['wt_iew_prod_use_chidren_sku']) ? 1 : 0;
$this->pro_stop_thumbnail_regen = !empty($form_data['advanced_form_data']['wt_iew_pro_stop_thumbnail_regen']) ? 1 : 0;
$this->delete_existing = !empty($form_data['advanced_form_data']['wt_iew_delete_existing']) ? 1 : 0;
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', "Preparing for import.");
$success = 0;
$failed = 0;
foreach ($import_data as $key => $data) {
$row = $batch_offset+$key+1;
$this->is_product_exist = false;
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', "Row :$row - Parsing item.");
$parsed_data = $this->parse_data($data);
if (!is_wp_error($parsed_data)){
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', "Row :$row - Processing item.");
$result = $this->process_item($parsed_data);
if(!is_wp_error($result)){
if($this->is_product_exist){
$msg = 'Product updated successfully.';
} else {
$msg = 'Product imported successfully.';
}
$this->import_results[$row] = array('row'=>$row, 'message'=>$msg, 'status'=>true, 'status_msg' => __( 'Success' ), 'post_id'=>$result['id'], 'post_link' => Wt_Import_Export_For_Woo_Basic_Product::get_item_link_by_id($result['id']));
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', "Row :$row - ".$msg);
$success++;
}else{
$this->import_results[$row] = array('row'=>$row, 'message'=>$result->get_error_message(), 'status'=>false, 'status_msg' => __( 'Failed/Skipped' ), 'post_id'=>'', 'post_link' => array( 'title' => __( 'Untitled' ), 'edit_url' => false ) );
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', "Row :$row - Processing failed. Reason: ".$result->get_error_message());
$failed++;
}
}else{
$this->import_results[$row] = array('row'=>$row, 'message'=>$parsed_data->get_error_message(), 'status'=>false, 'status_msg' => __( 'Failed/Skipped' ), 'post_id'=>'', 'post_link' => array( 'title' => __( 'Untitled' ), 'edit_url' => false ) );
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', "Row :$row - Parsing failed. Reason: ".$parsed_data->get_error_message());
$failed++;
}
}
if($is_last_batch && $this->delete_existing){
$this->delete_existing();
}
$this->clean_after_import();
$import_response=array(
'total_success'=>$success,
'total_failed'=>$failed,
'log_data'=>$this->import_results,
);
return $import_response;
}
public function clean_after_import() {
global $wpdb;
$posts = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_status = '%s' AND post_type IN ( 'product', 'product_variation')", 'importing'));
if($posts){
array_map('wp_delete_post',$posts);
}
}
public function delete_existing() {
$posts = new WP_Query([
'post_type' => array( 'product', 'product_variation'),
'fields' => 'ids',
'posts_per_page' => -1,
'post_status' => array( 'publish', 'private', 'draft', 'pending', 'future'),
'meta_query' => [
[
'key' => '_wt_delete_existing',
'compare' => 'NOT EXISTS',
]
]
]);
foreach ($posts->posts as $post) {
$this->import_results['detele_results'][$post] = wp_trash_post($post);
}
$posts = new WP_Query([
'post_type' => array( 'product', 'product_variation'),
'fields' => 'ids',
'posts_per_page' => -1,
'post_status' => array( 'publish', 'private', 'draft', 'pending', 'future'),
'meta_query' => [
[
'key' => '_wt_delete_existing',
'compare' => 'EXISTS',
]
]
]);
foreach ($posts->posts as $post) {
delete_post_meta($post,'_wt_delete_existing');
}
}
/**
* Parse the data.
*
*
* @param array $data value.
*
* @return array
*/
public function parse_data($data) {
try {
$mapped_data = $data['mapping_fields'];
foreach ($data['meta_mapping_fields'] as $value) {
$mapped_data = array_merge($mapped_data, $value);
}
$mapped_data = apply_filters('wt_woocommerce_product_importer_pre_parse_data', $mapped_data);
$this->item_data = array(); // resetting WC default data before parsing new item to avoid merging last parsed item wp_parse_args
$this->product_id = '';
if((isset($mapped_data['ID']) && !empty($mapped_data['ID']))||(isset($mapped_data['_sku']) && !empty($mapped_data['_sku'])) || (isset($mapped_data['sku']) && !empty($mapped_data['sku']))){
$this->item_data['id'] = $this->wt_product_existance_check($mapped_data); // to determine wether merge or import
}
if(!$this->merge){
$default_data = $this->get_default_data();
$this->item_data = wp_parse_args( $this->item_data, $default_data );
// $this->item_data = $default_data;
}
if($this->merge && !$this->merge_empty_cells){
$this->item_data = array();
$this->item_data['id'] = $this->product_id; // re assinging id after reset default product datas for merge, $this->product_id set from wt_product_existance_check
}
// Relative stock updates
if ($this->merge && $this->product_id) {
if (isset($mapped_data['stock'])) {
$mapped_data['stock'] = trim($mapped_data['stock']);
$mode = substr($mapped_data['stock'], 0, 3);
if ($mode == '(+)') {
$old_stock = intval(get_post_meta($this->product_id, '_stock', true));
$amount = intval(substr($mapped_data['stock'], 3));
$new_stock = $old_stock + $amount;
$mapped_data['stock'] = $new_stock;
}
if ($mode == '(-)') {
$old_stock = intval(get_post_meta($this->product_id, '_stock', true));
$amount = intval(substr($mapped_data['stock'], 3));
$new_stock = $old_stock - $amount;
$mapped_data['stock'] = $new_stock;
}
}
}
if (!isset($data['meta_mapping_fields']['taxonomies']['tax:product_type'])) {
$product_id = $this->item_data['id'];
$product = wc_get_product($product_id);
if($product){
$types = array('simple', 'grouped', 'external');
$product_type = $product->get_type();
if(in_array($product_type, $types)){
$this->item_data['type'] = $product_type;
}else{
return new WP_Error('woocommerce_product_importer_invalid_type', __('This product type is not supported.', 'woocommerce'), array('status' => 401));
}
}else{
$this->item_data['type'] = 'simple';
}
}
foreach ($mapped_data as $column => $value) {
if ($this->merge && !$this->merge_empty_cells && $value == '' && !strstr($column, 'attribute')) {
continue;
}
if (!strstr($column, 'attribute:') && !strstr($column, 'tax:')) { // to escape case change of attribute name
$column = strtolower($column);
}
if ('parent_id' == $column || 'post_parent' == $column || 'parent_sku' == $column) {
$this->item_data['parent_id'] = $this->wt_parse_parent_field($value,$column);
continue;
}
if ('type' == $column || 'tax:product_type' == $column) {
$this->item_data['type'] = $this->wt_parse_type_field($value);
continue;
}
if ('sku' == $column || '_sku' == $column) {
$this->item_data['sku'] = $value;
continue;
}
if ('name' == $column || 'post_title' == $column) {
$this->item_data['name'] = $value;
continue;
}
if ('slug' == $column || 'post_name' == $column) {
$this->item_data['slug'] = $value;
continue;
}
if ('date_created' == $column || 'post_date' == $column) {
$this->item_data['date_created'] = $value;
$this->item_data['date_modified'] = $value;
continue;
}
if ('post_author' == $column ) {
if(get_userdata( $value) ) {
$this->item_data['post_author'] = $value;
}
}
if ('status' == $column || 'post_status' == $column) {
$this->item_data['status'] = $this->wt_parse_published_field($value);
continue;
}
if ('catalog_visibility' == $column || '_visibility' == $column || 'tax:product_visibility' == $column) {
$this->item_data['catalog_visibility'] = $this->wt_parse_catalog_visibility_field($value);
continue;
}
if ('description' == $column || 'post_content' == $column) {
$enable_chatgpt = Wt_Import_Export_For_Woo_Basic_Common_Helper::get_advanced_settings('enable_chatgpt');
if( 1 == $enable_chatgpt ){
$gpt_key = Wt_Import_Export_For_Woo_Basic_Common_Helper::get_advanced_settings('chatgpt_api_key');
if('' !== $gpt_key && empty( $value ) && !$this->merge ){ // ChatGPT key is entered, product description column is empty and it's not an update.
$start_description = isset( $mapped_data['post_title'] ) ? $mapped_data['post_title'] : $value;
$this->item_data['description'] = $this->generate_product_description_using_openai($start_description, $gpt_key);
continue;
}
}
$this->item_data['description'] = $this->wt_parse_description_field($value);
continue;
}
if ('short_description' == $column || 'post_excerpt' == $column) {
$this->item_data['short_description'] = $this->wt_parse_description_field($value);
continue;
}
if ('price' == $column || '_price' == $column) {
$this->item_data['price'] = wc_format_decimal($value);
continue;
}
if ('regular_price' == $column || '_regular_price' == $column) {
$this->item_data['regular_price'] = wc_format_decimal($value);
continue;
}
if ('sale_price' == $column || '_sale_price' == $column) {
$this->item_data['sale_price'] = wc_format_decimal($value);
continue;
}
if ('date_on_sale_from' == $column || '_sale_price_dates_from' == $column || 'sale_price_dates_from' == $column) {
$this->item_data['date_on_sale_from'] = $value;
continue;
}
if ('date_on_sale_to' == $column || '_sale_price_dates_to' == $column || 'sale_price_dates_to' == $column) {
$this->item_data['date_on_sale_to'] = $value;
continue;
}
if ('total_sales' == $column || '_total_sales' == $column) {
$this->item_data['total_sales'] = $this->wt_parse_int_field($value);
continue;
}
if ('tax_status' == $column || '_tax_status' == $column) {
$this->item_data['tax_status'] = $this->wt_parse_tax_status_field($value);
continue;
}
if ('tax_class' == $column || '_tax_class' == $column) {
$this->item_data['tax_class'] = ($value);
continue;
}
if ('stock_quantity' == $column || '_stock' == $column || 'stock' == $column) {
$this->item_data['stock_quantity'] = $this->wt_parse_stock_quantity_field($value);
continue;
}
if ('manage_stock' == $column || '_manage_stock' == $column) {
$this->item_data['manage_stock'] = $this->wt_parse_string_to_bool_field($value);
continue;
}
if ('stock_status' == $column || '_stock_status' == $column) {
$this->item_data['stock_status'] = $this->wt_parse_stock_status_field($value);
continue;
}
if ('backorders' == $column || '_backorders' == $column) {
$this->item_data['backorders'] = $this->wt_parse_backorders_field($value);
continue;
}
if ('low_stock_amount' == $column || '_low_stock_amount' == $column) {
$this->item_data['low_stock_amount'] = $this->wt_parse_int_field($value);
continue;
}
if ('sold_individually' == $column || '_sold_individually' == $column) {
$this->item_data['sold_individually'] = $this->wt_parse_string_to_bool_field($value);
continue;
}
if ('product_url' == $column || '_product_url' == $column) {
$this->item_data['product_url'] = $value;
continue;
}
if ('button_text' == $column || '_button_text' == $column) {
$this->item_data['button_text'] = $value;
continue;
}
if ('weight' == $column || '_weight' == $column) {
$this->item_data['weight'] = ($value);
continue;
}
if ('length' == $column || '_length' == $column) {
$this->item_data['length'] = ($value);
continue;
}
if ('width' == $column || '_width' == $column) {
$this->item_data['width'] = ($value);
continue;
}
if ('height' == $column || '_height' == $column) {
$this->item_data['height'] = ($value);
continue;
}
if ('upsell_ids' == $column || '_upsell_ids' == $column || '_upsell_skus' == $column) {
$this->item_data['upsell_ids'] = $this->wt_parse_product_ids_field($value);
continue;
}
if ('crosssell_ids' == $column || '_crosssell_ids' == $column || '_crosssell_skus' == $column) {
$this->item_data['cross_sell_ids'] = $this->wt_parse_product_ids_field($value);
continue;
}
if ('reviews_allowed' == $column || 'comment_status' == $column) {
$this->item_data['reviews_allowed'] = $this->wt_parse_string_to_bool_field($value);
continue;
}
if ('purchase_note' == $column || '_purchase_note' == $column) {
$this->item_data['purchase_note'] = ($value);
continue;
}
if ('menu_order' == $column || 'position' == $column) {
$this->item_data['menu_order'] = $this->wt_parse_int_field($value);
continue;
}
if ('post_password' == $column) {
$this->item_data['post_password'] = ($value);
continue;
}
if ('virtual' == $column || '_virtual' == $column) {
$this->item_data['virtual'] = $this->wt_parse_string_to_bool_field($value);
continue;
}
if ('downloadable' == $column || '_downloadable' == $column) {
$this->item_data['downloadable'] = $this->wt_parse_string_to_bool_field($value);
continue;
}
if ('category_ids' == $column || 'tax:product_cat' == $column) {
$this->item_data['category_ids'] = $this->wt_parse_categories_field($value);
continue;
}
if ('tag_ids' == $column || 'tax:product_tag' == $column) {
$this->item_data['tag_ids'] = $this->wt_parse_tags_field($value);
continue;
}
if ('shipping_class_id' == $column || 'tax:product_shipping_class' == $column) {
$this->item_data['shipping_class_id'] = $this->wt_parse_shipping_class_field($value);
continue;
}
if ('downloads' == $column || '_downloadable_files' == $column || 'downloadable_files' == $column) {
$this->item_data['downloads'] = $this->wt_parse_downloads_field($value);
continue;
}
if ('download_limit' == $column || '_download_limit' == $column) {
$value = trim($value,'\'');
$this->item_data['download_limit'] = $this->wt_parse_int_field($value);
continue;
}
if ('download_expiry' == $column || '_download_expiry' == $column) {
$value = trim($value,'\'');
$this->item_data['download_expiry'] = $this->wt_parse_int_field($value);
continue;
}
if ('rating_counts' == $column) {
$this->item_data['rating_counts'] = ($value);
continue;
}
if ('average_rating' == $column) {
$this->item_data['average_rating'] = $this->wt_parse_int_field($value);
continue;
}
if ('review_count' == $column) {
$this->item_data['review_count'] = $this->wt_parse_int_field($value);
continue;
}
if ('Grouped products' == $column || 'children' == $column || '_children' == $column) {
$this->item_data['children'] = $this->wt_parse_product_ids_field($value);
continue;
}
if ('images' == $column) {
$images = $this->wt_parse_images_field($value);
$this->item_data['raw_image'] = array_shift($images);
if (!empty($images)) {
$this->item_data['raw_gallery_image'] = $images;
}
unset($images);
continue;
}
if (strstr($column, 'attribute:')) {
$this->wt_parse_attribute_field($value, $column);
continue;
}
if (strstr($column, 'attribute_data:')) {
$this->wt_parse_attribute_data_field($value, $column);
continue;
}
if (strstr($column, 'attribute_default:')) {
$this->wt_parse_attribute_default_field($value, $column);
continue;
}
if (strstr($column, 'meta:')) {
$this->wt_parse_meta_field($value, $column);
continue;
}
if (strstr($column, 'tax:')) {
$this->wt_parse_other_taxomomy_field($value, $column);
continue;
}
/**
* WPML
*/
if ($column == 'wpml:original_product_id' || $column == 'wpml:original_product_sku' || $column == 'wpml:language_code') {
$column = trim(str_replace('wpml:', '', $column));
$this->item_data['wpml'][] = array('key' => esc_attr($column), 'value' => $value);
}
}
if(empty($this->item_data['id'])){
$this->item_data['id'] = $this->wt_parse_id_field($mapped_data);
}
return $this->item_data;
} catch (Exception $e) {
return new WP_Error('woocommerce_product_importer_error', $e->getMessage(), array('status' => $e->getCode()));
}
}
/**
* Explode CSV cell values using commas by default, and handling escaped
* separators.
*
* @since 3.2.0
* @param string $value Value to explode.
* @param string $separator Separator separating each value. Defaults to comma.
* @return array
*/
protected function wt_explode_values( $value, $separator = ',' ) {
$value = str_replace( '\\,', '::separator::', $value );
$values = explode( $separator, $value );
$values = array_map( array( $this, 'wt_explode_values_formatter' ), $values );
return $values;
}
/**
* Remove formatting and trim each value.
*
* @since 3.2.0
* @param string $value Value to format.
* @return string
*/
protected function wt_explode_values_formatter( $value ) {
return trim( str_replace( '::separator::', ',', $value ) );
}
public function wt_parse_product_ids_field($value){
if('' == $value){
return array();
}
if($this->use_sku_upsell_crosssell){
$value = array_map('wc_get_product_id_by_sku',$this->wt_parse_seperation_field($value,'|'));
}else{
$value = $this->wt_parse_seperation_field($value,'|');
}
return $value;
}
public function wt_parse_catalog_visibility_field( $value ) {
$visibility = $value;
if (strstr($value, '|')) {
$visibilities = $this->wt_parse_seperation_field($value,'|');
if(in_array('featured', $visibilities)){
$this->item_data['featured'] = true;
}
if(in_array('exclude-from-search', $visibilities)){ // Search result only
$visibility = 'catalog';
}
if(in_array('exclude-from-catalog', $visibilities)){ // Shop only
$visibility ='search';
}
if(in_array('exclude-from-catalog', $visibilities) && in_array('exclude-from-search', $visibilities)){ // Hidden
$visibility ='hidden';
}
}else{
$visibility = $value = strtolower($value);
if('featured' == $value){
$this->item_data['featured'] = true;
}
if('exclude-from-search' == $value){ // Search result only
$visibility = 'catalog';
}
if('exclude-from-catalog' == $value){ // Shop only
$visibility ='search';
}
}
$options = array_keys( wc_get_product_visibility_options() );
if ( ! in_array( $visibility, $options ) ) {
// $this->error( 'product_invalid_catalog_visibility', __( 'Invalid catalog visibility option.', 'woocommerce' ) );
$visibility = 'visible';
}
return $visibility;
}
/**
* Parse backorders from a CSV.
*
* @param string $value Field value.
*
* @return string
*/
public function wt_parse_backorders_field( $value ) {
$value = strtolower($value);
if ( empty( $value ) ) {
return 'no';
}
return $value;
}
public function wt_parse_stock_quantity_field($value) {
if ('' === $value) {
return $value;
}
return wc_stock_amount($value);
}
public function wt_parse_stock_status_field($value) {
return $value;
}
public function wt_parse_string_to_bool_field($value) {
$value = strtolower(trim($value));
if ( isset( $value ) ) {
if ( 'open' == $value ) { // comment_status
return true;
}
if ( '' === $value ) {
return false;
} else {
return wc_string_to_bool($value);
}
}
return false;
}
public function wt_parse_parent_field($value,$column){
if(!empty($this->item_data['parent_id'])){
return $this->item_data['parent_id'];
}
global $wpdb;
if ( '' == $value ) {
return '';
}
$parent_id = '';
// ID
if ( 'parent_sku' != $column ) {
$id = intval( $value );
// See if the given ID maps to a valid product allready.
$existing_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type IN ( 'product' ) AND ID = %d;", $id ) ); // WPCS: db call ok, cache ok.
if ( $existing_id ) {
$parent_id = absint( $existing_id );
}
}else{
// $id = wc_get_product_id_by_sku( $value );
$value = trim($value);
$db_query = $wpdb->prepare("SELECT $wpdb->posts.ID
FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
WHERE $wpdb->posts.post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )
AND $wpdb->posts.post_type IN ( 'product' )
AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s'
", $value);
$id = $wpdb->get_var($db_query);
if ( $id ) {
$parent_id = $id;
}
}
if($parent_id && empty($this->item_data['type'])){
throw new Exception('Basic version does not support import of variable products.' );
// $this->item_data['type'] = 'variation';
}
return $parent_id;
}
public function wt_parse_type_field($value) {
if(!empty($this->item_data['type'])){
return $this->item_data['type'];
}
$value = strtolower(trim($value));
$type = $value;
if ( $value == '') {
$type = 'simple';
}
if('' == $value && !empty($this->item_data['parent_id'])){
$type = 'variation';
}
if( $type == 'variation' || $type == 'variable' ){
throw new Exception(sprintf('Basic version does not support import of %s products.',$value ));
}
// Type is the most important part here because we need to be using the correct class and methods.
elseif ( isset( $value ) ) {
$types = array_keys( wc_get_product_types() );
// $types[] = 'variation';
if ( ! in_array( $type, $types, true ) ) {
throw new Exception(sprintf('Invalid product type %s',$value ));
}
}
return $type;
}
public function wt_parse_meta_field($value,$column) {
$meta_key = trim(str_replace('meta:', '', $column));
/**
* Handle meta: columns for variation attributes
*/
if (strstr($column, 'meta:attribute_')) {
$attribute_key = (trim(str_replace('meta:attribute_', '', $column)));
if (!$attribute_key )
return;
if('variation' == $this->item_data['type']){
$this->item_data['raw_attributes'][$attribute_key]['value'] = $this->wt_parse_seperation_field($value,'|');
}
return;
}
$this->item_data['meta_data'][] = array('key'=>$meta_key,'value'=>$value);
}
/**
* handle extra/other (custom taxonomy by other plugin) taxonomies.
*/
public function wt_parse_other_taxomomy_field($value, $column) {
// Get taxonomy
$taxonomy = trim(str_replace('tax:', '', $column));
// Exists?
if (!taxonomy_exists($taxonomy)) {
return;
}
if (empty($value)) {
return array();
}
$names = $this->wt_explode_values($value, '|');
$taxs = array();
foreach ($names as $name) {
$parent = null;
$other_terms = array_map( 'trim', explode( '>', $name ) );
$total = count( $other_terms );
foreach ( $other_terms as $index => $_term ) {
$term = term_exists( $_term, $taxonomy, $parent );
if ( is_array( $term ) ) {
$term_id = $term['term_id'];
}else {
$term = wp_insert_term( $_term, $taxonomy, array( 'parent' => intval( $parent ) ) );
if ( is_wp_error( $term ) ) {
break;
}
$term_id = $term['term_id'];
}
if ( ( 1 + $index ) === $total ) {
$taxs[] = $term_id;
} else {
$parent = $term_id;
}
}
}
$this->item_data['other_taxomomy_data'][] = array('taxonomy' => $taxonomy, 'terms' => $taxs);
}
public function wt_parse_taxonomy_field($value) {
return $value;
}
/**
* Handle Attributes
*/
public function wt_parse_attribute_field($value,$column) {
$attribute_key = sanitize_title(trim(str_replace('attribute:', '', $column)));
$attribute_args = array('name'=>'',
'value'=>array(),
'visible'=>1,
'taxonomy'=>0,
'default'=>'',
'position' =>0,
);
if (!$attribute_key)
return;
// Taxonomy
if (substr($attribute_key, 0, 3) == 'pa_') {
$this->item_data['raw_attributes'][$attribute_key]['name'] = trim(str_replace('attribute:pa_', '', $column));
$this->item_data['raw_attributes'][$attribute_key]['taxonomy'] = 1;
}else{
$this->item_data['raw_attributes'][$attribute_key]['name'] = trim(str_replace('attribute:', '', $column));
$this->item_data['raw_attributes'][$attribute_key]['taxonomy'] = 0;
}
if('variation' != $this->item_data['type']){
$this->item_data['raw_attributes'][$attribute_key]['value'] = $this->wt_parse_seperation_field($value,'|');
}
return;
}
/**
* Handle Attributes Data - position|is_visible|is_variation
*/
public function wt_parse_attribute_data_field($value,$column) {
$attribute_key = sanitize_title(trim(str_replace('attribute_data:', '', $column)));
if (!$attribute_key) {
return;
}
$values = explode('|', $value);
$position = isset($values[0]) ? (int) $values[0] : 0;
$visible = isset($values[1]) ? (int) $values[1] : 1;
$variation = isset($values[2]) ? (int) $values[2] : 0;
$this->item_data['raw_attributes'][$attribute_key]['visible'] = $visible;
$this->item_data['raw_attributes'][$attribute_key]['position'] = $position;
return;
}
/**
* Handle Attributes Default Values
*/
public function wt_parse_attribute_default_field($value,$column) {
$attribute_key = sanitize_title(trim(str_replace('attribute_default:', '', $column)));
if (!$attribute_key || '' == $value )
return;
$this->item_data['raw_attributes'][$attribute_key]['default'] = $value;
return;
}
public function wt_product_existance_check($data){
global $wpdb;
$product_id = 0;
$this->product_id = '';
$this->is_product_exist = false;
$id = isset($data['ID']) && !empty($data['ID']) ? absint($data['ID']) : 0;
$id_found_with_id = '';
if($id && 'id' == $this->merge_with){
$id_found_with_id = $wpdb->get_var($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' ) AND ID = %d;", $id)); // WPCS: db call ok, cache ok.
if($id_found_with_id){
if(in_array(get_post_type($id_found_with_id), array('product', 'product_variation'))){
$this->is_product_exist = true;
$product_id = $id_found_with_id;
}
}else{
$product_id = $data['ID'];
}
}
$sku = isset($data['_sku']) && '' != $data['_sku'] ? trim($data['_sku']) : '';
if($sku == ''){
$sku = isset($data['sku']) && '' != $data['sku'] ? trim($data['sku']) : '';
}
$id_found_with_sku = '';
if(!empty($sku) && 'sku' == $this->merge_with){
$db_query = $wpdb->prepare("SELECT $wpdb->posts.ID,$wpdb->posts.post_type
FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
WHERE $wpdb->posts.post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )
AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s'
", $sku);
$id_found_with_sku = $wpdb->get_row($db_query);
if ($id_found_with_sku && (in_array($id_found_with_sku->post_type, array('product', 'product_variation')))) {
$id_found_with_sku = $id_found_with_sku->ID;
$this->is_product_exist = true;
$product_id = $id_found_with_sku;
}
}
/*
* WPML
*/
if (apply_filters('wpml_setting', false, 'setup_complete') && (!empty($sku)) && ((!empty($data['wpml:original_product_id']) || !empty($data['wpml:original_product_sku'])) && !empty($data['wpml:language_code']))) {
$db_query = $wpdb->prepare("
SELECT $wpdb->posts.ID
FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
WHERE $wpdb->posts.post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )
AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s'
", $sku);
$found_product_ids = $wpdb->get_results($db_query);
/*
* Finding product ID by sku (each translation may have the same sku if the translation created by duplicating original product)
*/
$found_product_id = '';
foreach ($found_product_ids as $value) {
$original_post_language_info = self::wt_get_wpml_original_post_language_info($value->ID);
if ($original_post_language_info->language_code == $data['wpml:language_code']) {
$found_product_id = $value->ID;
}
}
if ($found_product_id != '') {
$product_id = $found_product_id;
}
}
if($this->is_product_exist){
if('skip' == $this->found_action){
if($id && $id_found_with_id ){
throw new Exception(sprintf('Product with same ID already exists. ID: %d',$id ));
}elseif($sku && $id_found_with_sku ){
throw new Exception(sprintf('Product with same SKU already exists. SKU: %s',$sku ));
}else{
throw new Exception('Product already exists.');
}
}elseif('update' == $this->found_action){
$this->merge = true;
$this->product_id = $product_id;
return $product_id;
}
}
if($this->skip_new){
throw new Exception('Skipping new item' );
}
if($id && $id_found_with_id && !$this->is_product_exist && 'skip' == $this->id_conflict){
throw new Exception(sprintf('Importing Product(ID) conflicts with an existing post. ID: %d',$id ));
}
}
/**
* Parse relative field and return ID.
*
* Handles `id` and Product SKU.
*
* If we're not doing an update, create a prost and return ID
* for rows following this one.
*
* @param array $data mapped data.
*
* @return int|Exception
*/
public function wt_parse_id_field($data ) {
if(!empty($this->item_data['id'])){
return $this->item_data['id'];
}
// global $wpdb;
// $product_id = 0;
// $this->is_product_exist = false;
//
$id = isset($data['ID']) && !empty($data['ID']) ? absint($data['ID']) : 0;
$found_id = $this->wt_product_existance_check($id);
if($found_id){
return $found_id;
}
$this->item_data['type'] = isset($this->item_data['type']) ? $this->item_data['type'] : 'simple';
$postdata = array( // if not specifiying id (id is empty) or if not found by given id or Product
'post_title' => ($this->item_data['type'] == 'variation' ? 'product variation' : $this->item_data['name'] ),
'post_status' => 'importing',
'post_type' => $this->post_type,
'post_content' => isset($this->item_data['description']) ? $this->item_data['description'] : '',
'post_excerpt' => isset($this->item_data['short_description']) ? $this->item_data['short_description'] : ''
);
if(isset($id) && !empty($id)){
$postdata['import_id'] = $id;
}
$post_id = wp_insert_post( $postdata, true );
if($post_id && !is_wp_error($post_id)){
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', sprintf('Importing as new '. ($this->parent_module->module_base).' ID:%d',$post_id ));
return $post_id;
}else{
throw new Exception($post_id->get_error_message());
}
}
/**
* Parse a comma-delineated field from a CSV.
*
* @param string $value Field value.
*
* @return array
*/
public function wt_parse_seperation_field($value, $separator = ',') {
if (empty($value) && '0' !== $value) {
return array();
}
$wt_clean_options = apply_filters('wt_clean_product_options', true);
if ($wt_clean_options) {
return array_map('wc_clean', $this->wt_explode_values($value, $separator));
} else {
return $this->wt_explode_values($value, $separator);
}
}
/**
* Parse a field that is generally '1' or '0' but can be something else.
*
* @param string $value Field value.
*
* @return bool|string
*/
public function wt_parse_bool_field( $value ) {
if ( '0' === $value ) {
return false;
}
if ( '1' === $value ) {
return true;
}
// Don't return explicit true or false for empty fields or values like 'notify'.
return wc_clean( $value );
}
/**
* Parse the tax status field.
*
* @param string $value Field value.
*
* @return string
*/
public function wt_parse_tax_status_field( $value ) {
if ( '' === $value ) {
return $value;
}
$tax_status = strtolower($value);
$value = ('taxable' == $tax_status || 'shipping' == $tax_status) ? $tax_status : 'none';
return wc_clean( $value );
}
/**
* Parse a category field from a CSV.
* Categories are separated by commas and subcategories are "parent > subcategory".
*
* @param string $value Field value.
*
* @return array of arrays with "parent" and "name" keys.
*/
public function wt_parse_categories_field( $value ) {
if ( empty( $value ) ) {
return array();
}
$row_terms = $this->wt_explode_values( $value ,'|' );
$categories = array();
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.
$term = term_exists( $_term, 'product_cat', $parent );
if ( is_array( $term ) ) {
$term_id = $term['term_id'];
// Don't allow users without capabilities to create new categories.
} elseif ( ! current_user_can( 'manage_product_terms' ) ) {
break;
} else {
$term = wp_insert_term( $_term, 'product_cat', array( 'parent' => intval( $parent ) ) );
if ( is_wp_error( $term ) ) {
break; // We cannot continue if the term cannot be inserted.
}
$term_id = $term['term_id'];
}
// Only requires assign the last category.
if ( ( 1 + $index ) === $total ) {
$categories[] = $term_id;
} else {
// Store parent to be able to insert or query categories based in parent ID.
$parent = $term_id;
}
}
}
return $categories;
}
/**
* Parse a tag field from a CSV.
*
* @param string $value Field value.
*
* @return array
*/
public function wt_parse_tags_field( $value ) {
if ( empty( $value ) ) {
return array();
}
$names = $this->wt_explode_values( $value, '|' );
$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' );
}
if ( ! is_wp_error( $term ) ) {
$tags[] = $term->term_id;
}
}
return $tags;
}
/**
* Parse a tag field from a CSV with space separators.
*
* @param string $value Field value.
*
* @return array
*/
public function wt_parse_tags_spaces_field( $value ) {
if ( empty( $value ) ) {
return array();
}
$names = $this->wt_explode_values( $value, ' ' );
$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' );
}
if ( ! is_wp_error( $term ) ) {
$tags[] = $term->term_id;
}
}
return $tags;
}
/**
* Parse a shipping class field from a CSV.
*
* @param string $value Field value.
*
* @return int
*/
public function wt_parse_shipping_class_field( $value ) {
if ( empty( $value ) ) {
return 0;
}
$term = get_term_by( 'name', $value, 'product_shipping_class' );
if ( ! $term || is_wp_error( $term ) ) {
$term = (object) wp_insert_term( $value, 'product_shipping_class' );
}
if ( is_wp_error( $term ) ) {
return 0;
}
return $term->term_id;
}
/**
* Parse images list from a CSV. Images can be filenames or URLs.
*
* @param string $value Field value.
*
* @return array
*/
public function wt_parse_images_field( $value ) {
if ( empty( $value ) ) {
return array();
}
$images = array();
$default_separator = '|';
if (strpos($value, ',') !== false) {
$default_separator = ',';
}
$separator = apply_filters( 'wt_woocommerce_product_import_image_separator', $default_separator );
foreach ( $this->wt_explode_values( $value, $separator ) as $image_data ) {
$images[] = $this->arrange_product_images($image_data);
}
return $images;
}
/**
* Arrange product images metadata
*/
public function arrange_product_images($image_data) {
if (!empty($image_data)) {
$image_details[] = explode('!', $image_data);
foreach ($image_details as $image_detail) {
$j = 0;
foreach ($image_detail as $current_image_detail) {
if ($j == 0) {
$images['url'] = trim($current_image_detail);
$j++;
continue;
}
@list($image['key'], $image['data']) = explode(':', $current_image_detail);
$images[trim(strtolower($image['key']))] = trim($image['data']);
}
}
unset($image_details, $image_detail, $current_image_detail, $image, $image_data, $j);
}
return $images;
}
/**
* Parse download file urls, we should allow shortskus here.
*
* Allow shortskus if present, othersiwe esc_url the value.
*
* @param string $value Field value.
*
* @return string
*/
public function wt_parse_download_file_field( $value ) {
// Absolute file paths.
if ( 0 === strpos( $value, 'http' ) ) {
return esc_url_raw( $value );
}
// Relative and shortsku paths.
return wc_clean( $value );
}
/**
* Parse an int value field
*
* @param int $value field value.
*
* @return int
*/
public function wt_parse_int_field( $value ) {
// Remove the ' prepended to fields that start with - if needed.
// $value = $this->unescape_data( $value );
return intval( $value );
}
/**
* Parse the published field. 1 is published, 0 is private, -1 is draft.
* Alternatively, 'true' can be used for published and 'false' for draft.
*
* @param string $value Field value.
*
* @return float|string
*/
public function wt_parse_published_field( $value ) {
$product_status = strtolower($value);
// Status is mapped from a special published field.
if (in_array($product_status, array(1, '1', TRUE, 'true', 'publish'), TRUE)) {
$product_status = 'publish';
} elseif (in_array($product_status, array(0, '0', FALSE, 'false', 'draft'), TRUE)) {
$product_status = 'draft';
}
if (!in_array($product_status, array('publish', 'private', 'draft', 'pending', 'future', 'inherit', 'trash'))) {
$product_status = 'publish';
}
return $product_status;
}
public function wt_parse_downloads_field($value){
if ( empty( $value ) ) {
return array();
}
$download = array();
foreach ( $this->wt_explode_values( $value, '|' ) as $key => $download_data ) {
@list($download[$key]['name'], $download[$key]['file']) = explode('::', $download_data);
}
return $download;
}
/**
* Parse a description value field
*
* @param string $description field value.
*
* @return string
*/
public function wt_parse_description_field( $description ) {
$parts = explode( "\\\\n", $description );
foreach ( $parts as $key => $part ) {
$parts[ $key ] = str_replace( '\n', "\n", $part );
}
return implode( '\\\n', $parts );
}
public function get_default_data(){
return array(
// 'id' => 0,
'name' => '',
'slug' => '',
'date_created' => null,
'date_modified' => null,
'status' => false,
'featured' => false,
'catalog_visibility' => 'visible',
'description' => '',
'short_description' => '',
'sku' => '',
'price' => '',
'regular_price' => '',
'sale_price' => '',
'date_on_sale_from' => null,
'date_on_sale_to' => null,
'total_sales' => '0',
'tax_status' => 'taxable',
'tax_class' => '',
'manage_stock' => false,
'stock_quantity' => null,
'stock_status' => 'instock',
'backorders' => 'no',
'low_stock_amount' => '',
'sold_individually' => false,
'weight' => '',
'length' => '',
'width' => '',
'height' => '',
'upsell_ids' => array(),
'cross_sell_ids' => array(),
'parent_id' => 0,
'reviews_allowed' => true,
'purchase_note' => '',
'attributes' => array(),
'default_attributes' => array(),
'menu_order' => 0,
'post_password' => '',
'virtual' => false,
'downloadable' => false,
'category_ids' => array(),
'tag_ids' => array(),
'shipping_class_id' => 0,
'downloads' => array(),
'image_id' => '',
'gallery_image_ids' => array(),
'download_limit' => -1,
'download_expiry' => -1,
'rating_counts' => array(),
'average_rating' => 0,
'review_count' => 0,
// Grouped product
'children' => array()
);
}
public function process_item($data) {
try {
do_action('wt_woocommerce_product_import_before_process_item', $data);
$data = apply_filters('wt_woocommerce_product_import_process_item_data', $data);
// Get product ID from SKU if created during the importation.
if (empty($data['id']) && !empty($data['sku'])) {
$product_id = wc_get_product_id_by_sku($data['sku']);
if ($product_id) {
$data['id'] = $product_id;
}
}
$object = $this->get_product_object($data);
if (is_wp_error($object)) {
return $object;
}
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', "Found ".$object->get_type()." product object. ID:".$object->get_id());
if ('external' === $object->get_type()) {
unset($data['manage_stock'], $data['stock_status'], $data['backorders'], $data['low_stock_amount']);
}
if ('variation' === $object->get_type()) {
if (isset($data['status']) && 'draft' === $data['status']) {
$data['status'] = 'private'; // Variations cannot be drafts - set to private.
}
}
if ('importing' === $object->get_status()) {
$object->set_status($data['status']);
}
$result = $object->set_props(array_diff_key($data, array_flip(array('meta_data', 'raw_image_id', 'raw_gallery_image_ids', 'raw_attributes','attributes','default_attributes','images'))));
if (is_wp_error($result)) {
throw new Exception($result->get_error_message());
}
if(isset($data['raw_attributes']) && is_array($data['raw_attributes'])){
$data['raw_attributes'] = array_filter($data['raw_attributes'],array( $this, 'wt_remove_empty_attributes' ));
// Sort attribute positions
if (!function_exists('attributes_cmp')) {
function attributes_cmp($a, $b) {
if ($a['position'] == $b['position'])
return 0;
return ( $a['position'] < $b['position'] ) ? -1 : 1;
}
}
uasort($data['raw_attributes'], 'attributes_cmp');
}else{
$data['raw_attributes'] = array();
}
$this->set_product_data($object, $data);
$this->set_image_data($object, $data);
$this->set_meta_data($object, $data);
$this->set_other_taxonomy_data($object, $data);
$object = apply_filters('wt_woocommerce_product_import_pre_insert_product_object', $object, $data);
$object->save();
$product_post = get_post( $object->get_id());
if ( $product_post && apply_filters( 'wt_woocommerce_product_importer_allow_post_author_from_import_file', false) ) {
$product_post->post_author = $data['post_author'];
wp_update_post( $product_post );
}
/*
* WPML
*/
$translation_post_details = array();
if (isset($data['wpml']) && !empty($data['wpml'])) {
foreach ($data['wpml'] as $meta) {
$key = apply_filters('wt_wpml_import_post_meta_key', $meta['key']);
if ($key == 'original_product_id' || $key == 'original_product_sku' || $key == 'language_code') {
$translation_post_details[$key] = $meta['value'];
}
}
$translation_post_details['current_post_id'] = $object->get_id();
}
if ((!empty($translation_post_details['original_product_id']) || !empty($translation_post_details['original_product_sku'])) && !empty($translation_post_details['language_code'])) {
$this->wt_wpml_element_connect_on_insert($translation_post_details);
}
if($this->delete_existing){
update_post_meta($object->get_id(), '_wt_delete_existing', 1);
}
do_action('wt_woocommerce_product_import_inserted_product_object', $object, $data);
return $result = array(
'id' => $object->get_id(),
'updated' => $this->merge,
);
} catch (Exception $e) {
return new WP_Error('woocommerce_product_importer_error', $e->getMessage(), array('status' => $e->getCode()));
}
}
public function wt_remove_empty_attributes($attribute) {
if($this->merge_empty_cells){
return $attribute;
}
if(!empty($attribute['value'])){
return $attribute;
}
}
function get_product_object($data) {
$id = isset($data['id']) ? absint($data['id']) : 0;
// Type is the most important part here because we need to be using the correct class and methods.
if (isset($data['type'])) {
$types = array('simple', 'grouped', 'external');
if (!in_array($data['type'], $types, true)) {
return new WP_Error('woocommerce_product_importer_invalid_type', __('Invalid product type.', 'woocommerce'), array('status' => 401));
}
try {
$product = wt_wc_get_product_object($data['type'], $id);
} catch (WC_Data_Exception $e) {
return new WP_Error('woocommerce_product_csv_importer_' . $e->getErrorCode(), $e->getMessage(), array('status' => 401));
}
} elseif (!empty($data['id'])) {
$product = wc_get_product($id);
if (!$product) {
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,
)
);
}
} else {
$product = wt_wc_get_product_object('simple', $id);
}
return apply_filters('wt_woocommerce_product_import_get_product_object', $product, $data);
}
function get_attribute_taxonomy_id($raw_name) {
global $wpdb, $wc_product_attributes;
// 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');
$attribute_name = array_search($raw_name, $attribute_labels, true);
if (!$attribute_name) {
$attribute_name = wc_sanitize_taxonomy_name($raw_name);
}
$attribute_id = wc_attribute_taxonomy_id_by_name($attribute_name);
// Get the ID from the name.
if ($attribute_id) {
return $attribute_id;
}
$beautify_attr_name = ucfirst(str_replace('-', ' ', $raw_name));
// If the attribute does not exist, create it.
$attribute_id = wc_create_attribute(
array(
'name' => $beautify_attr_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);
}
// Register as taxonomy while importing.
$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,
)
)
);
// Set product attributes global.
$wc_product_attributes = array();
foreach (wc_get_attribute_taxonomies() as $taxonomy) {
$wc_product_attributes[wc_attribute_taxonomy_name($taxonomy->attribute_name)] = $taxonomy;
}
return $attribute_id;
}
function get_variation_parent_attributes($attributes, $parent) {
$parent_attributes = $parent->get_attributes();
$require_save = false;
foreach ($attributes as $attribute) {
$attribute_id = 0;
// Get ID if is a global attribute.
if (!empty($attribute['taxonomy'])) {
$attribute_id = $this->get_attribute_taxonomy_id($attribute['name']);
}
if ($attribute_id) {
$attribute_name = wc_attribute_taxonomy_name_by_id($attribute_id);
} else {
$attribute_name = sanitize_title($attribute['name']);
}
// Check if attribute handle variations.
if (isset($parent_attributes[$attribute_name]) && !$parent_attributes[$attribute_name]->get_variation()) {
// Re-create the attribute to CRUD save and generate again.
$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;
}
function set_product_data(&$product, $data) {
if (isset($data['raw_attributes']) && !empty($data['raw_attributes'])) {
$attributes = array();
$default_attributes = array();
$existing_attributes = $product->get_attributes();
if(isset($existing_attributes)){
foreach ($existing_attributes as $key => $existing_attribute) {
$attributes[] = $existing_attribute;
}
}
foreach ($data['raw_attributes'] as $position => $attribute) {
$attribute_id = 0;
// Get ID if is a global attribute.
if (!empty($attribute['taxonomy'])) {
$attribute_id = $this->get_attribute_taxonomy_id($attribute['name']);
}
// Set attribute visibility.
if (isset($attribute['visible'])) {
$is_visible = $attribute['visible'];
} else {
$is_visible = 1;
}
// 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.
$is_variation = 0;
if ($attribute_id) {
if (isset($attribute['value'])) {
$options = array_map('wc_sanitize_term_text_based', $attribute['value']);
$options = array_filter($options, 'strlen');
} else {
$options = array();
}
// Check for default attributes and set "is_variation".
if (!empty($attribute['default']) && in_array($attribute['default'], $options, true)) {
$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']);
}
$default_attributes[$attribute_name] = $default;
$is_variation = 1;
}
if (!empty($options)) {
$attribute_object = new WC_Product_Attribute();
$attribute_object->set_id($attribute_id);
$attribute_object->set_name($attribute_name);
$attribute_object->set_options($options);
$attribute_object->set_position($attribute['position']);
$attribute_object->set_visible($is_visible);
$attribute_object->set_variation($is_variation);
$attributes[] = $attribute_object;
}
} elseif (isset($attribute['value'])) {
// Check for default attributes and set "is_variation".
if (!empty($attribute['default']) && in_array($attribute['default'], $attribute['value'], true)) {
$default_attributes[sanitize_title($attribute['name'])] = $attribute['default'];
$is_variation = 1;
}
$attribute_object = new WC_Product_Attribute();
$attribute_object->set_name($attribute['name']);
$attribute_object->set_options($attribute['value']);
$attribute_object->set_position($attribute['position']);
$attribute_object->set_visible($is_visible);
$attribute_object->set_variation($is_variation);
$attributes[] = $attribute_object;
}
if (empty($attribute['value']) && $this->merge_empty_cells) {
foreach ($attributes as $key => $attribute) {
if (method_exists($attribute, 'get_name') && $attribute->get_name() === $attribute_name) {
$attributes[$key]->set_options(array());
}
}
}
}
$product->set_attributes($attributes);
}
}
function set_image_data(&$product, $data) {
// Image URLs need converting to IDs before inserting.
if (isset($data['raw_image'])) {
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', 'Setting Featured Image. URL:'.$data['raw_image']['url']);
$image_id = $this->get_attachment_id_from_url($data['raw_image']['url'], $product->get_id());
if($image_id){
$this->wt_set_attachment_data($image_id,$data['raw_image']);
$product->set_image_id($image_id);
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', 'Attachment ID:'.$image_id);
}
}
// Gallery image URLs need converting to IDs before inserting.
if (isset($data['raw_gallery_image'])) {
$gallery_image_ids = array();
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', 'Setting Gallery Images.');
foreach ($data['raw_gallery_image'] as $image_id) {
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', 'Image URL:'.$image_id['url']);
$gallery_image_id = $this->get_attachment_id_from_url($image_id['url'], $product->get_id());
if($gallery_image_id){
$this->wt_set_attachment_data($gallery_image_id, $image_id);
$gallery_image_ids[] = $gallery_image_id;
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', 'Attachment ID:'.$gallery_image_id);
}
}
$product->set_gallery_image_ids(array_filter($gallery_image_ids));
}
}
function wt_set_attachment_data($attachment_id, $attachment_data) {
$attachment = array(
'ID' => $attachment_id,
'post_content' => isset($attachment_data['desc']) ? $attachment_data['desc'] : '',
'post_excerpt' => isset($attachment_data['caption']) ? $attachment_data['caption'] : '',
);
if (isset($attachment_data['title']) && !empty($attachment_data['title'])) {
$attachment['post_title'] = $attachment_data['title'];
}
wp_update_post($attachment);
if (isset($attachment_data['alt']) && !empty($attachment_data['alt'])) {
update_post_meta($attachment_id, '_wp_attachment_image_alt', $attachment_data['alt']);
}
}
public function fetch_remote_file($url, $post) {
// extract the file name and extension from the url
$file_name = basename(current(explode('?', $url)));
$wp_filetype = wp_check_filetype($file_name, null);
$parsed_url = @parse_url($url);
// Check parsed URL
if (!$parsed_url || !is_array($parsed_url))
return new WP_Error('import_file_error', 'Invalid URL');
// Ensure url is valid
$url = str_replace(" ", '%20', $url);
// Get the file
$response = wp_remote_get($url, array(
'timeout' => 60,
"user-agent" => "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:56.0) Gecko/20100101 Firefox/56.0",
'sslverify' => FALSE
));
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200)
return new WP_Error('import_file_error', 'Error getting remote image');
// Ensure we have a file name and type
if (!$wp_filetype['type']) {
$headers = wp_remote_retrieve_headers($response);
if (isset($headers['content-disposition']) && strstr($headers['content-disposition'], 'filename=')) {
$disposition = end(explode('filename=', $headers['content-disposition']));
$disposition = sanitize_file_name($disposition);
$file_name = $disposition;
if (isset($headers['content-type']) && strstr($headers['content-type'], 'image/')) {
$supported_image = array(
'gif',
'jpg',
'jpeg',
'png'
);
$ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION)); // Using strtolower to overcome case sensitive
if (!in_array($ext, $supported_image)) {
$file_name = $file_name . '.' . str_replace('image/', '', $headers['content-type']);
}
}
} elseif (isset($headers['content-type']) && strstr($headers['content-type'], 'image/')) {
$file_name = 'image.' . str_replace('image/', '', $headers['content-type']);
$file_name = preg_replace('/^([^;]*).*$/', '$1', $file_name);
}
unset($headers);
}
// Upload the file
$upload = wp_upload_bits($file_name, '', wp_remote_retrieve_body($response));
if ($upload['error'])
return new WP_Error('upload_dir_error', $upload['error']);
// Get filesize
$filesize = filesize($upload['file']);
if (0 == $filesize) {
@unlink($upload['file']);
unset($upload);
return new WP_Error('import_file_error', __('Zero size file downloaded', 'wf_csv_import_export'));
}
unset($response);
return $upload;
}
function get_attachment_id_from_url($url, $product_id) {
if (empty($url)) {
return 0;
}
$id = 0;
$upload_dir = wp_upload_dir(null, false);
$base_url = $upload_dir['baseurl'] . '/';
$remove_protocol = array("http://","https://");
// Check first if attachment is inside the WordPress uploads directory, or we're given a filename only.
if (false !== strpos(str_replace($remove_protocol,"",$url), str_replace($remove_protocol,"",$base_url)) || false === strpos($url, '://')) {
// Search for yyyy/mm/slug.extension or slug.extension - remove the base URL.
$file = str_replace(str_replace($remove_protocol,"",$base_url), '', str_replace($remove_protocol,"",$url));
$args = array(
'post_type' => 'attachment',
'post_status' => 'any',
'fields' => 'ids',
'meta_query' => array(// @codingStandardsIgnoreLine.
'relation' => 'OR',
array(
'key' => '_wp_attached_file',
'value' => '^' . $file,
'compare' => 'REGEXP',
),
array(
'key' => '_wp_attached_file',
'value' => '/' . $file,
'compare' => 'LIKE',
),
array(
'key' => '_wt_attachment_source',
'value' => '/' . $file,
'compare' => 'LIKE',
),
),
);
} else {
// This is an external URL, so compare to source.
$args = array(
'post_type' => 'attachment',
'post_status' => 'any',
'fields' => 'ids',
'meta_query' => array(// @codingStandardsIgnoreLine.
array(
'value' => $url,
'key' => '_wt_attachment_source',
),
),
);
}
$ids = get_posts($args); // @codingStandardsIgnoreLine.
if ($ids) {
$id = current($ids);
}
// Upload if attachment does not exists.
if (!$id && stristr($url, '://')) {
add_filter( 'https_ssl_verify', '__return_false' );
// Bypass image thumbnail generation - it will be in background after the last batch.
add_filter( 'intermediate_image_sizes', '__return_empty_array' );
$upload = wc_rest_upload_image_from_url($url);
if (is_wp_error($upload)) {
$allow_custom_rendered_image = apply_filters('wt_allow_custom_rendered_image', true);
if($allow_custom_rendered_image){
$upload = $this->fetch_remote_file($url, array());
if (is_wp_error($upload)) {
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', 'URL:'.$url.' Reason:'.$upload->get_error_message());
return;
}
}else{
Wt_Import_Export_For_Woo_Logwriter::write_log($this->parent_module->module_base, 'import', 'URL:'.$url.' Reason:'.$upload->get_error_message());
return;
}
}
if (apply_filters('wt_use_wc_rest_upload', true)) {
$id = wc_rest_set_uploaded_image_as_attachment($upload, $product_id);
} else {
$info = wp_check_filetype($upload['file']);
$post = array();
$post['post_mime_type'] = $info['type'];
$post['guid'] = $upload['url'];
$post['post_title'] = $upload['name'];
$id = wp_insert_attachment($post, $upload['file'], $product_id);
}
if (!wp_attachment_is_image($id)) {
/* translators: %s: image URL */
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', sprintf(__('Not able to attach "%s".'), $url));
return;
}
// Save attachment source for future reference.
update_post_meta($id, '_wt_attachment_source', $url);
}
if (!$id) {
/* translators: %s: image URL */
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', sprintf(__('Unable to use image "%s".'), $url));
return;
}
return $id;
}
function set_meta_data(&$product, $data) {
if (isset($data['meta_data'])) {
foreach ($data['meta_data'] as $meta) {
if(''== $meta)
continue;
$function = 'set_' . $meta[ 'key' ];
$has_setter = is_callable( array( $product, $function ) );
if ( $has_setter ) {
$product->{$function}( $meta[ 'value' ] );
continue;
}
$product->update_meta_data($meta['key'], $meta['value']);
}
}
}
/* Set third-party taxonomy data ( eg:- brand ) */
public function set_other_taxonomy_data(&$product, $data) {
if (isset($data['other_taxomomy_data']) && !empty($data['other_taxomomy_data'])) {
$terms_to_set = array();
foreach ($data['other_taxomomy_data'] as $term_group) {
$taxonomy = $term_group['taxonomy'];
$terms = $term_group['terms'];
if (!$taxonomy || !taxonomy_exists($taxonomy)) {
continue;
}
if (!is_array($terms)) {
$terms = array($terms);
}
$terms_to_set[$taxonomy] = array();
foreach ($terms as $term_id) {
$terms_to_set[$taxonomy][] = intval($term_id);
}
}
foreach ($terms_to_set as $tax => $ids) {
if(isset($data['id'])&& !empty($data['id'])){
wp_set_post_terms($data['id'], $ids, $tax, false);
}
}
unset($data['other_taxomomy_data'], $terms_to_set);
}
}
/**
* WPML compatibility
*/
public function wt_wpml_element_connect_on_insert($translation_post_details) {
if ($translation_post_details) {
// https://wpml.org/wpml-hook/wpml_element_type/
$wpml_element_type = apply_filters('wpml_element_type', 'post_product');
// get the language info of the original post
// https://wpml.org/wpml-hook/wpml_element_language_details/
if (isset($translation_post_details['original_product_id']) && !empty($translation_post_details['original_product_id']))
$original_product = wc_get_product($translation_post_details['original_product_id']);
$original_product_id = '';
if (!empty($original_product) && is_object($original_product)) {
$original_product_id = $translation_post_details['original_product_id'];
}
if (!$original_product_id && isset($translation_post_details['original_product_sku']) && !empty($translation_post_details['original_product_sku'])) {
$original_product_id = wc_get_product_id_by_sku($translation_post_details['original_product_sku']);
}
if ($original_product_id) {
$original_post_language_info = self::wt_get_wpml_original_post_language_info($original_product_id);
$set_language_args = array(
'element_id' => $translation_post_details['current_post_id'],
'element_type' => $wpml_element_type,
'trid' => $original_post_language_info->trid,
'language_code' => $translation_post_details['language_code'],
'source_language_code' => $original_post_language_info->language_code
);
do_action('wpml_set_element_language_details', $set_language_args);
}
}
}
/**
* Get info like language code, parent product ID etc by product id.
* @param int Product ID.
* @return array/false.
*/
public static function wt_get_wpml_original_post_language_info($element_id) {
$get_language_args = array('element_id' => $element_id, 'element_type' => 'post_product');
$original_post_language_info = apply_filters('wpml_element_language_details', null, $get_language_args);
return $original_post_language_info;
}
/**
* Generate product description using ChatGPT.
*
* @since 2.3.1
*
* @param string $product_description
* @param string $api_key
* @return string
*/
public function generate_product_description_using_openai($product_description, $api_key) {
$api_url = 'https://api.openai.com/v1/chat/completions';
$tone = apply_filters( 'wt_openai_product_description_tone', 'formal' );
// casual - Relaxed, informal, conversational tone. Like chatting with a friend.
// formal - A polished, well-structured product description, adhering to professional standards.
// flowery - Ornate, elaborate, poetic tone. Rich in descriptive language.
// convincing - A persuasive, compelling product description, designed to influence decisions and drive action.
$messages = array(
array(
'role' => 'user',
'content' => "Write a product description with $tone tone, from the following features: '$product_description'.",
),
);
// Configure curl request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json',
'Authorization: Bearer ' . $api_key,
)
);
$post_data = array(
'messages' => $messages,
'model' => 'gpt-3.5-turbo',
'temperature' => 1,
);
$post_data_json = json_encode($post_data);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data_json);
$response = curl_exec($ch);
$generated_text = $product_description;
if (curl_error($ch)) {
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', "ChatGPT API error response : " . curl_error($ch));
} else {
$response_data = json_decode($response, true);
if (isset($response_data['error']) && !empty($response_data['error'])) {
Wt_Import_Export_For_Woo_Basic_Logwriter::write_log($this->parent_module->module_base, 'import', "ChatGPT API error response : " . $response_data['error']['message']);
} else {
$generated_text = $response_data['choices'][0]['message']['content'];
// If cannot find proper description, return the input
if (strpos($generated_text, 'We apologize') !== false) {
$generated_text = $product_description;
}
}
}
curl_close($ch);
return $generated_text;
}
}
}