Import Products from any XML or CSV to WooCommerce - Version 1.3.4

Version Description

  • bug fix: import product visibility WC 3.0
  • bug fix: stock threshold
Download this release

Release Info

Developer soflyy
Plugin Icon 128x128 Import Products from any XML or CSV to WooCommerce
Version 1.3.4
Comparing to
See all releases

Code changes from version 1.3.3 to 1.3.4

models/import/record.php CHANGED
@@ -240,21 +240,29 @@ class PMWI_Import_Record extends PMWI_Model_Record {
240
  }
241
 
242
  // Composing product Stock status
243
- if ($import->options['product_stock_status'] == 'xpath' and "" != $import->options['single_product_stock_status']){
244
- $this->data['product_stock_status'] = XmlImportParser::factory($xml, $cxpath, $import->options['single_product_stock_status'], $file)->parse($records); $tmp_files[] = $file;
 
245
  }
246
- elseif($import->options['product_stock_status'] == 'auto'){
 
247
  $count and $this->data['product_stock_status'] = array_fill(0, $count, $import->options['product_stock_status']);
248
- foreach ($this->data['product_stock_qty'] as $key => $value) {
249
- if ($this->data['product_manage_stock'][$key] == 'yes'){
250
- $this->data['product_stock_status'][$key] = (( (int) $value === 0 or (int) $value < 0 ) and $value != "") ? 'outofstock' : 'instock';
 
 
 
 
 
251
  }
252
  else{
253
  $this->data['product_stock_status'][$key] = 'instock';
254
  }
255
  }
256
  }
257
- else{
 
258
  $count and $this->data['product_stock_status'] = array_fill(0, $count, $import->options['product_stock_status']);
259
  }
260
 
@@ -629,19 +637,14 @@ class PMWI_Import_Record extends PMWI_Model_Record {
629
 
630
  $is_new_product = empty($articleData['ID']);
631
 
632
- // Get types
633
  $product_type = 'simple';
634
 
635
- if ($this->options['update_all_data'] == 'no' and ! $this->options['is_update_product_type'] and ! $is_new_product ){
636
- $product = WC()->product_factory->get_product($pid);
 
637
  if ( ! empty($product->product_type) ) $product_type = $product->product_type;
638
  }
639
-
640
- $this->existing_meta_keys = array();
641
- foreach (get_post_meta($pid, '') as $cur_meta_key => $cur_meta_val) $this->existing_meta_keys[] = $cur_meta_key;
642
-
643
- $this->post_meta_to_update = array(); // for bulk UPDATE SQL query
644
- $this->post_meta_to_insert = array(); // for bulk INSERT SQL query
645
  $this->articleData = $articleData;
646
 
647
  $total_sales = get_post_meta($pid, 'total_sales', true);
@@ -653,7 +656,7 @@ class PMWI_Import_Record extends PMWI_Model_Record {
653
  $is_featured = $product_featured[$i];
654
 
655
  // Product type + Downloadable/Virtual
656
- if ($is_new_product or $this->options['update_all_data'] == 'yes' or ($this->options['update_all_data'] == 'no' and $this->options['is_update_product_type'])) {
657
  $product_type_term = is_exists_term($product_type, 'product_type', 0);
658
  if ( ! empty($product_type_term) and ! is_wp_error($product_type_term) ){
659
  $this->associate_terms( $pid, array( (int) $product_type_term['term_taxonomy_id'] ), 'product_type' );
@@ -672,10 +675,10 @@ class PMWI_Import_Record extends PMWI_Model_Record {
672
  $this->pushmeta($pid, '_regular_price', ($product_regular_price[$i] == "") ? '' : stripslashes( $product_regular_price[$i] ) );
673
  $this->pushmeta($pid, '_sale_price', ($product_sale_price[$i] == "") ? '' : stripslashes( $product_sale_price[$i] ) );
674
  $this->pushmeta($pid, '_tax_status', stripslashes( $product_tax_status[$i] ) );
675
- $this->pushmeta($pid, '_tax_class', stripslashes( $product_tax_class[$i] ) );
676
- $this->pushmeta($pid, '_visibility', stripslashes( $product_visibility[$i] ) );
677
  $this->pushmeta($pid, '_purchase_note', stripslashes( $product_purchase_note[$i] ) );
678
  $this->pushmeta($pid, '_featured', ($is_featured == "yes") ? 'yes' : 'no' );
 
679
 
680
  // Dimensions
681
  if ( $is_virtual == 'no' ) {
@@ -690,12 +693,12 @@ class PMWI_Import_Record extends PMWI_Model_Record {
690
  $this->pushmeta($pid, '_height', '' );
691
  }
692
 
693
- if ($is_new_product or $this->is_update_data_allowed('is_update_comment_status')) $this->wpdb->update( $this->wpdb->posts, array('comment_status' => ($product_enable_reviews[$i] == 'yes') ? 'open' : 'closed' ), array('ID' => $pid));
694
 
695
  if ($is_new_product or $this->is_update_data_allowed('is_update_menu_order')) $this->wpdb->update( $this->wpdb->posts, array('menu_order' => ($product_menu_order[$i] != '') ? (int) $product_menu_order[$i] : 0 ), array('ID' => $pid));
696
 
697
  // Save shipping class
698
- if ( pmwi_is_update_taxonomy($articleData, $this->options, 'product_shipping_class') )
699
  {
700
 
701
  $p_shipping_class = ($product_type != 'external') ? $product_shipping_class[$i] : '';
@@ -782,27 +785,58 @@ class PMWI_Import_Record extends PMWI_Model_Record {
782
  // Unique SKU
783
  $sku = ($is_new_product) ? '' : get_post_meta($pid, '_sku', true);
784
  $new_sku = wc_clean( trim( stripslashes( $product_sku[$i] ) ) );
785
-
786
- if ( $new_sku == '' and $this->options['disable_auto_sku_generation'] ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
787
  $this->pushmeta($pid, '_sku', '' );
788
  }
789
- elseif ( $new_sku == '' and ! $this->options['disable_auto_sku_generation'] ) {
790
  if ($is_new_product or $this->is_update_cf('_sku')){
791
- $unique_keys = XmlImportParser::factory($xml, $cxpath, $this->options['unique_key'], $file)->parse(); $tmp_files[] = $file;
792
  foreach ($tmp_files as $file) { // remove all temporary files created
793
  @unlink($file);
794
  }
795
  $new_sku = substr(md5($unique_keys[$i]), 0, 12);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
796
  }
797
  }
798
  if ( $new_sku != '' and $new_sku !== $sku ) {
799
  if ( ! empty( $new_sku ) ) {
800
- if ( ! $this->options['disable_sku_matching'] and
801
  $this->wpdb->get_var( $this->wpdb->prepare("
802
  SELECT ".$this->wpdb->posts.".ID
803
  FROM ".$this->wpdb->posts."
804
  LEFT JOIN ".$this->wpdb->postmeta." ON (".$this->wpdb->posts.".ID = ".$this->wpdb->postmeta.".post_id)
805
- WHERE ".$this->wpdb->posts.".post_type = 'product'
 
806
  AND ".$this->wpdb->posts.".post_status = 'publish'
807
  AND ".$this->wpdb->postmeta.".meta_key = '_sku' AND ".$this->wpdb->postmeta.".meta_value = '%s'
808
  ", $new_sku ) )
@@ -824,7 +858,7 @@ class PMWI_Import_Record extends PMWI_Model_Record {
824
 
825
  $is_variation_attributes_defined = false;
826
 
827
- if ( $this->options['update_all_data'] == "yes" or ( $this->options['update_all_data'] == "no" and $this->options['is_update_attributes']) or $is_new_product){ // Update Product Attributes
828
 
829
  $is_update_attributes = true;
830
 
@@ -832,17 +866,11 @@ class PMWI_Import_Record extends PMWI_Model_Record {
832
 
833
  $attribute_position = 0;
834
 
835
- $attr_names = array();
836
-
837
  foreach ($serialized_attributes as $anum => $attr_data) { $attr_name = $attr_data['names'][$i];
838
 
839
- // if ( in_array( $attr_name, $this->reserved_terms ) ) {
840
- // $attr_name .= 's';
841
- // }
842
 
843
- if (empty($attr_name) or in_array($attr_name, $attr_names)) continue;
844
-
845
- $attr_names[] = $attr_name;
846
 
847
  $is_visible = intval( $attr_data['is_visible'][$i] );
848
  $is_variation = intval( $attr_data['in_variation'][$i] );
@@ -853,9 +881,9 @@ class PMWI_Import_Record extends PMWI_Model_Record {
853
  }
854
 
855
  // Update only these Attributes, leave the rest alone
856
- if ( ! $is_new_product and $this->options['update_all_data'] == "no" and $this->options['is_update_attributes'] and $this->options['update_attributes_logic'] == 'only'){
857
- if ( ! empty($this->options['attributes_list']) and is_array($this->options['attributes_list'])) {
858
- if ( ! in_array( ( ($is_taxonomy) ? wc_attribute_taxonomy_name( $attr_name ) : $attr_name ) , array_filter($this->options['attributes_list'], 'trim'))){
859
  $attribute_position++;
860
  continue;
861
  }
@@ -867,9 +895,9 @@ class PMWI_Import_Record extends PMWI_Model_Record {
867
  }
868
 
869
  // Leave these attributes alone, update all other Attributes
870
- if ( ! $is_new_product and $this->options['update_all_data'] == "no" and $this->options['is_update_attributes'] and $this->options['update_attributes_logic'] == 'all_except'){
871
- if ( ! empty($this->options['attributes_list']) and is_array($this->options['attributes_list'])) {
872
- if ( in_array( ( ($is_taxonomy) ? wc_attribute_taxonomy_name( $attr_name ) : $attr_name ) , array_filter($this->options['attributes_list'], 'trim'))){
873
  $attribute_position++;
874
  continue;
875
  }
@@ -885,7 +913,9 @@ class PMWI_Import_Record extends PMWI_Model_Record {
885
  // Remove empty items in the array
886
  $values = array_filter( $values, array($this, "filtering") );
887
 
888
- if (intval($attr_data['is_create_taxonomy_terms'][$i])) $this->create_taxonomy($attr_name, $logger);
 
 
889
 
890
  if ( ! empty($values) and taxonomy_exists( wc_attribute_taxonomy_name( $attr_name ) )){
891
 
@@ -930,7 +960,7 @@ class PMWI_Import_Record extends PMWI_Model_Record {
930
  else $values = array();
931
 
932
  }
933
-
934
  // Update post terms
935
  if ( taxonomy_exists( wc_attribute_taxonomy_name( $attr_name ) ))
936
  $this->associate_terms( $pid, $values, wc_attribute_taxonomy_name( $attr_name ) );
@@ -939,7 +969,7 @@ class PMWI_Import_Record extends PMWI_Model_Record {
939
  // Add attribute to array, but don't set values
940
  $attributes[ sanitize_title(wc_attribute_taxonomy_name( $attr_name )) ] = array(
941
  'name' => wc_attribute_taxonomy_name( $attr_name ),
942
- 'value' => '',
943
  'position' => $attribute_position,
944
  'is_visible' => $is_visible,
945
  'is_variation' => $is_variation,
@@ -956,12 +986,12 @@ class PMWI_Import_Record extends PMWI_Model_Record {
956
  $this->associate_terms( $pid, NULL, wc_attribute_taxonomy_name( $attr_name ) );
957
  }
958
 
959
- if (!empty($attr_data['value'][$i])){
960
 
961
  // Custom attribute - Add attribute to array and set the values
962
  $attributes[ sanitize_title( $attr_name ) ] = array(
963
  'name' => sanitize_text_field( $attr_name ),
964
- 'value' => $attr_data['value'][$i],
965
  'position' => $attribute_position,
966
  'is_visible' => $is_visible,
967
  'is_variation' => $is_variation,
@@ -1021,7 +1051,7 @@ class PMWI_Import_Record extends PMWI_Model_Record {
1021
 
1022
  if ( $product_sale_price[$i] != '' && $date_to == '' && $date_from == '' ){
1023
 
1024
- $this->pushmeta($pid, '_price', (empty($product_sale_price[$i])) ? '' : stripslashes( $product_sale_price[$i] ));
1025
 
1026
  }
1027
  else{
@@ -1030,7 +1060,7 @@ class PMWI_Import_Record extends PMWI_Model_Record {
1030
  }
1031
 
1032
  if ( $product_sale_price[$i] != '' && $date_from && strtotime( $date_from ) < strtotime( 'NOW', current_time( 'timestamp' ) ) ){
1033
- $this->pushmeta($pid, '_price', (empty($product_sale_price[$i])) ? '' : stripslashes( $product_sale_price[$i] ));
1034
  }
1035
 
1036
  if ( $date_to && strtotime( $date_to ) < strtotime( 'NOW', current_time( 'timestamp' ) ) ) {
@@ -1042,8 +1072,8 @@ class PMWI_Import_Record extends PMWI_Model_Record {
1042
 
1043
  if (in_array( $product_type, array( 'simple', 'external' ) )) {
1044
 
1045
- if ($this->options['is_multiple_grouping_product'] != 'yes'){
1046
- if ($this->options['grouping_indicator'] == 'xpath' and ! is_numeric($product_grouping_parent[$i])){
1047
  $dpost = pmxi_findDuplicates(array(
1048
  'post_type' => 'product',
1049
  'ID' => $pid,
@@ -1055,7 +1085,7 @@ class PMWI_Import_Record extends PMWI_Model_Record {
1055
  else
1056
  $product_grouping_parent[$i] = 0;
1057
  }
1058
- elseif ($this->options['grouping_indicator'] != 'xpath'){
1059
  $dpost = pmxi_findDuplicates($articleData, $custom_grouping_indicator_name[$i], $custom_grouping_indicator_value[$i], 'custom field');
1060
  if (!empty($dpost))
1061
  $product_grouping_parent[$i] = array_shift($dpost);
@@ -1067,7 +1097,15 @@ class PMWI_Import_Record extends PMWI_Model_Record {
1067
  if ( "" != $product_grouping_parent[$i] and absint($product_grouping_parent[$i]) > 0){
1068
 
1069
  $this->wpdb->update( $this->wpdb->posts, array('post_parent' => absint( $product_grouping_parent[$i] ) ), array('ID' => $pid));
1070
-
 
 
 
 
 
 
 
 
1071
  }
1072
  }
1073
 
@@ -1125,7 +1163,7 @@ class PMWI_Import_Record extends PMWI_Model_Record {
1125
 
1126
  $stock_status = 'instock';
1127
 
1128
- } elseif ( 'variable' === $product_type and ! $this->options['link_all_variations'] ) {
1129
 
1130
  // Stock status is always determined by children so sync later
1131
  // $stock_status = '';
@@ -1149,7 +1187,7 @@ class PMWI_Import_Record extends PMWI_Model_Record {
1149
 
1150
  $current_manage_stock = get_post_meta( $pid, '_manage_stock', true );
1151
 
1152
- if ( $product_manage_stock[$i] == 'yes' || ! $this->is_update_cf('_manage_stock') && $current_manage_stock == 'yes') {
1153
  $this->pushmeta( $pid, '_stock', wc_stock_amount( $product_stock_qty[$i] ) );
1154
  } else {
1155
  $this->pushmeta($pid, '_stock', '');
@@ -1160,10 +1198,10 @@ class PMWI_Import_Record extends PMWI_Model_Record {
1160
  }
1161
 
1162
  // Upsells
1163
- $this->import_linked_products($pid, $product_up_sells[$i], '_upsell_ids', $is_new_product, $logger, $import->id);
1164
 
1165
  // Cross sells
1166
- $this->import_linked_products($pid, $product_cross_sells[$i], '_crosssell_ids', $is_new_product, $logger, $import->id);
1167
 
1168
  // Downloadable options
1169
  if ( $is_downloadable == 'yes' ) {
@@ -1180,8 +1218,8 @@ class PMWI_Import_Record extends PMWI_Model_Record {
1180
  if ( !empty( $product_files[$i] ) ) {
1181
  $_file_paths = array();
1182
 
1183
- $file_paths = explode( $this->options['product_files_delim'] , $product_files[$i] );
1184
- $file_names = explode( $this->options['product_files_names_delim'] , $product_files_names[$i] );
1185
 
1186
  foreach ( $file_paths as $fn => $file_path ) {
1187
  $file_path = trim( $file_path );
@@ -1200,11 +1238,21 @@ class PMWI_Import_Record extends PMWI_Model_Record {
1200
  if ( isset( $product_download_type[$i] ) )
1201
  $this->pushmeta($pid, '_download_type', esc_attr( $product_download_type[$i] ));
1202
 
1203
- }
1204
 
1205
- // Update product visibility term WC 3.0.0
 
 
 
 
 
 
 
 
 
 
1206
  if ( version_compare(WOOCOMMERCE_VERSION, '3.0') >= 0 ) {
1207
- if ( pmwi_is_update_taxonomy($articleData, $this->options, 'product_visibility') ){
1208
  $associate_terms = array();
1209
  if ($is_featured == "yes"){
1210
  $featured_term = get_term_by( 'name', 'featured', 'product_visibility' );
240
  }
241
 
242
  // Composing product Stock status
243
+ if ($import->options['product_stock_status'] == 'xpath' and "" != $import->options['single_product_stock_status'])
244
+ {
245
+ $this->data['product_stock_status'] = XmlImportParser::factory($this->xml, $cxpath, $import->options['single_product_stock_status'], $file)->parse($records); $tmp_files[] = $file;
246
  }
247
+ elseif($import->options['product_stock_status'] == 'auto')
248
+ {
249
  $count and $this->data['product_stock_status'] = array_fill(0, $count, $import->options['product_stock_status']);
250
+
251
+ $nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );
252
+
253
+ foreach ($this->data['product_stock_qty'] as $key => $value)
254
+ {
255
+ if ($this->data['product_manage_stock'][$key] == 'yes')
256
+ {
257
+ $this->data['product_stock_status'][$key] = (( (int) $value === 0 or (int) $value <= $nostock ) and $value != "") ? 'outofstock' : 'instock';
258
  }
259
  else{
260
  $this->data['product_stock_status'][$key] = 'instock';
261
  }
262
  }
263
  }
264
+ else
265
+ {
266
  $count and $this->data['product_stock_status'] = array_fill(0, $count, $import->options['product_stock_status']);
267
  }
268
 
637
 
638
  $is_new_product = empty($articleData['ID']);
639
 
 
640
  $product_type = 'simple';
641
 
642
+ $product = WC()->product_factory->get_product($pid);
643
+
644
+ if ($import->options['update_all_data'] == 'no' and ! $import->options['is_update_product_type'] and ! $is_new_product ){
645
  if ( ! empty($product->product_type) ) $product_type = $product->product_type;
646
  }
647
+
 
 
 
 
 
648
  $this->articleData = $articleData;
649
 
650
  $total_sales = get_post_meta($pid, 'total_sales', true);
656
  $is_featured = $product_featured[$i];
657
 
658
  // Product type + Downloadable/Virtual
659
+ if ($is_new_product or $import->options['update_all_data'] == 'yes' or ($import->options['update_all_data'] == 'no' and $import->options['is_update_product_type'])) {
660
  $product_type_term = is_exists_term($product_type, 'product_type', 0);
661
  if ( ! empty($product_type_term) and ! is_wp_error($product_type_term) ){
662
  $this->associate_terms( $pid, array( (int) $product_type_term['term_taxonomy_id'] ), 'product_type' );
675
  $this->pushmeta($pid, '_regular_price', ($product_regular_price[$i] == "") ? '' : stripslashes( $product_regular_price[$i] ) );
676
  $this->pushmeta($pid, '_sale_price', ($product_sale_price[$i] == "") ? '' : stripslashes( $product_sale_price[$i] ) );
677
  $this->pushmeta($pid, '_tax_status', stripslashes( $product_tax_status[$i] ) );
678
+ $this->pushmeta($pid, '_tax_class', strtolower($product_tax_class[$i]) == 'standard' ? '' : stripslashes( $product_tax_class[$i] ) );
 
679
  $this->pushmeta($pid, '_purchase_note', stripslashes( $product_purchase_note[$i] ) );
680
  $this->pushmeta($pid, '_featured', ($is_featured == "yes") ? 'yes' : 'no' );
681
+ $this->pushmeta($pid, '_visibility', stripslashes( $product_visibility[$i] ) );
682
 
683
  // Dimensions
684
  if ( $is_virtual == 'no' ) {
693
  $this->pushmeta($pid, '_height', '' );
694
  }
695
 
696
+ if ($is_new_product or $this->is_update_data_allowed('is_update_comment_status')) $this->wpdb->update( $this->wpdb->posts, array('comment_status' => ( in_array($product_enable_reviews[$i], array('yes', 'open')) ) ? 'open' : 'closed' ), array('ID' => $pid));
697
 
698
  if ($is_new_product or $this->is_update_data_allowed('is_update_menu_order')) $this->wpdb->update( $this->wpdb->posts, array('menu_order' => ($product_menu_order[$i] != '') ? (int) $product_menu_order[$i] : 0 ), array('ID' => $pid));
699
 
700
  // Save shipping class
701
+ if ( pmwi_is_update_taxonomy($articleData, $import->options, 'product_shipping_class') )
702
  {
703
 
704
  $p_shipping_class = ($product_type != 'external') ? $product_shipping_class[$i] : '';
785
  // Unique SKU
786
  $sku = ($is_new_product) ? '' : get_post_meta($pid, '_sku', true);
787
  $new_sku = wc_clean( trim( stripslashes( $product_sku[$i] ) ) );
788
+
789
+ if ( ( in_array($product_type, array('variation', 'variable')) or $product_types[$i] == "variable" ) and ! $import->options['link_all_variations'] ){
790
+ switch ($import->options['matching_parent']){
791
+ case 'first_is_parent_id':
792
+ if (!empty($single_product_first_is_parent_id_parent_sku[$i])){
793
+ update_post_meta($pid, '_parent_sku', $single_product_first_is_parent_id_parent_sku[$i]);
794
+ }
795
+ break;
796
+ case 'first_is_variation':
797
+ if (!empty($single_product_first_is_parent_title_parent_sku[$i])){
798
+ update_post_meta($pid, '_parent_sku', $single_product_first_is_parent_title_parent_sku[$i]);
799
+ }
800
+ break;
801
+ }
802
+ }
803
+
804
+ if ( $new_sku == '' and $import->options['disable_auto_sku_generation'] ) {
805
  $this->pushmeta($pid, '_sku', '' );
806
  }
807
+ elseif ( $new_sku == '' and ! $import->options['disable_auto_sku_generation'] ) {
808
  if ($is_new_product or $this->is_update_cf('_sku')){
809
+ $unique_keys = XmlImportParser::factory($xml, $cxpath, $import->options['unique_key'], $file)->parse(); $tmp_files[] = $file;
810
  foreach ($tmp_files as $file) { // remove all temporary files created
811
  @unlink($file);
812
  }
813
  $new_sku = substr(md5($unique_keys[$i]), 0, 12);
814
+
815
+ if ( ( in_array($product_type, array('variation', 'variable')) or $product_types[$i] == "variable" ) and ! $import->options['link_all_variations'] ){
816
+ switch ($import->options['matching_parent']){
817
+ case 'first_is_parent_id':
818
+ if (empty($single_product_first_is_parent_id_parent_sku[$i])){
819
+ update_post_meta($pid, '_parent_sku', strrev($new_sku));
820
+ }
821
+ break;
822
+ case 'first_is_variation':
823
+ if (empty($single_product_first_is_parent_title_parent_sku[$i])){
824
+ update_post_meta($pid, '_parent_sku', strrev($new_sku));
825
+ }
826
+ break;
827
+ }
828
+ }
829
  }
830
  }
831
  if ( $new_sku != '' and $new_sku !== $sku ) {
832
  if ( ! empty( $new_sku ) ) {
833
+ if ( ! $import->options['disable_sku_matching'] and
834
  $this->wpdb->get_var( $this->wpdb->prepare("
835
  SELECT ".$this->wpdb->posts.".ID
836
  FROM ".$this->wpdb->posts."
837
  LEFT JOIN ".$this->wpdb->postmeta." ON (".$this->wpdb->posts.".ID = ".$this->wpdb->postmeta.".post_id)
838
+ WHERE (".$this->wpdb->posts.".post_type = 'product'
839
+ OR ".$this->wpdb->posts.".post_type = 'product_variation')
840
  AND ".$this->wpdb->posts.".post_status = 'publish'
841
  AND ".$this->wpdb->postmeta.".meta_key = '_sku' AND ".$this->wpdb->postmeta.".meta_value = '%s'
842
  ", $new_sku ) )
858
 
859
  $is_variation_attributes_defined = false;
860
 
861
+ if ( $import->options['update_all_data'] == "yes" or ( $import->options['update_all_data'] == "no" and $import->options['is_update_attributes']) or $is_new_product){ // Update Product Attributes
862
 
863
  $is_update_attributes = true;
864
 
866
 
867
  $attribute_position = 0;
868
 
 
 
869
  foreach ($serialized_attributes as $anum => $attr_data) { $attr_name = $attr_data['names'][$i];
870
 
871
+ if (empty($attr_name)) continue;
 
 
872
 
873
+ // $attr_names[] = $attr_name;
 
 
874
 
875
  $is_visible = intval( $attr_data['is_visible'][$i] );
876
  $is_variation = intval( $attr_data['in_variation'][$i] );
881
  }
882
 
883
  // Update only these Attributes, leave the rest alone
884
+ if ( ! $is_new_product and $import->options['update_all_data'] == "no" and $import->options['is_update_attributes'] and $import->options['update_attributes_logic'] == 'only'){
885
+ if ( ! empty($import->options['attributes_list']) and is_array($import->options['attributes_list'])) {
886
+ if ( ! in_array( ( ($is_taxonomy) ? wc_attribute_taxonomy_name( $attr_name ) : $attr_name ) , array_filter($import->options['attributes_list'], 'trim'))){
887
  $attribute_position++;
888
  continue;
889
  }
895
  }
896
 
897
  // Leave these attributes alone, update all other Attributes
898
+ if ( ! $is_new_product and $import->options['update_all_data'] == "no" and $import->options['is_update_attributes'] and $import->options['update_attributes_logic'] == 'all_except'){
899
+ if ( ! empty($import->options['attributes_list']) and is_array($import->options['attributes_list'])) {
900
+ if ( in_array( ( ($is_taxonomy) ? wc_attribute_taxonomy_name( $attr_name ) : $attr_name ) , array_filter($import->options['attributes_list'], 'trim'))){
901
  $attribute_position++;
902
  continue;
903
  }
913
  // Remove empty items in the array
914
  $values = array_filter( $values, array($this, "filtering") );
915
 
916
+ if (intval($attr_data['is_create_taxonomy_terms'][$i])){
917
+ $attr_name = $this->create_taxonomy($attr_name, $logger);
918
+ }
919
 
920
  if ( ! empty($values) and taxonomy_exists( wc_attribute_taxonomy_name( $attr_name ) )){
921
 
960
  else $values = array();
961
 
962
  }
963
+
964
  // Update post terms
965
  if ( taxonomy_exists( wc_attribute_taxonomy_name( $attr_name ) ))
966
  $this->associate_terms( $pid, $values, wc_attribute_taxonomy_name( $attr_name ) );
969
  // Add attribute to array, but don't set values
970
  $attributes[ sanitize_title(wc_attribute_taxonomy_name( $attr_name )) ] = array(
971
  'name' => wc_attribute_taxonomy_name( $attr_name ),
972
+ 'value' => $attr_data['value'][$i],
973
  'position' => $attribute_position,
974
  'is_visible' => $is_visible,
975
  'is_variation' => $is_variation,
986
  $this->associate_terms( $pid, NULL, wc_attribute_taxonomy_name( $attr_name ) );
987
  }
988
 
989
+ if (trim($attr_data['value'][$i]) != ""){
990
 
991
  // Custom attribute - Add attribute to array and set the values
992
  $attributes[ sanitize_title( $attr_name ) ] = array(
993
  'name' => sanitize_text_field( $attr_name ),
994
+ 'value' => trim($attr_data['value'][$i]),
995
  'position' => $attribute_position,
996
  'is_visible' => $is_visible,
997
  'is_variation' => $is_variation,
1051
 
1052
  if ( $product_sale_price[$i] != '' && $date_to == '' && $date_from == '' ){
1053
 
1054
+ $this->pushmeta($pid, '_price', ($product_sale_price[$i] == "") ? '' : stripslashes( $product_sale_price[$i] ));
1055
 
1056
  }
1057
  else{
1060
  }
1061
 
1062
  if ( $product_sale_price[$i] != '' && $date_from && strtotime( $date_from ) < strtotime( 'NOW', current_time( 'timestamp' ) ) ){
1063
+ $this->pushmeta($pid, '_price', ($product_sale_price[$i] == "") ? '' : stripslashes( $product_sale_price[$i] ));
1064
  }
1065
 
1066
  if ( $date_to && strtotime( $date_to ) < strtotime( 'NOW', current_time( 'timestamp' ) ) ) {
1072
 
1073
  if (in_array( $product_type, array( 'simple', 'external' ) )) {
1074
 
1075
+ if ($import->options['is_multiple_grouping_product'] != 'yes'){
1076
+ if ($import->options['grouping_indicator'] == 'xpath' and ! is_numeric($product_grouping_parent[$i])){
1077
  $dpost = pmxi_findDuplicates(array(
1078
  'post_type' => 'product',
1079
  'ID' => $pid,
1085
  else
1086
  $product_grouping_parent[$i] = 0;
1087
  }
1088
+ elseif ($import->options['grouping_indicator'] != 'xpath'){
1089
  $dpost = pmxi_findDuplicates($articleData, $custom_grouping_indicator_name[$i], $custom_grouping_indicator_value[$i], 'custom field');
1090
  if (!empty($dpost))
1091
  $product_grouping_parent[$i] = array_shift($dpost);
1097
  if ( "" != $product_grouping_parent[$i] and absint($product_grouping_parent[$i]) > 0){
1098
 
1099
  $this->wpdb->update( $this->wpdb->posts, array('post_parent' => absint( $product_grouping_parent[$i] ) ), array('ID' => $pid));
1100
+
1101
+ $all_grouped_products = get_post_meta($product_grouping_parent[$i], '_children', true);
1102
+
1103
+ if (empty($all_grouped_products)) $all_grouped_products = array();
1104
+
1105
+ if ( ! in_array($pid, $all_grouped_products) ){
1106
+ $all_grouped_products[] = $pid;
1107
+ update_post_meta($product_grouping_parent[$i], '_children', $all_grouped_products);
1108
+ }
1109
  }
1110
  }
1111
 
1163
 
1164
  $stock_status = 'instock';
1165
 
1166
+ } elseif ( 'variable' === $product_type and ! $import->options['link_all_variations'] ) {
1167
 
1168
  // Stock status is always determined by children so sync later
1169
  // $stock_status = '';
1187
 
1188
  $current_manage_stock = get_post_meta( $pid, '_manage_stock', true );
1189
 
1190
+ if ( $product_manage_stock[$i] == 'yes' || ! $this->is_update_cf('_manage_stock') && $current_manage_stock == 'yes') {
1191
  $this->pushmeta( $pid, '_stock', wc_stock_amount( $product_stock_qty[$i] ) );
1192
  } else {
1193
  $this->pushmeta($pid, '_stock', '');
1198
  }
1199
 
1200
  // Upsells
1201
+ $this->import_linked_products($pid, $product_up_sells[$i], '_upsell_ids', $is_new_product);
1202
 
1203
  // Cross sells
1204
+ $this->import_linked_products($pid, $product_cross_sells[$i], '_crosssell_ids', $is_new_product);
1205
 
1206
  // Downloadable options
1207
  if ( $is_downloadable == 'yes' ) {
1218
  if ( !empty( $product_files[$i] ) ) {
1219
  $_file_paths = array();
1220
 
1221
+ $file_paths = explode( $import->options['product_files_delim'] , $product_files[$i] );
1222
+ $file_names = explode( $import->options['product_files_names_delim'] , $product_files_names[$i] );
1223
 
1224
  foreach ( $file_paths as $fn => $file_path ) {
1225
  $file_path = trim( $file_path );
1238
  if ( isset( $product_download_type[$i] ) )
1239
  $this->pushmeta($pid, '_download_type', esc_attr( $product_download_type[$i] ));
1240
 
1241
+ }
1242
 
1243
+ // Product url
1244
+ if ( $product_type == 'external' ) {
1245
+ if ( isset( $product_url[$i] ) && $product_url[$i] ){
1246
+ $this->auto_cloak_links($import, $product_url[$i]);
1247
+ $this->pushmeta($pid, '_product_url', esc_url_raw( $product_url[$i] ));
1248
+ }
1249
+ if ( isset( $product_button_text[$i] ) && $product_button_text[$i] ){
1250
+ $this->pushmeta($pid, '_button_text', esc_attr( $product_button_text[$i] ));
1251
+ }
1252
+ }
1253
+ // Update product visibility term WC 3.0.0
1254
  if ( version_compare(WOOCOMMERCE_VERSION, '3.0') >= 0 ) {
1255
+ if ( pmwi_is_update_taxonomy($articleData, $import->options, 'product_visibility') ){
1256
  $associate_terms = array();
1257
  if ($is_featured == "yes"){
1258
  $featured_term = get_term_by( 'name', 'featured', 'product_visibility' );
plugin.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: WP All Import - WooCommerce Add-On
4
  Plugin URI: http://www.wpallimport.com/
5
  Description: An extremely easy, drag & drop importer to import WooCommerce simple products. A paid upgrade is available for premium support and support for Variable, Grouped, and External/Affiliate products
6
- Version: 1.3.3
7
  Author: Soflyy
8
  */
9
  /**
@@ -24,7 +24,7 @@ define('PMWI_ROOT_URL', rtrim(plugin_dir_url(__FILE__), '/'));
24
  */
25
  define('PMWI_PREFIX', 'pmwi_');
26
 
27
- define('PMWI_FREE_VERSION', '1.3.3');
28
 
29
  define('PMWI_EDITION', 'free');
30
 
3
  Plugin Name: WP All Import - WooCommerce Add-On
4
  Plugin URI: http://www.wpallimport.com/
5
  Description: An extremely easy, drag & drop importer to import WooCommerce simple products. A paid upgrade is available for premium support and support for Variable, Grouped, and External/Affiliate products
6
+ Version: 1.3.4
7
  Author: Soflyy
8
  */
9
  /**
24
  */
25
  define('PMWI_PREFIX', 'pmwi_');
26
 
27
+ define('PMWI_FREE_VERSION', '1.3.4');
28
 
29
  define('PMWI_EDITION', 'free');
30
 
readme.txt CHANGED
@@ -1,8 +1,8 @@
1
  === Import Products from any XML or CSV to WooCommerce ===
2
  Contributors: soflyy, wpallimport
3
  Requires at least: 4.1
4
- Tested up to: 4.7.3
5
- Stable tag: 1.3.3
6
  License: GPLv2 or later
7
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
8
  Tags: woocommerce xml import, woocommerce csv import, woocommerce, import, xml, csv, wp all import, csv import, import csv, xml import, import xml, woocommerce csv importer, woocommerce xml importer, csv importer, csv import suite
@@ -83,6 +83,10 @@ The WooCommerce add-on will appear in the Step 4 of WP All Import.
83
 
84
  == Changelog ==
85
 
 
 
 
 
86
  = 1.3.3 =
87
  * improvement: compatibility with WC 3.x
88
 
1
  === Import Products from any XML or CSV to WooCommerce ===
2
  Contributors: soflyy, wpallimport
3
  Requires at least: 4.1
4
+ Tested up to: 4.7.5
5
+ Stable tag: 1.3.4
6
  License: GPLv2 or later
7
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
8
  Tags: woocommerce xml import, woocommerce csv import, woocommerce, import, xml, csv, wp all import, csv import, import csv, xml import, import xml, woocommerce csv importer, woocommerce xml importer, csv importer, csv import suite
83
 
84
  == Changelog ==
85
 
86
+ = 1.3.4 =
87
+ - bug fix: import product visibility WC 3.0
88
+ - bug fix: stock threshold
89
+
90
  = 1.3.3 =
91
  * improvement: compatibility with WC 3.x
92
 
views/admin/import/_tabs/_general.php CHANGED
@@ -254,13 +254,16 @@
254
  $tax_classes = array_filter( array_map( 'trim', explode( "\n", get_option( 'woocommerce_tax_classes' ) ) ) );
255
  $classes_options = array();
256
  $classes_options[''] = __( 'Standard', 'wpai_woocommerce_addon_plugin' );
257
- if ( $tax_classes )
258
- foreach ( $tax_classes as $class )
259
- $classes_options[ sanitize_title( $class ) ] = esc_html( $class );
 
 
 
260
  ?>
261
  <select class="select short" name="multiple_product_tax_class">
262
  <?php foreach ($classes_options as $key => $value):?>
263
- <option value="<?php echo $key; ?>" <?php echo $key == $post['multiple_product_tax_class'] ? 'selected="selected"': '' ?>><?php echo $value; ?></option>
264
  <?php endforeach; ?>
265
  </select>
266
  </span>
254
  $tax_classes = array_filter( array_map( 'trim', explode( "\n", get_option( 'woocommerce_tax_classes' ) ) ) );
255
  $classes_options = array();
256
  $classes_options[''] = __( 'Standard', 'wpai_woocommerce_addon_plugin' );
257
+
258
+ if ( $tax_classes ){
259
+ foreach ( $tax_classes as $class ){
260
+ $classes_options[ sanitize_title( $class ) ] = esc_html( $class );
261
+ }
262
+ }
263
  ?>
264
  <select class="select short" name="multiple_product_tax_class">
265
  <?php foreach ($classes_options as $key => $value):?>
266
+ <option value="<?php echo $key; ?>" <?php echo selected( esc_attr( $key ), esc_attr( $post['multiple_product_tax_class'] ), false ); ?>><?php echo $value; ?></option>
267
  <?php endforeach; ?>
268
  </select>
269
  </span>
views/admin/import/_tabs/_options.php CHANGED
@@ -6,13 +6,15 @@
6
  <div class="options_group">
7
 
8
  <p class="form-field"><?php _e('Import options','wpai_woocommerce_addon_plugin');?></p>
9
-
 
10
  <p class="form-field wpallimport-radio-field">
11
  <input type="hidden" name="missing_records_stock_status" value="0" />
12
  <input type="checkbox" id="missing_records_stock_status" name="missing_records_stock_status" value="1" <?php echo $post['missing_records_stock_status'] ? 'checked="checked"' : '' ?> />
13
  <label for="missing_records_stock_status"><?php _e('Set out of stock status for missing records', 'wpai_woocommerce_addon_plugin') ?></label>
14
  <a href="#help" class="wpallimport-help" title="<?php _e('Option to set the stock status to out of stock instead of deleting the product entirely. This option doesn\'t work when \'Delete missing records\' option is enabled.', 'wpai_woocommerce_addon_plugin') ?>" style="position:relative; top:-2px;">?</a>
15
  </p>
 
16
  <p class="form-field wpallimport-radio-field">
17
  <input type="hidden" name="disable_auto_sku_generation" value="0" />
18
  <input type="checkbox" id="disable_auto_sku_generation" name="disable_auto_sku_generation" value="1" <?php echo $post['disable_auto_sku_generation'] ? 'checked="checked"' : '' ?> />
6
  <div class="options_group">
7
 
8
  <p class="form-field"><?php _e('Import options','wpai_woocommerce_addon_plugin');?></p>
9
+
10
+ <?php if ( "new" == $post['wizard_type']): ?>
11
  <p class="form-field wpallimport-radio-field">
12
  <input type="hidden" name="missing_records_stock_status" value="0" />
13
  <input type="checkbox" id="missing_records_stock_status" name="missing_records_stock_status" value="1" <?php echo $post['missing_records_stock_status'] ? 'checked="checked"' : '' ?> />
14
  <label for="missing_records_stock_status"><?php _e('Set out of stock status for missing records', 'wpai_woocommerce_addon_plugin') ?></label>
15
  <a href="#help" class="wpallimport-help" title="<?php _e('Option to set the stock status to out of stock instead of deleting the product entirely. This option doesn\'t work when \'Delete missing records\' option is enabled.', 'wpai_woocommerce_addon_plugin') ?>" style="position:relative; top:-2px;">?</a>
16
  </p>
17
+ <?php endif; ?>
18
  <p class="form-field wpallimport-radio-field">
19
  <input type="hidden" name="disable_auto_sku_generation" value="0" />
20
  <input type="checkbox" id="disable_auto_sku_generation" name="disable_auto_sku_generation" value="1" <?php echo $post['disable_auto_sku_generation'] ? 'checked="checked"' : '' ?> />