Product Import Export for WooCommerce - Version 1.5.4

Version Description

  • Updates: Tested OK with WC 3.5.4
  • Bug Fix:- Importing hierarchical category
  • Content Update.
Download this release

Release Info

Developer webtoffee
Plugin Icon 128x128 Product Import Export for WooCommerce
Version 1.5.4
Comparing to
See all releases

Code changes from version 1.5.3 to 1.5.4

includes/class-wf-prodimpexpcsv-admin-screen.php CHANGED
@@ -40,8 +40,12 @@ class WF_ProdImpExpCsv_Admin_Screen {
40
  * Admin Scripts
41
  */
42
  public function admin_scripts() {
43
- wp_enqueue_style('woocommerce_admin_styles', WC()->plugin_url() . '/assets/css/admin.css');
44
- wp_enqueue_style('woocommerce-product-csv-importer', plugins_url(basename(plugin_dir_path(WF_ProdImpExpCsv_FILE)) . '/styles/wf-style.css', basename(__FILE__)), '', '1.4.4', 'screen');
 
 
 
 
45
  }
46
 
47
  /**
40
  * Admin Scripts
41
  */
42
  public function admin_scripts() {
43
+ $screen = get_current_screen();
44
+ $allowed_creen_id = array('product_page_wf_woocommerce_csv_im_ex');
45
+ if (in_array($screen->id, $allowed_creen_id)) {
46
+ wp_enqueue_style('woocommerce_admin_styles', WC()->plugin_url() . '/assets/css/admin.css');
47
+ wp_enqueue_style('woocommerce-product-csv-importer', plugins_url(basename(plugin_dir_path(WF_ProdImpExpCsv_FILE)) . '/styles/wf-style.css', basename(__FILE__)), '', '1.4.4', 'screen');
48
+ }
49
  }
50
 
51
  /**
includes/importer/class-wf-csv-parser.php CHANGED
@@ -4,210 +4,206 @@
4
  */
5
  class WF_CSV_Parser {
6
 
7
- var $row;
8
- var $post_type;
9
- var $reserved_fields; // Fields we map/handle (not custom fields)
10
- var $post_defaults; // Default post data
11
- var $postmeta_defaults; // default post meta
12
- var $postmeta_allowed; // post meta validation
13
- var $allowed_product_types; // Allowed product types
14
-
15
- /**
16
- * Constructor
17
- */
18
- public function __construct( $post_type = 'product' ) {
19
-
20
- $this->post_type = $post_type;
21
- $this->reserved_fields = include( 'data/data-wf-reserved-fields.php' );
22
- $this->post_defaults = include( 'data/data-wf-post-defaults.php' );
23
- $this->postmeta_defaults = include( 'data/data-wf-postmeta-defaults.php' );
24
- $this->postmeta_allowed = include( 'data/data-wf-postmeta-allowed.php' );
25
-
26
- $simple_term = get_term_by( 'slug', 'simple', 'product_type' );
27
- $variable_term = get_term_by( 'slug', 'variable', 'product_type' );
28
- $grouped_term = get_term_by( 'slug', 'grouped', 'product_type' );
29
- $external_term = get_term_by( 'slug', 'external', 'product_type' );
30
-
31
- $this->allowed_product_types = array(
32
- 'simple' => $simple_term->term_id,
33
- 'variable' => $variable_term->term_id,
34
- 'grouped' => $grouped_term->term_id,
35
- 'external' => $external_term->term_id
36
- );
37
-
38
- }
39
-
40
- /**
41
- * Format data from the csv file
42
- * @param string $data
43
- * @param string $enc
44
- * @return string
45
- */
46
- public function format_data_from_csv( $data, $enc ) {
47
- return ( $enc == 'UTF-8' ) ? $data : utf8_encode( $data );
48
- }
49
-
50
- /**
51
- * Parse the data
52
- * @param string $file [description]
53
- * @param string $delimiter [description]
54
- * @param array $mapping [description]
55
- * @param integer $start_pos [description]
56
- * @param integer $end_pos [description]
57
- * @return array
58
- */
59
- public function parse_data( $file, $delimiter, $mapping, $start_pos = 0, $end_pos = null, $eval_field ) {
60
- // Set locale
61
- $enc = mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
62
- if ( $enc )
63
- setlocale( LC_ALL, 'en_US.' . $enc );
64
- @ini_set( 'auto_detect_line_endings', true );
65
-
66
- $parsed_data = array();
67
- $raw_headers = array();
68
-
69
- // Put all CSV data into an associative array
70
- if ( ( $handle = fopen( $file, "r" ) ) !== FALSE ) {
71
-
72
- $header = fgetcsv( $handle, 0, $delimiter );
73
- if ( $start_pos != 0 )
74
- fseek( $handle, $start_pos );
75
-
76
- while ( ( $postmeta = fgetcsv( $handle, 0, $delimiter ) ) !== FALSE ) {
77
- $row = array();
78
-
79
- foreach ( $header as $key => $heading ) {
80
- // Heading is the lowercase version of the column name
81
- $s_heading = strtolower( $heading );
82
-
83
- // Check if this heading is being mapped to a different field
84
- if ( isset( $mapping[$s_heading] ) ) {
85
- if ( $mapping[$s_heading] == 'import_as_meta' ) {
86
-
87
- $s_heading = 'meta:' . $s_heading;
88
-
89
- } elseif ( $mapping[$s_heading] == 'import_as_images' ) {
90
-
91
- $s_heading = 'images';
92
-
93
- } else {
94
- $s_heading = esc_attr( $mapping[$s_heading] );
95
- }
96
- }
97
- if( !empty($mapping) )
98
- {
99
  foreach ($mapping as $mkey => $mvalue) {
100
- if(trim($mvalue) === trim($heading)){
101
- $s_heading = $mkey;
102
- }
103
  }
104
  }
105
 
106
- if ( $s_heading == '' )
107
- continue;
108
-
109
- // Add the heading to the parsed data
110
- $row[$s_heading] = ( isset( $postmeta[$key] ) ) ? $this->format_data_from_csv( $postmeta[$key], $enc ) : '';
111
-
112
- if(!empty($eval_field[strtolower( $heading )]))
113
- $row[$s_heading] = $this->evaluate_field($row[$s_heading], $eval_field[strtolower( $heading )]);
114
-
115
- // Raw Headers stores the actual column name in the CSV
116
- $raw_headers[ $s_heading ] = $heading;
117
- }
118
- $parsed_data[] = $row;
119
-
120
- unset( $postmeta, $row );
121
-
122
- $position = ftell( $handle );
123
-
124
- if ( $end_pos && $position >= $end_pos )
125
- break;
126
- }
127
- fclose( $handle );
128
- }
129
- return array( $parsed_data, $raw_headers, $position );
130
- }
131
-
132
- private function evaluate_field($value, $evaluation_field){
133
-
134
- $processed_value = $value;
135
- if(!empty($evaluation_field)){
136
- $operator = substr($evaluation_field, 0, 1);
137
- if(in_array($operator, array('=', '+', '-', '*', '/', '&'))){
138
- $eval_val = substr($evaluation_field, 1);
139
-
140
- switch($operator){
141
- case '=':
142
- $processed_value = trim($eval_val);
143
- break;
144
- case '+':
145
- $processed_value = $value + $eval_val;
146
- break;
147
- case '-':
148
- $processed_value = $value - $eval_val;
149
- break;
150
- case '*':
151
- $processed_value = $value * $eval_val;
152
- break;
153
- case '/':
154
- $processed_value = $value / $eval_val;
155
- break;
156
- case '&':
157
- if (strpos($eval_val, '[VAL]') !== false) {
158
- $processed_value = str_replace('[VAL]',$value,$eval_val);
159
- }
160
- else{
161
- $processed_value = $value . $eval_val;
162
- }
163
- break;
164
- }
165
- }
166
- }
167
- return $processed_value;
168
- }
169
-
170
- /**
171
- * Parse product
172
- * @param array $item
173
- * @param integer $merge_empty_cells
174
- * @return array
175
- */
176
- public function parse_product( $item, $merge_empty_cells = 0 ) {
177
- global $WF_CSV_Product_Import, $wpdb;
178
- $this->row++;
179
-
180
- $terms_array = $postmeta = $product = array();
181
- $attributes = $default_attributes = $gpf_data = null;
182
-
183
- // Merging
184
- $merging = ( ! empty( $_GET['merge'] ) && $_GET['merge'] ) ? 1 : 0;
185
- //if($item['post_parent']!== '' && $item['parent_sku'] !== ''){
186
-
187
- $this->post_defaults['post_type'] = 'product';
188
- $this->post_type = 'product';
189
- // Post ID field mapping
190
- $post_id = ( ! empty( $item['id'] ) ) ? $item['id'] : 0;
191
- $post_id = ( ! empty( $item['post_id'] ) ) ? $item['post_id'] : $post_id;
192
- if ( $merging ) {
193
-
194
- $product['merging'] = true;
195
-
196
-
197
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> Row %s - preparing for merge.', 'wf_csv_import_export'), $this->row ) );
198
-
199
- // Required fields
200
- if ( ! $post_id && empty( $item['sku'] ) ) {
201
-
202
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Cannot merge without id or sku. Importing instead.', 'wf_csv_import_export') );
203
-
204
- $merging = false;
205
- } else {
206
-
207
- // Check product exists
208
- if ( ! $post_id ) {
209
- // Check product to merge exists
210
- $db_query = $wpdb->prepare("
211
  SELECT $wpdb->posts.ID
212
  FROM $wpdb->posts
213
  LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
@@ -215,642 +211,612 @@ class WF_CSV_Parser {
215
  AND $wpdb->posts.post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )
216
  AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s'
217
  ", $item['sku']);
218
- $found_product_id = $wpdb->get_var($db_query);
219
- if ( ! $found_product_id ) {
220
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf(__( '> > Skipped. Cannot find product with sku %s. Importing instead.', 'wf_csv_import_export'), $item['sku']) );
221
- $merging = false;
222
-
223
- } else {
224
-
225
- $post_id = $found_product_id;
226
-
227
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf(__( '> > Found product with ID %s.', 'wf_csv_import_export'), $post_id) );
228
-
229
- }
230
- }
231
-
232
- }
233
- }
234
-
235
- if ( ! $merging ) {
236
-
237
- $product['merging'] = false;
238
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> Row %s - preparing for import.', 'wf_csv_import_export'), $this->row ) );
239
-
240
- // Required fields
241
- if ( isset($item['post_parent']) && $item['post_parent']=== '' && $item['post_title']=== '') {
242
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Skipped. No post_title set for new product.', 'wf_csv_import_export') );
243
- return new WP_Error( 'parse-error', __( 'No post_title set for new product.', 'wf_csv_import_export' ) );
244
- }
245
- if ( !empty($item['post_parent']) && $item['post_parent']!== '' && $item['post_parent']!== null && $item['parent_sku'] === '' ) {
246
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', __( '> > Skipped. No parent set for new variation product.', 'wf_csv_import_export') );
247
- //return new WP_Error( 'parse-error', __( 'No post_title set for new product.', 'wf_csv_import_export' ) );
248
- return new WP_Error( 'parse-error', __( 'No parent set for new variation product.', 'wf_csv_import_export' ) );
249
- }
250
-
251
- }
252
-
253
- $product['post_id'] = $post_id;
254
-
255
-
256
- // Get post fields
257
- foreach ( $this->post_defaults as $column => $default ) {
258
- if ( isset( $item[ $column ] ) ) $product[ $column ] = $item[ $column ];
259
- }
260
-
261
- // Get custom fields
262
- foreach ( $this->postmeta_defaults as $column => $default ) {
263
- if ( isset( $item[$column] ) )
264
- $postmeta[$column] = (string) $item[$column];
265
- elseif ( isset( $item['_' . $column] ) )
266
- $postmeta[$column] = (string) $item['_' . $column];
267
-
268
- // Check custom fields are valid
269
- if ( isset( $postmeta[$column] ) && isset( $this->postmeta_allowed[$column] ) && ! in_array( $postmeta[$column], $this->postmeta_allowed[$column] ) ) {
270
- $postmeta[$column] = $this->postmeta_defaults[$column];
271
- }
272
- }
273
-
274
- if ( ! $merging ) {
275
- // Merge post meta with defaults
276
- $product = wp_parse_args( $product, $this->post_defaults );
277
- $postmeta = wp_parse_args( $postmeta, $this->postmeta_defaults );
278
- }
279
-
280
- // Handle special meta fields
281
- // price
282
- if ( $merging ) {
283
- if ( ! isset( $postmeta['regular_price'] ) )
284
- $postmeta['regular_price'] = get_post_meta( $post_id, '_regular_price', true );
285
- $postmeta['regular_price'] = $this->hf_currency_formatter($postmeta['regular_price']);
286
- if ( ! isset( $postmeta['sale_price'] ) )
287
- $postmeta['sale_price'] = get_post_meta( $post_id, '_sale_price', true );
288
- $postmeta['sale_price'] = $this->hf_currency_formatter($postmeta['sale_price']);
289
- }
290
-
291
- if ( isset( $postmeta['regular_price'] ) && isset( $postmeta['sale_price'] ) && $postmeta['sale_price'] !== '' ) {
292
- $postmeta['sale_price'] = $this->hf_currency_formatter($postmeta['sale_price']);
293
- $postmeta['regular_price'] = $this->hf_currency_formatter($postmeta['regular_price']);
294
- $price = min( $postmeta['sale_price'], $postmeta['regular_price']);
295
- $postmeta['price'] = $price;
296
- } elseif ( isset( $postmeta['regular_price'] ) ) {
297
- $postmeta['price'] = $this->hf_currency_formatter($postmeta['regular_price']);
298
- }
299
-
300
- // Reset dynamically generated meta
301
- if ( !isset($item['post_parent']) ) {
302
- $postmeta['min_variation_price'] = $postmeta['max_variation_price'] = $postmeta['min_variation_regular_price'] =$postmeta['max_variation_regular_price'] = $postmeta['min_variation_sale_price'] = $postmeta['max_variation_sale_price'] = '';
303
- }
304
-
305
- // upsells
306
- if ( isset( $postmeta['upsell_ids'] ) && ! is_array( $postmeta['upsell_ids'] ) ) {
307
- $ids = array_filter( array_map( 'trim', explode( '|', $postmeta['upsell_ids'] ) ) );
308
- $postmeta['upsell_ids'] = $ids;
309
- }
310
-
311
- // crosssells
312
- if ( isset( $postmeta['crosssell_ids'] ) && ! is_array( $postmeta['crosssell_ids'] ) ) {
313
- $ids = array_filter( array_map( 'trim', explode( '|', $postmeta['crosssell_ids'] ) ) );
314
- $postmeta['crosssell_ids'] = $ids;
315
- }
316
-
317
- // Sale dates
318
- if ( isset( $postmeta['sale_price_dates_from'] ) ) {
319
- $postmeta['sale_price_dates_from'] = empty( $postmeta['sale_price_dates_from'] ) ? '' : strtotime( $postmeta['sale_price_dates_from'] );
320
- }
321
-
322
- if ( isset( $postmeta['sale_price_dates_to'] ) ) {
323
- $postmeta['sale_price_dates_to'] = empty( $postmeta['sale_price_dates_to'] ) ? '' : strtotime( $postmeta['sale_price_dates_to'] );
324
- }
325
-
326
- // Relative stock updates
327
- if ( $merging ) {
328
- if ( isset( $postmeta['stock'] ) ) {
329
-
330
- $postmeta['stock'] = trim( $postmeta['stock'] );
331
-
332
- $mode = substr( $postmeta['stock'], 0, 3 );
333
-
334
- if ( $mode == '(+)' ) {
335
- $old_stock = absint( get_post_meta( $post_id, '_stock', true ) );
336
- $amount = absint( substr( $postmeta['stock'], 3 ) );
337
- $new_stock = $old_stock + $amount;
338
- $postmeta['stock'] = $new_stock;
339
- }
340
-
341
- if ( $mode == '(-)' ) {
342
- $old_stock = absint( get_post_meta( $post_id, '_stock', true ) );
343
- $amount = absint( substr( $postmeta['stock'], 3 ) );
344
- $new_stock = $old_stock - $amount;
345
- $postmeta['stock'] = $new_stock;
346
- }
347
- }
348
- }
349
-
350
- // Format post status
351
- if ( ! empty( $product['post_status'] ) ) {
352
- $product['post_status'] = strtolower( $product['post_status'] );
353
-
354
- if ( empty($item['post_parent']) ) {
355
- if ( ! in_array( $product['post_status'], array( 'publish', 'private', 'draft', 'pending', 'future', 'inherit', 'trash' ) ) ) {
356
- $product['post_status'] = 'publish';
357
- }
358
- } else {
359
- if ( ! in_array( $product['post_status'], array( 'private', 'publish' ) ) ) {
360
- $product['post_status'] = 'publish';
361
- }
362
- }
363
- }
364
-
365
- // Put set core product postmeta into product array
366
- foreach ( $postmeta as $key => $value ) {
367
- $product['postmeta'][] = array( 'key' => '_' . esc_attr($key), 'value' => $value );
368
- }
369
-
370
- /**
371
- * Handle other columns
372
- */
373
- foreach ( $item as $key => $value ) {
374
-
375
- if ( empty($item['post_parent']) && ! $merge_empty_cells && $value == "" )
376
- continue;
377
-
378
- /**
379
- * File path handling
380
- */
381
- if ( $key == 'file_paths' || $key == 'downloadable_files' ) {
382
-
383
- $file_paths = explode( '|', $value );
384
- $_file_paths = array();
385
- foreach ( $file_paths as $file_path ) {
386
- // 2.1
387
- if ( function_exists( 'wc_get_filename_from_url' ) ) {
388
- $file_path = array_map( 'trim', explode( '::', $file_path ) );
389
- if ( sizeof( $file_path ) === 2 ) {
390
- $file_name = $file_path[0];
391
- $file_path = $file_path[1];
392
- } else {
393
- $file_name = wc_get_filename_from_url( $file_path[0] );
394
- $file_path = $file_path[0];
395
- }
396
- $_file_paths[ md5( $file_path ) ] = array(
397
- 'name' => $file_name,
398
- 'file' => $file_path
399
- );
400
- } else {
401
- $file_path = trim( $file_path );
402
- $_file_paths[ md5( $file_path ) ] = $file_path;
403
- }
404
- }
405
- $value = $_file_paths;
406
-
407
- $product['postmeta'][] = array( 'key' => '_' . esc_attr( $key ), 'value' => $value );
408
- }
409
-
410
- elseif ( strstr( $key, 'tax:' ) ) {
411
-
412
- // Get taxonomy
413
- $taxonomy = trim( str_replace( 'tax:', '', $key ) );
414
-
415
- // Exists?
416
- if ( ! taxonomy_exists( $taxonomy ) ) {
417
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> > Skipping taxonomy "%s" - it does not exist.', 'wf_csv_import_export'), $taxonomy ) );
418
- continue;
419
- }
420
-
421
- // Product type check
422
- if ( $taxonomy == 'product_type' ) {
423
- $term = strtolower(trim($value));
424
-
425
- if ( ! array_key_exists( $term, $this->allowed_product_types ) ) {
426
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> > > Product type "%s" not allowed - using simple.', 'wf_csv_import_export'), $term ) );
427
- $term_id = $this->allowed_product_types['simple'];
428
- } else {
429
- $term_id = $this->allowed_product_types[ $term ];
430
- }
431
-
432
- // Add to array
433
- $terms_array[] = array(
434
- 'taxonomy' => $taxonomy,
435
- 'terms' => array( $term_id )
436
- );
437
-
438
- continue;
439
- }
440
-
441
- // Get terms - ID => parent
442
- $terms = array();
443
- $raw_terms = explode( '|', $value );
444
- $raw_terms = array_map( 'trim', $raw_terms );
445
-
446
- // Handle term hierachy (>)
447
- foreach ( $raw_terms as $raw_term ) {
448
-
449
- if ( strstr( $raw_term, '>' ) ) {
450
-
451
- $raw_term = explode( '>', $raw_term );
452
- $raw_term = array_map( 'trim', $raw_term );
453
-
454
- if(WC()->version < '2.7.0')
455
- {
456
- $raw_term = array_map( 'wp_specialchars', $raw_term );
457
- $raw_term = array_filter( $raw_term );
458
-
459
- }
460
- else
461
- {
462
- $raw_term = array_map( 'esc_html', $raw_term );
463
- $raw_term = array_filter( $raw_term );
464
 
465
- }
466
-
467
- $parent = 0;
468
- $loop = 0;
469
 
470
- foreach ( $raw_term as $term ) {
471
- $loop ++;
472
- $term_id = '';
473
-
474
- if ( isset( $this->inserted_terms[ $taxonomy ][ $parent ][ $term ] ) ) {
475
- $term_id = $this->inserted_terms[ $taxonomy ][ $parent ][ $term ];
476
- } elseif ( $term ) {
477
-
478
- /**
479
- * Check term existance
480
- */
481
- $term_may_exist = term_exists( $term, $taxonomy, absint( $parent ) );
482
-
483
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __( '> > (' . __LINE__ . ') Term %s (%s) exists? %s', 'wf_csv_import_export' ), sanitize_text_field( $term ), esc_html( $taxonomy ), $term_may_exist ? print_r( $term_may_exist, true ) : '-' ) );
484
-
485
- if ( is_array( $term_may_exist ) ) {
486
- $possible_term = get_term( $term_may_exist['term_id'], 'product_cat' );
487
 
488
- if (!empty($possible_term) && $possible_term->parent == $parent ) {
489
- $term_id = $term_may_exist['term_id'];
490
- }
491
- }
 
 
492
 
493
- if ( ! $term_id ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
494
 
495
- // Create appropriate slug
496
- $slug = array();
497
 
498
- for ( $i = 0; $i < $loop; $i ++ )
499
- $slug[] = $raw_term[ $i ];
500
 
501
- $slug = sanitize_title( implode( '-', $slug ) );
 
 
 
 
 
 
 
 
 
502
 
503
- $t = wp_insert_term( $term, $taxonomy, array( 'parent' => $parent, 'slug' => $slug ) );
 
504
 
505
- if ( ! is_wp_error( $t ) ) {
506
- $term_id = $t['term_id'];
507
- } else {
508
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __( '> > (' . __LINE__ . ') Failed to import term %s, parent %s - %s', 'wf_csv_import_export' ), sanitize_text_field( $term ), sanitize_text_field( $parent ), sanitize_text_field( $taxonomy ) ) );
509
- break;
510
- }
511
- }
512
 
513
- $this->inserted_terms[$taxonomy][$parent][$term] = $term_id;
 
 
514
 
515
- }
 
516
 
517
- if ( ! $term_id )
518
- break;
519
 
520
- // Add to product terms, ready to set if this is the final term
521
- if ( sizeof( $raw_term ) == $loop )
522
- $terms[] = $term_id;
523
 
524
- $parent = $term_id;
525
- }
 
526
 
527
- } else {
 
528
 
529
- $term_id = '';
530
- $raw_term = (WC()->version < '2.7.0') ? wp_specialchars( $raw_term ) : esc_html( $raw_term );
 
 
 
 
 
531
 
532
- if ( isset( $this->inserted_terms[$taxonomy][0][$raw_term] ) ) {
 
 
 
 
 
 
 
533
 
534
- $term_id = $this->inserted_terms[$taxonomy][0][$raw_term];
 
 
535
 
536
- } elseif ( $raw_term ) {
 
 
 
 
 
537
 
538
- // Check term existance
539
- $term_exists = term_exists( $raw_term, $taxonomy, 0 );
540
- $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : 0;
 
541
 
542
- if ( ! $term_id ) {
543
- $t = wp_insert_term( trim( $raw_term ), $taxonomy, array( 'parent' => 0 ) );
544
 
545
- if ( ! is_wp_error( $t ) ) {
546
- $term_id = $t['term_id'];
547
- } else {
548
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __( '> > Failed to import term %s %s', 'wf_csv_import_export' ), esc_html($raw_term), esc_html($taxonomy) ) );
549
- break;
550
- }
551
- }
552
 
553
- $this->inserted_terms[$taxonomy][0][$raw_term] = $term_id;
 
554
 
555
- }
556
 
557
- // Store terms for later insertion
558
- if ( $term_id )
559
- $terms[] = $term_id;
560
 
561
- }
562
 
563
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
564
 
565
- // Any defined?
566
- if ( sizeof( $terms ) == 0 )
567
- continue;
 
 
 
 
568
 
569
- // Add to array
570
- $terms_array[] = array(
571
- 'taxonomy' => $taxonomy,
572
- 'terms' => $terms
573
- );
574
- }
575
 
576
- /**
577
- * Handle Attributes
578
- */
579
- elseif ( strstr( $key, 'attribute:' ) ) {
580
 
581
- $attribute_key = sanitize_title( trim( str_replace( 'attribute:', '', $key ) ) );
582
- $attribute_name = str_replace( 'attribute:', '', $WF_CSV_Product_Import->raw_headers[ $key ] );
583
 
584
- if ( ! $attribute_key )
585
- continue;
 
586
 
587
- // Taxonomy
588
- if ( substr( $attribute_key, 0, 3 ) == 'pa_' ) {
 
589
 
590
- $taxonomy = $attribute_key;
 
591
 
592
- // Exists?
593
- if ( ! taxonomy_exists( $taxonomy ) ) {
594
-
595
 
596
- $nicename = strtolower( sanitize_title( str_replace( 'pa_', '', $taxonomy ) ) );
597
-
598
- $attribute_label = ucwords(str_replace('-',' ',$nicename)); // for importing attribute name as human readable string
599
-
600
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> > Attribute taxonomy "%s" does not exist. Adding it. Nicename: %s', 'wf_csv_import_export'), $taxonomy, $nicename ) );
 
 
 
601
 
602
- $exists_in_db = $wpdb->get_var( "SELECT attribute_id FROM " . $wpdb->prefix . "woocommerce_attribute_taxonomies WHERE attribute_name = '" . $nicename . "';" );
 
 
 
 
603
 
604
- if ( ! $exists_in_db ) {
605
- // Create the taxonomy
606
- $wpdb->insert( $wpdb->prefix . "woocommerce_attribute_taxonomies", array( 'attribute_name' => $nicename, 'attribute_label' => $attribute_label, 'attribute_type' => 'select', 'attribute_orderby' => 'menu_order' ) );
607
- } else {
608
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __('> > Attribute taxonomy %s already exists in DB.', 'wf_csv_import_export'), $taxonomy ) );
609
- }
 
 
 
 
 
 
610
 
611
- // Register the taxonomy now so that the import works!
612
- register_taxonomy( $taxonomy,
613
- array( 'product', 'product_variation' ),
614
- array(
615
- 'hierarchical' => true,
616
- 'show_ui' => false,
617
- 'query_var' => true,
618
- 'rewrite' => false,
619
- )
620
- );
621
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
622
 
623
- // Get terms
624
- $terms = array();
625
- $raw_terms = explode( '|', $value );
626
- if(WC()->version < '2.7.0')
627
- {
628
- $raw_terms = array_map( 'wp_specialchars', $raw_terms );
629
- $raw_terms = array_map( 'trim', $raw_terms );
630
-
631
- }else{
632
-
633
- $raw_terms = array_map( 'esc_html', $raw_terms );
634
- $raw_terms = array_map( 'trim', $raw_terms );
635
-
636
- }
637
-
638
- if ( sizeof( $raw_terms ) > 0 ) {
639
-
640
- foreach ( $raw_terms as $raw_term ) {
641
-
642
- if ( empty( $raw_term ) && 0 != $raw_term ) {
643
- continue;
644
- }
645
-
646
- // Check term existance
647
- $term_exists = term_exists( $raw_term, $taxonomy, 0 );
648
- $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : 0;
649
-
650
- if ( ! $term_id ) {
651
- $t = wp_insert_term( trim( $raw_term ), $taxonomy );
652
-
653
- if ( ! is_wp_error( $t ) ) {
654
- $term_id = $t['term_id'];
655
-
656
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __( '> > Inserted Raw Term %s ID = %s', 'wf_csv_import_export' ), esc_html( $raw_term ), $term_id ) );
657
- } else {
658
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __( '> > Failed to import term %s %s', 'wf_csv_import_export' ), esc_html($raw_term), esc_html($taxonomy) ) );
659
- break;
660
- }
661
- } else {
662
- $WF_CSV_Product_Import->hf_log_data_change( 'csv-import', sprintf( __( '> > Raw Term %s ID = %s', 'wf_csv_import_export' ), esc_html( $raw_term ), $term_id ) );
663
- }
664
-
665
- if ( $term_id ) {
666
- $terms[] = $term_id;
667
- }
668
- }
669
-
670
- }
671
-
672
- // Add to array
673
- $terms_array[] = array(
674
- 'taxonomy' => $taxonomy,
675
- 'terms' => $terms
676
- );
677
-
678
- // Ensure we have original attributes
679
- if ( is_null( $attributes ) && $merging ) {
680
- $attributes = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_product_attributes', true ) ) );
681
- } elseif ( is_null( $attributes ) ) {
682
- $attributes = array();
683
- }
684
-
685
- // Set attribute
686
- if ( ! isset( $attributes[$taxonomy] ) )
687
- $attributes[$taxonomy] = array();
688
-
689
- $attributes[$taxonomy]['name'] = $taxonomy;
690
- $attributes[$taxonomy]['value'] = null;
691
- $attributes[$taxonomy]['is_taxonomy'] = 1;
692
-
693
- if ( ! isset( $attributes[$taxonomy]['position'] ) )
694
- $attributes[$taxonomy]['position'] = 0;
695
- if ( ! isset( $attributes[$taxonomy]['is_visible'] ) )
696
- $attributes[$taxonomy]['is_visible'] = 1;
697
- if ( ! isset( $attributes[$taxonomy]['is_variation'] ) )
698
- $attributes[$taxonomy]['is_variation'] = 0;
699
-
700
- } else {
701
-
702
- if ( ! $value || ! $attribute_key ) continue;
703
-
704
- // Set attribute
705
- if ( ! isset( $attributes[$attribute_key] ) )
706
- $attributes[$attribute_key] = array();
707
-
708
- $attributes[$attribute_key]['name'] = $attribute_name;
709
- $attributes[$attribute_key]['value'] = $value;
710
- $attributes[$attribute_key]['is_taxonomy'] = 0;
711
-
712
- if ( ! isset( $attributes[$attribute_key]['position'] ) )
713
- $attributes[$attribute_key]['position'] = 0;
714
- if ( ! isset( $attributes[$attribute_key]['is_visible'] ) )
715
- $attributes[$attribute_key]['is_visible'] = 1;
716
- if ( ! isset( $attributes[$attribute_key]['is_variation'] ) )
717
- $attributes[$attribute_key]['is_variation'] = 0;
718
- }
719
-
720
- }
721
-
722
- /**
723
- * Handle Attributes Data - position|is_visible|is_variation
724
- */
725
- elseif ( strstr( $key, 'attribute_data:' ) ) {
726
-
727
- $attribute_key = sanitize_title( trim( str_replace( 'attribute_data:', '', $key ) ) );
728
-
729
- if ( ! $attribute_key ) {
730
- continue;
731
- }
732
-
733
- $values = explode( '|', $value );
734
- $position = isset( $values[0] ) ? (int) $values[0] : 0;
735
- $visible = isset( $values[1] ) ? (int) $values[1] : 1;
736
- $variation = isset( $values[2] ) ? (int) $values[2] : 0;
737
-
738
- // Ensure we have original attributes
739
- if ( ! isset( $attributes[ $attribute_key ] ) ) {
740
- if ( $merging ) {
741
- $existing_attributes = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_product_attributes', true ) ) );
742
- $attributes[ $attribute_key ] = isset( $existing_attributes[ $attribute_key ] ) ? $existing_attributes[ $attribute_key ] : array();
743
- } else {
744
- $attributes[ $attribute_key ] = array();
745
- }
746
- }
747
-
748
- $attributes[ $attribute_key ]['position'] = $position;
749
- $attributes[ $attribute_key ]['is_visible'] = $visible;
750
- $attributes[ $attribute_key ]['is_variation'] = $variation;
751
- }
752
-
753
- /**
754
- * Handle Attributes Default Values
755
- */
756
- elseif ( strstr( $key, 'attribute_default:' ) ) {
757
-
758
- $attribute_key = sanitize_title( trim( str_replace( 'attribute_default:', '', $key ) ) );
759
-
760
- if ( ! $attribute_key ) continue;
761
-
762
- // Ensure we have original attributes
763
- if ( is_null( $default_attributes ) && $merging ) {
764
- $default_attributes = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_default_attributes', true ) ) );
765
- } elseif ( is_null( $default_attributes ) ) {
766
- $default_attributes = array();
767
- }
768
-
769
- $default_attributes[ $attribute_key ] = $value;
770
- }
771
-
772
- /**
773
- * Handle gpf: google product feed columns
774
- */
775
- elseif ( strstr( $key, 'gpf:' ) ) {
776
-
777
- $gpf_key = trim( str_replace( 'gpf:', '', $key ) );
778
-
779
- // Get original values
780
- if ( is_null( $gpf_data ) && $merging ) {
781
- $gpf_data = array_filter( (array) maybe_unserialize( get_post_meta( $post_id, '_woocommerce_gpf_data', true ) ) );
782
- } elseif ( is_null( $gpf_data ) ) {
783
- $gpf_data = array(
784
- 'availability' => '',
785
- 'condition' => '',
786
- 'brand' => '',
787
- 'product_type' => '',
788
- 'google_product_category' => '',
789
- 'gtin' => '',
790
- 'mpn' => '',
791
- 'gender' => '',
792
- 'age_group' => '',
793
- 'color' => '',
794
- 'size' => ''
795
- );
796
- }
797
-
798
- $gpf_data[$gpf_key] = $value;
799
-
800
- }
801
-
802
- /**
803
- * Handle upsell SKUs which we cannot assign until we get IDs later on
804
- */
805
- elseif ( strstr( $key, 'upsell_skus' ) ) {
806
- if ( $value ) {
807
- $skus = array_filter( array_map( 'trim', explode( '|', $value ) ) );
808
- $product['upsell_skus'] = $skus;
809
- }
810
- }
811
-
812
- /**
813
- * Handle crosssells SKUs which we cannot assign until we get IDs later on
814
- */
815
- elseif ( strstr( $key, 'crosssell_skus' ) ) {
816
- if ( $value ) {
817
- $skus = array_filter( array_map( 'trim', explode( '|', $value ) ) );
818
- $product['crosssell_skus'] = $skus;
819
- }
820
- }
821
-
822
- }
823
-
824
- // Remove empty attribues
825
- if(!empty($attributes))
826
- foreach ( $attributes as $key => $value ) {
827
- if ( ! isset($value['name']) ) unset( $attributes[$key] );
828
- }
829
-
830
- /**
831
- * Handle images
832
- */
833
- if ( ! empty( $item['images'] ) ) {
834
- $images = array_map( 'trim', explode( '|', $item['images'] ) );
835
- } else {
836
- $images = '';
837
- }
838
-
839
- $product['postmeta'][] = array( 'key' => '_default_attributes', 'value' => $default_attributes );
840
- $product['attributes'] = $attributes;
841
- $product['gpf_data'] = $gpf_data;
842
- $product['images'] = $images;
843
- $product['terms'] = $terms_array;
844
- $product['sku'] = ( ! empty( $item['sku'] ) ) ? $item['sku'] : '';
845
- $product['post_title'] = ( ! empty( $item['post_title'] ) ) ? $item['post_title'] : '';
846
- $product['post_type'] = $this->post_type;
847
- unset( $item, $terms_array, $postmeta, $attributes, $gpf_data, $images );
848
-
849
- return $product;
850
- }
851
- public function hf_currency_formatter($price){
852
-
853
- $decimal_seperator = wc_get_price_decimal_separator();
854
- return preg_replace("[^0-9\\'.$decimal_seperator.']", "", $price);
855
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
856
  }
4
  */
5
  class WF_CSV_Parser {
6
 
7
+ var $row;
8
+ var $post_type;
9
+ var $reserved_fields; // Fields we map/handle (not custom fields)
10
+ var $post_defaults; // Default post data
11
+ var $postmeta_defaults; // default post meta
12
+ var $postmeta_allowed; // post meta validation
13
+ var $allowed_product_types; // Allowed product types
14
+
15
+ /**
16
+ * Constructor
17
+ */
18
+
19
+ public function __construct($post_type = 'product') {
20
+
21
+ $this->post_type = $post_type;
22
+ $this->reserved_fields = include( 'data/data-wf-reserved-fields.php' );
23
+ $this->post_defaults = include( 'data/data-wf-post-defaults.php' );
24
+ $this->postmeta_defaults = include( 'data/data-wf-postmeta-defaults.php' );
25
+ $this->postmeta_allowed = include( 'data/data-wf-postmeta-allowed.php' );
26
+
27
+ $simple_term = get_term_by('slug', 'simple', 'product_type');
28
+ $variable_term = get_term_by('slug', 'variable', 'product_type');
29
+ $grouped_term = get_term_by('slug', 'grouped', 'product_type');
30
+ $external_term = get_term_by('slug', 'external', 'product_type');
31
+
32
+ $this->allowed_product_types = array(
33
+ 'simple' => $simple_term->term_id,
34
+ 'variable' => $variable_term->term_id,
35
+ 'grouped' => $grouped_term->term_id,
36
+ 'external' => $external_term->term_id
37
+ );
38
+ }
39
+
40
+ /**
41
+ * Format data from the csv file
42
+ * @param string $data
43
+ * @param string $enc
44
+ * @return string
45
+ */
46
+ public function format_data_from_csv($data, $enc) {
47
+ return ( $enc == 'UTF-8' ) ? $data : utf8_encode($data);
48
+ }
49
+
50
+ /**
51
+ * Parse the data
52
+ * @param string $file [description]
53
+ * @param string $delimiter [description]
54
+ * @param array $mapping [description]
55
+ * @param integer $start_pos [description]
56
+ * @param integer $end_pos [description]
57
+ * @return array
58
+ */
59
+ public function parse_data($file, $delimiter, $mapping, $start_pos = 0, $end_pos = null, $eval_field) {
60
+ // Set locale
61
+ $enc = mb_detect_encoding($file, 'UTF-8, ISO-8859-1', true);
62
+ if ($enc)
63
+ setlocale(LC_ALL, 'en_US.' . $enc);
64
+ @ini_set('auto_detect_line_endings', true);
65
+
66
+ $parsed_data = array();
67
+ $raw_headers = array();
68
+
69
+ // Put all CSV data into an associative array
70
+ if (( $handle = fopen($file, "r") ) !== FALSE) {
71
+
72
+ $header = fgetcsv($handle, 0, $delimiter);
73
+ if ($start_pos != 0)
74
+ fseek($handle, $start_pos);
75
+
76
+ while (( $postmeta = fgetcsv($handle, 0, $delimiter) ) !== FALSE) {
77
+ $row = array();
78
+
79
+ foreach ($header as $key => $heading) {
80
+ // Heading is the lowercase version of the column name
81
+ $s_heading = strtolower($heading);
82
+
83
+ // Check if this heading is being mapped to a different field
84
+ if (isset($mapping[$s_heading])) {
85
+ if ($mapping[$s_heading] == 'import_as_meta') {
86
+
87
+ $s_heading = 'meta:' . $s_heading;
88
+ } elseif ($mapping[$s_heading] == 'import_as_images') {
89
+
90
+ $s_heading = 'images';
91
+ } else {
92
+ $s_heading = esc_attr($mapping[$s_heading]);
93
+ }
94
+ }
95
+ if (!empty($mapping)) {
 
 
 
96
  foreach ($mapping as $mkey => $mvalue) {
97
+ if (trim($mvalue) === trim($heading)) {
98
+ $s_heading = $mkey;
99
+ }
100
  }
101
  }
102
 
103
+ if ($s_heading == '')
104
+ continue;
105
+
106
+ // Add the heading to the parsed data
107
+ $row[$s_heading] = ( isset($postmeta[$key]) ) ? $this->format_data_from_csv($postmeta[$key], $enc) : '';
108
+
109
+ if (!empty($eval_field[strtolower($heading)]))
110
+ $row[$s_heading] = $this->evaluate_field($row[$s_heading], $eval_field[strtolower($heading)]);
111
+
112
+ // Raw Headers stores the actual column name in the CSV
113
+ $raw_headers[$s_heading] = $heading;
114
+ }
115
+ $parsed_data[] = $row;
116
+
117
+ unset($postmeta, $row);
118
+
119
+ $position = ftell($handle);
120
+
121
+ if ($end_pos && $position >= $end_pos)
122
+ break;
123
+ }
124
+ fclose($handle);
125
+ }
126
+ return array($parsed_data, $raw_headers, $position);
127
+ }
128
+
129
+ private function evaluate_field($value, $evaluation_field) {
130
+
131
+ $processed_value = $value;
132
+ if (!empty($evaluation_field)) {
133
+ $operator = substr($evaluation_field, 0, 1);
134
+ if (in_array($operator, array('=', '+', '-', '*', '/', '&'))) {
135
+ $eval_val = substr($evaluation_field, 1);
136
+
137
+ switch ($operator) {
138
+ case '=':
139
+ $processed_value = trim($eval_val);
140
+ break;
141
+ case '+':
142
+ $processed_value = $value + $eval_val;
143
+ break;
144
+ case '-':
145
+ $processed_value = $value - $eval_val;
146
+ break;
147
+ case '*':
148
+ $processed_value = $value * $eval_val;
149
+ break;
150
+ case '/':
151
+ $processed_value = $value / $eval_val;
152
+ break;
153
+ case '&':
154
+ if (strpos($eval_val, '[VAL]') !== false) {
155
+ $processed_value = str_replace('[VAL]', $value, $eval_val);
156
+ } else {
157
+ $processed_value = $value . $eval_val;
158
+ }
159
+ break;
160
+ }
161
+ }
162
+ }
163
+ return $processed_value;
164
+ }
165
+
166
+ /**
167
+ * Parse product
168
+ * @param array $item
169
+ * @param integer $merge_empty_cells
170
+ * @return array
171
+ */
172
+ public function parse_product($item, $merge_empty_cells = 0) {
173
+ global $WF_CSV_Product_Import, $wpdb;
174
+ $this->row++;
175
+
176
+ $terms_array = $postmeta = $product = array();
177
+ $attributes = $default_attributes = $gpf_data = null;
178
+
179
+ // Merging
180
+ $merging = (!empty($_GET['merge']) && $_GET['merge'] ) ? 1 : 0;
181
+ //if($item['post_parent']!== '' && $item['parent_sku'] !== ''){
182
+
183
+ $this->post_defaults['post_type'] = 'product';
184
+ $this->post_type = 'product';
185
+ // Post ID field mapping
186
+ $post_id = (!empty($item['id']) ) ? $item['id'] : 0;
187
+ $post_id = (!empty($item['post_id']) ) ? $item['post_id'] : $post_id;
188
+ if ($merging) {
189
+
190
+ $product['merging'] = true;
191
+
192
+
193
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> Row %s - preparing for merge.', 'wf_csv_import_export'), $this->row));
194
+
195
+ // Required fields
196
+ if (!$post_id && empty($item['sku'])) {
197
+
198
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', __('> > Cannot merge without id or sku. Importing instead.', 'wf_csv_import_export'));
199
+
200
+ $merging = false;
201
+ } else {
202
+
203
+ // Check product exists
204
+ if (!$post_id) {
205
+ // Check product to merge exists
206
+ $db_query = $wpdb->prepare("
 
207
  SELECT $wpdb->posts.ID
208
  FROM $wpdb->posts
209
  LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
211
  AND $wpdb->posts.post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )
212
  AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s'
213
  ", $item['sku']);
214
+ $found_product_id = $wpdb->get_var($db_query);
215
+ if (!$found_product_id) {
216
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > Skipped. Cannot find product with sku %s. Importing instead.', 'wf_csv_import_export'), $item['sku']));
217
+ $merging = false;
218
+ } else {
219
+
220
+ $post_id = $found_product_id;
221
+
222
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > Found product with ID %s.', 'wf_csv_import_export'), $post_id));
223
+ }
224
+ }
225
+ }
226
+ }
227
+
228
+ if (!$merging) {
229
+
230
+ $product['merging'] = false;
231
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> Row %s - preparing for import.', 'wf_csv_import_export'), $this->row));
232
+
233
+ // Required fields
234
+ if (isset($item['post_parent']) && $item['post_parent'] === '' && $item['post_title'] === '') {
235
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', __('> > Skipped. No post_title set for new product.', 'wf_csv_import_export'));
236
+ return new WP_Error('parse-error', __('No post_title set for new product.', 'wf_csv_import_export'));
237
+ }
238
+ if (!empty($item['post_parent']) && $item['post_parent'] !== '' && $item['post_parent'] !== null && $item['parent_sku'] === '') {
239
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', __('> > Skipped. No parent set for new variation product.', 'wf_csv_import_export'));
240
+ //return new WP_Error( 'parse-error', __( 'No post_title set for new product.', 'wf_csv_import_export' ) );
241
+ return new WP_Error('parse-error', __('No parent set for new variation product.', 'wf_csv_import_export'));
242
+ }
243
+ }
244
+
245
+ $product['post_id'] = $post_id;
246
+
247
+
248
+ // Get post fields
249
+ foreach ($this->post_defaults as $column => $default) {
250
+ if (isset($item[$column]))
251
+ $product[$column] = $item[$column];
252
+ }
253
+
254
+ // Get custom fields
255
+ foreach ($this->postmeta_defaults as $column => $default) {
256
+ if (isset($item[$column]))
257
+ $postmeta[$column] = (string) $item[$column];
258
+ elseif (isset($item['_' . $column]))
259
+ $postmeta[$column] = (string) $item['_' . $column];
260
+
261
+ // Check custom fields are valid
262
+ if (isset($postmeta[$column]) && isset($this->postmeta_allowed[$column]) && !in_array($postmeta[$column], $this->postmeta_allowed[$column])) {
263
+ $postmeta[$column] = $this->postmeta_defaults[$column];
264
+ }
265
+ }
266
+
267
+ if (!$merging) {
268
+ // Merge post meta with defaults
269
+ $product = wp_parse_args($product, $this->post_defaults);
270
+ $postmeta = wp_parse_args($postmeta, $this->postmeta_defaults);
271
+ }
272
+
273
+ // Handle special meta fields
274
+ // price
275
+ if ($merging) {
276
+ if (!isset($postmeta['regular_price']))
277
+ $postmeta['regular_price'] = get_post_meta($post_id, '_regular_price', true);
278
+ $postmeta['regular_price'] = $this->hf_currency_formatter($postmeta['regular_price']);
279
+ if (!isset($postmeta['sale_price']))
280
+ $postmeta['sale_price'] = get_post_meta($post_id, '_sale_price', true);
281
+ $postmeta['sale_price'] = $this->hf_currency_formatter($postmeta['sale_price']);
282
+ }
283
+
284
+ if (isset($postmeta['regular_price']) && isset($postmeta['sale_price']) && $postmeta['sale_price'] !== '') {
285
+ $postmeta['sale_price'] = $this->hf_currency_formatter($postmeta['sale_price']);
286
+ $postmeta['regular_price'] = $this->hf_currency_formatter($postmeta['regular_price']);
287
+ $price = min($postmeta['sale_price'], $postmeta['regular_price']);
288
+ $postmeta['price'] = $price;
289
+ } elseif (isset($postmeta['regular_price'])) {
290
+ $postmeta['price'] = $this->hf_currency_formatter($postmeta['regular_price']);
291
+ }
292
+
293
+ // Reset dynamically generated meta
294
+ if (!isset($item['post_parent'])) {
295
+ $postmeta['min_variation_price'] = $postmeta['max_variation_price'] = $postmeta['min_variation_regular_price'] = $postmeta['max_variation_regular_price'] = $postmeta['min_variation_sale_price'] = $postmeta['max_variation_sale_price'] = '';
296
+ }
297
+
298
+ // upsells
299
+ if (isset($postmeta['upsell_ids']) && !is_array($postmeta['upsell_ids'])) {
300
+ $ids = array_filter(array_map('trim', explode('|', $postmeta['upsell_ids'])));
301
+ $postmeta['upsell_ids'] = $ids;
302
+ }
303
+
304
+ // crosssells
305
+ if (isset($postmeta['crosssell_ids']) && !is_array($postmeta['crosssell_ids'])) {
306
+ $ids = array_filter(array_map('trim', explode('|', $postmeta['crosssell_ids'])));
307
+ $postmeta['crosssell_ids'] = $ids;
308
+ }
309
+
310
+ // Sale dates
311
+ if (isset($postmeta['sale_price_dates_from'])) {
312
+ $postmeta['sale_price_dates_from'] = empty($postmeta['sale_price_dates_from']) ? '' : strtotime($postmeta['sale_price_dates_from']);
313
+ }
314
+
315
+ if (isset($postmeta['sale_price_dates_to'])) {
316
+ $postmeta['sale_price_dates_to'] = empty($postmeta['sale_price_dates_to']) ? '' : strtotime($postmeta['sale_price_dates_to']);
317
+ }
318
+
319
+ // Relative stock updates
320
+ if ($merging) {
321
+ if (isset($postmeta['stock'])) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
 
323
+ $postmeta['stock'] = trim($postmeta['stock']);
 
 
 
324
 
325
+ $mode = substr($postmeta['stock'], 0, 3);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
 
327
+ if ($mode == '(+)') {
328
+ $old_stock = absint(get_post_meta($post_id, '_stock', true));
329
+ $amount = absint(substr($postmeta['stock'], 3));
330
+ $new_stock = $old_stock + $amount;
331
+ $postmeta['stock'] = $new_stock;
332
+ }
333
 
334
+ if ($mode == '(-)') {
335
+ $old_stock = absint(get_post_meta($post_id, '_stock', true));
336
+ $amount = absint(substr($postmeta['stock'], 3));
337
+ $new_stock = $old_stock - $amount;
338
+ $postmeta['stock'] = $new_stock;
339
+ }
340
+ }
341
+ }
342
+
343
+ // Format post status
344
+ if (!empty($product['post_status'])) {
345
+ $product['post_status'] = strtolower($product['post_status']);
346
+
347
+ if (empty($item['post_parent'])) {
348
+ if (!in_array($product['post_status'], array('publish', 'private', 'draft', 'pending', 'future', 'inherit', 'trash'))) {
349
+ $product['post_status'] = 'publish';
350
+ }
351
+ } else {
352
+ if (!in_array($product['post_status'], array('private', 'publish'))) {
353
+ $product['post_status'] = 'publish';
354
+ }
355
+ }
356
+ }
357
+
358
+ // Put set core product postmeta into product array
359
+ foreach ($postmeta as $key => $value) {
360
+ $product['postmeta'][] = array('key' => '_' . esc_attr($key), 'value' => $value);
361
+ }
362
+
363
+ /**
364
+ * Handle other columns
365
+ */
366
+ foreach ($item as $key => $value) {
367
+
368
+ if (empty($item['post_parent']) && !$merge_empty_cells && $value == "")
369
+ continue;
370
+
371
+ /**
372
+ * File path handling
373
+ */
374
+ if ($key == 'file_paths' || $key == 'downloadable_files') {
375
+
376
+ $file_paths = explode('|', $value);
377
+ $_file_paths = array();
378
+ foreach ($file_paths as $file_path) {
379
+ // 2.1
380
+ if (function_exists('wc_get_filename_from_url')) {
381
+ $file_path = array_map('trim', explode('::', $file_path));
382
+ if (sizeof($file_path) === 2) {
383
+ $file_name = $file_path[0];
384
+ $file_path = $file_path[1];
385
+ } else {
386
+ $file_name = wc_get_filename_from_url($file_path[0]);
387
+ $file_path = $file_path[0];
388
+ }
389
+ $_file_paths[md5($file_path)] = array(
390
+ 'name' => $file_name,
391
+ 'file' => $file_path
392
+ );
393
+ } else {
394
+ $file_path = trim($file_path);
395
+ $_file_paths[md5($file_path)] = $file_path;
396
+ }
397
+ }
398
+ $value = $_file_paths;
399
+
400
+ $product['postmeta'][] = array('key' => '_' . esc_attr($key), 'value' => $value);
401
+ } elseif (strstr($key, 'tax:')) {
402
+
403
+ // Get taxonomy
404
+ $taxonomy = trim(str_replace('tax:', '', $key));
405
+
406
+ // Exists?
407
+ if (!taxonomy_exists($taxonomy)) {
408
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > Skipping taxonomy "%s" - it does not exist.', 'wf_csv_import_export'), $taxonomy));
409
+ continue;
410
+ }
411
+
412
+ // Product type check
413
+ if ($taxonomy == 'product_type') {
414
+ $term = strtolower(trim($value));
415
+
416
+ if (!array_key_exists($term, $this->allowed_product_types)) {
417
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > > Product type "%s" not allowed - using simple.', 'wf_csv_import_export'), $term));
418
+ $term_id = $this->allowed_product_types['simple'];
419
+ } else {
420
+ $term_id = $this->allowed_product_types[$term];
421
+ }
422
+
423
+ // Add to array
424
+ $terms_array[] = array(
425
+ 'taxonomy' => $taxonomy,
426
+ 'terms' => array($term_id)
427
+ );
428
+
429
+ continue;
430
+ }
431
+
432
+ // Get terms - ID => parent
433
+ $terms = array();
434
+ $raw_terms = explode('|', $value);
435
+ $raw_terms = array_map('trim', $raw_terms);
436
+
437
+ // Handle term hierachy (>)
438
+ foreach ($raw_terms as $raw_term) {
439
+
440
+ if (strstr($raw_term, '>')) {
441
+
442
+ $raw_term = explode('>', $raw_term);
443
+ $raw_term = array_map('trim', $raw_term);
444
+
445
+ if (WC()->version < '2.7.0') {
446
+ $raw_term = array_map('wp_specialchars', $raw_term);
447
+ $raw_term = array_filter($raw_term);
448
+ } else {
449
+ $raw_term = array_map('esc_html', $raw_term);
450
+ $raw_term = array_filter($raw_term);
451
+ }
452
+
453
+ $parent = 0;
454
+ $loop = 0;
455
+
456
+ foreach ($raw_term as $term) {
457
+ $loop ++;
458
+ $term_id = '';
459
+
460
+ if (isset($this->inserted_terms[$taxonomy][$parent][$term])) {
461
+ $term_id = $this->inserted_terms[$taxonomy][$parent][$term];
462
+ } elseif ($term) {
463
+
464
+ /**
465
+ * Check term existance
466
+ */
467
+ $term_may_exist = term_exists($term, $taxonomy, absint($parent));
468
+
469
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > (' . __LINE__ . ') Term %s (%s) exists? %s', 'wf_csv_import_export'), sanitize_text_field($term), esc_html($taxonomy), $term_may_exist ? print_r($term_may_exist, true) : '-' ));
470
+
471
+ if (is_array($term_may_exist)) {
472
+ $possible_term = get_term($term_may_exist['term_id'], 'product_cat');
473
+
474
+ if (!empty($possible_term) && $possible_term->parent == $parent) {
475
+ $term_id = $term_may_exist['term_id'];
476
+ }
477
+ }
478
+
479
+ if (!$term_id) {
480
 
481
+ //Create appropriate slug for the category
482
+ $slug = sanitize_title( $raw_term[$loop - 1] );
483
 
484
+ $t = wp_insert_term($term, $taxonomy, array('parent' => $parent, 'slug' => $slug));
 
485
 
486
+ if (!is_wp_error($t)) {
487
+ $term_id = $t['term_id'];
488
+ } else {
489
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > (' . __LINE__ . ') Failed to import term %s, parent %s - %s', 'wf_csv_import_export'), sanitize_text_field($term), sanitize_text_field($parent), sanitize_text_field($taxonomy)));
490
+ break;
491
+ }
492
+ }
493
+
494
+ $this->inserted_terms[$taxonomy][$parent][$term] = $term_id;
495
+ }
496
 
497
+ if (!$term_id)
498
+ break;
499
 
500
+ // Add to product terms, ready to set if this is the final term
501
+ if (sizeof($raw_term) == $loop)
502
+ $terms[] = $term_id;
 
 
 
 
503
 
504
+ $parent = $term_id;
505
+ }
506
+ } else {
507
 
508
+ $term_id = '';
509
+ $raw_term = (WC()->version < '2.7.0') ? wp_specialchars($raw_term) : esc_html($raw_term);
510
 
511
+ if (isset($this->inserted_terms[$taxonomy][0][$raw_term])) {
 
512
 
513
+ $term_id = $this->inserted_terms[$taxonomy][0][$raw_term];
514
+ } elseif ($raw_term) {
 
515
 
516
+ // Check term existance
517
+ $term_exists = term_exists($raw_term, $taxonomy, 0);
518
+ $term_id = is_array($term_exists) ? $term_exists['term_id'] : 0;
519
 
520
+ if (!$term_id) {
521
+ $t = wp_insert_term(trim($raw_term), $taxonomy, array('parent' => 0));
522
 
523
+ if (!is_wp_error($t)) {
524
+ $term_id = $t['term_id'];
525
+ } else {
526
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > Failed to import term %s %s', 'wf_csv_import_export'), esc_html($raw_term), esc_html($taxonomy)));
527
+ break;
528
+ }
529
+ }
530
 
531
+ $this->inserted_terms[$taxonomy][0][$raw_term] = $term_id;
532
+ }
533
+
534
+ // Store terms for later insertion
535
+ if ($term_id)
536
+ $terms[] = $term_id;
537
+ }
538
+ }
539
 
540
+ // Any defined?
541
+ if (sizeof($terms) == 0)
542
+ continue;
543
 
544
+ // Add to array
545
+ $terms_array[] = array(
546
+ 'taxonomy' => $taxonomy,
547
+ 'terms' => $terms
548
+ );
549
+ }
550
 
551
+ /**
552
+ * Handle Attributes
553
+ */
554
+ elseif (strstr($key, 'attribute:')) {
555
 
556
+ $attribute_key = sanitize_title(trim(str_replace('attribute:', '', $key)));
557
+ $attribute_name = str_replace('attribute:', '', $WF_CSV_Product_Import->raw_headers[$key]);
558
 
559
+ if (!$attribute_key)
560
+ continue;
 
 
 
 
 
561
 
562
+ // Taxonomy
563
+ if (substr($attribute_key, 0, 3) == 'pa_') {
564
 
565
+ $taxonomy = $attribute_key;
566
 
567
+ // Exists?
568
+ if (!taxonomy_exists($taxonomy)) {
 
569
 
 
570
 
571
+ $nicename = strtolower(sanitize_title(str_replace('pa_', '', $taxonomy)));
572
+
573
+ $attribute_label = ucwords(str_replace('-', ' ', $nicename)); // for importing attribute name as human readable string
574
+
575
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > Attribute taxonomy "%s" does not exist. Adding it. Nicename: %s', 'wf_csv_import_export'), $taxonomy, $nicename));
576
+
577
+ $exists_in_db = $wpdb->get_var("SELECT attribute_id FROM " . $wpdb->prefix . "woocommerce_attribute_taxonomies WHERE attribute_name = '" . $nicename . "';");
578
+
579
+ if (!$exists_in_db) {
580
+ // Create the taxonomy
581
+ $wpdb->insert($wpdb->prefix . "woocommerce_attribute_taxonomies", array('attribute_name' => $nicename, 'attribute_label' => $attribute_label, 'attribute_type' => 'select', 'attribute_orderby' => 'menu_order'));
582
+ } else {
583
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > Attribute taxonomy %s already exists in DB.', 'wf_csv_import_export'), $taxonomy));
584
+ }
585
+
586
+ // Register the taxonomy now so that the import works!
587
+ register_taxonomy($taxonomy, array('product', 'product_variation'), array(
588
+ 'hierarchical' => true,
589
+ 'show_ui' => false,
590
+ 'query_var' => true,
591
+ 'rewrite' => false,
592
+ )
593
+ );
594
+ }
595
 
596
+ // Get terms
597
+ $terms = array();
598
+ $raw_terms = explode('|', $value);
599
+ if (WC()->version < '2.7.0') {
600
+ $raw_terms = array_map('wp_specialchars', $raw_terms);
601
+ $raw_terms = array_map('trim', $raw_terms);
602
+ } else {
603
 
604
+ $raw_terms = array_map('esc_html', $raw_terms);
605
+ $raw_terms = array_map('trim', $raw_terms);
606
+ }
 
 
 
607
 
608
+ if (sizeof($raw_terms) > 0) {
 
 
 
609
 
610
+ foreach ($raw_terms as $raw_term) {
 
611
 
612
+ if (empty($raw_term) && 0 != $raw_term) {
613
+ continue;
614
+ }
615
 
616
+ // Check term existance
617
+ $term_exists = term_exists($raw_term, $taxonomy, 0);
618
+ $term_id = is_array($term_exists) ? $term_exists['term_id'] : 0;
619
 
620
+ if (!$term_id) {
621
+ $t = wp_insert_term(trim($raw_term), $taxonomy);
622
 
623
+ if (!is_wp_error($t)) {
624
+ $term_id = $t['term_id'];
 
625
 
626
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > Inserted Raw Term %s ID = %s', 'wf_csv_import_export'), esc_html($raw_term), $term_id));
627
+ } else {
628
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > Failed to import term %s %s', 'wf_csv_import_export'), esc_html($raw_term), esc_html($taxonomy)));
629
+ break;
630
+ }
631
+ } else {
632
+ $WF_CSV_Product_Import->hf_log_data_change('csv-import', sprintf(__('> > Raw Term %s ID = %s', 'wf_csv_import_export'), esc_html($raw_term), $term_id));
633
+ }
634
 
635
+ if ($term_id) {
636
+ $terms[] = $term_id;
637
+ }
638
+ }
639
+ }
640
 
641
+ // Add to array
642
+ $terms_array[] = array(
643
+ 'taxonomy' => $taxonomy,
644
+ 'terms' => $terms
645
+ );
646
+
647
+ // Ensure we have original attributes
648
+ if (is_null($attributes) && $merging) {
649
+ $attributes = array_filter((array) maybe_unserialize(get_post_meta($post_id, '_product_attributes', true)));
650
+ } elseif (is_null($attributes)) {
651
+ $attributes = array();
652
+ }
653
 
654
+ // Set attribute
655
+ if (!isset($attributes[$taxonomy]))
656
+ $attributes[$taxonomy] = array();
657
+
658
+ $attributes[$taxonomy]['name'] = $taxonomy;
659
+ $attributes[$taxonomy]['value'] = null;
660
+ $attributes[$taxonomy]['is_taxonomy'] = 1;
661
+
662
+ if (!isset($attributes[$taxonomy]['position']))
663
+ $attributes[$taxonomy]['position'] = 0;
664
+ if (!isset($attributes[$taxonomy]['is_visible']))
665
+ $attributes[$taxonomy]['is_visible'] = 1;
666
+ if (!isset($attributes[$taxonomy]['is_variation']))
667
+ $attributes[$taxonomy]['is_variation'] = 0;
668
+ } else {
669
+
670
+ if (!$value || !$attribute_key)
671
+ continue;
672
+
673
+ // Set attribute
674
+ if (!isset($attributes[$attribute_key]))
675
+ $attributes[$attribute_key] = array();
676
+
677
+ $attributes[$attribute_key]['name'] = $attribute_name;
678
+ $attributes[$attribute_key]['value'] = $value;
679
+ $attributes[$attribute_key]['is_taxonomy'] = 0;
680
+
681
+ if (!isset($attributes[$attribute_key]['position']))
682
+ $attributes[$attribute_key]['position'] = 0;
683
+ if (!isset($attributes[$attribute_key]['is_visible']))
684
+ $attributes[$attribute_key]['is_visible'] = 1;
685
+ if (!isset($attributes[$attribute_key]['is_variation']))
686
+ $attributes[$attribute_key]['is_variation'] = 0;
687
+ }
688
+ }
689
+
690
+ /**
691
+ * Handle Attributes Data - position|is_visible|is_variation
692
+ */
693
+ elseif (strstr($key, 'attribute_data:')) {
694
+
695
+ $attribute_key = sanitize_title(trim(str_replace('attribute_data:', '', $key)));
696
+
697
+ if (!$attribute_key) {
698
+ continue;
699
+ }
700
+
701
+ $values = explode('|', $value);
702
+ $position = isset($values[0]) ? (int) $values[0] : 0;
703
+ $visible = isset($values[1]) ? (int) $values[1] : 1;
704
+ $variation = isset($values[2]) ? (int) $values[2] : 0;
705
+
706
+ // Ensure we have original attributes
707
+ if (!isset($attributes[$attribute_key])) {
708
+ if ($merging) {
709
+ $existing_attributes = array_filter((array) maybe_unserialize(get_post_meta($post_id, '_product_attributes', true)));
710
+ $attributes[$attribute_key] = isset($existing_attributes[$attribute_key]) ? $existing_attributes[$attribute_key] : array();
711
+ } else {
712
+ $attributes[$attribute_key] = array();
713
+ }
714
+ }
715
+
716
+ $attributes[$attribute_key]['position'] = $position;
717
+ $attributes[$attribute_key]['is_visible'] = $visible;
718
+ $attributes[$attribute_key]['is_variation'] = $variation;
719
+ }
720
+
721
+ /**
722
+ * Handle Attributes Default Values
723
+ */ elseif (strstr($key, 'attribute_default:')) {
724
+
725
+ $attribute_key = sanitize_title(trim(str_replace('attribute_default:', '', $key)));
726
+
727
+ if (!$attribute_key)
728
+ continue;
729
+
730
+ // Ensure we have original attributes
731
+ if (is_null($default_attributes) && $merging) {
732
+ $default_attributes = array_filter((array) maybe_unserialize(get_post_meta($post_id, '_default_attributes', true)));
733
+ } elseif (is_null($default_attributes)) {
734
+ $default_attributes = array();
735
+ }
736
+
737
+ $default_attributes[$attribute_key] = $value;
738
+ }
739
+
740
+ /**
741
+ * Handle gpf: google product feed columns
742
+ */ elseif (strstr($key, 'gpf:')) {
743
+
744
+ $gpf_key = trim(str_replace('gpf:', '', $key));
745
+
746
+ // Get original values
747
+ if (is_null($gpf_data) && $merging) {
748
+ $gpf_data = array_filter((array) maybe_unserialize(get_post_meta($post_id, '_woocommerce_gpf_data', true)));
749
+ } elseif (is_null($gpf_data)) {
750
+ $gpf_data = array(
751
+ 'availability' => '',
752
+ 'condition' => '',
753
+ 'brand' => '',
754
+ 'product_type' => '',
755
+ 'google_product_category' => '',
756
+ 'gtin' => '',
757
+ 'mpn' => '',
758
+ 'gender' => '',
759
+ 'age_group' => '',
760
+ 'color' => '',
761
+ 'size' => ''
762
+ );
763
+ }
764
+
765
+ $gpf_data[$gpf_key] = $value;
766
+ }
767
+
768
+ /**
769
+ * Handle upsell SKUs which we cannot assign until we get IDs later on
770
+ */ elseif (strstr($key, 'upsell_skus')) {
771
+ if ($value) {
772
+ $skus = array_filter(array_map('trim', explode('|', $value)));
773
+ $product['upsell_skus'] = $skus;
774
+ }
775
+ }
776
+
777
+ /**
778
+ * Handle crosssells SKUs which we cannot assign until we get IDs later on
779
+ */ elseif (strstr($key, 'crosssell_skus')) {
780
+ if ($value) {
781
+ $skus = array_filter(array_map('trim', explode('|', $value)));
782
+ $product['crosssell_skus'] = $skus;
783
+ }
784
+ }
785
+ }
786
 
787
+ // Remove empty attribues
788
+ if (!empty($attributes))
789
+ foreach ($attributes as $key => $value) {
790
+ if (!isset($value['name']))
791
+ unset($attributes[$key]);
792
+ }
793
+
794
+ /**
795
+ * Handle images
796
+ */
797
+ if (!empty($item['images'])) {
798
+ $images = array_map('trim', explode('|', $item['images']));
799
+ } else {
800
+ $images = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
801
  }
802
+
803
+ $product['postmeta'][] = array('key' => '_default_attributes', 'value' => $default_attributes);
804
+ $product['attributes'] = $attributes;
805
+ $product['gpf_data'] = $gpf_data;
806
+ $product['images'] = $images;
807
+ $product['terms'] = $terms_array;
808
+ $product['sku'] = (!empty($item['sku']) ) ? $item['sku'] : '';
809
+ $product['post_title'] = (!empty($item['post_title']) ) ? $item['post_title'] : '';
810
+ $product['post_type'] = $this->post_type;
811
+ unset($item, $terms_array, $postmeta, $attributes, $gpf_data, $images);
812
+
813
+ return $product;
814
+ }
815
+
816
+ public function hf_currency_formatter($price) {
817
+
818
+ $decimal_seperator = wc_get_price_decimal_separator();
819
+ return preg_replace("[^0-9\\'.$decimal_seperator.']", "", $price);
820
+ }
821
+
822
  }
includes/importer/class-wf-prodimpexpcsv-product-import.php CHANGED
@@ -578,11 +578,11 @@ class WF_ProdImpExpCsv_Product_Import extends WP_Importer {
578
  foreach ( $this->parsed_data as $key => &$item ) {
579
 
580
  $product = $this->parser->parse_product( $item, $this->merge_empty_cells );
581
- if ( ! is_wp_error( $product ) )
582
  $this->process_product( $product );
583
- else
584
- $this->add_import_result( 'failed', $product->get_error_message(), 'Not parsed', json_encode( $item ), '-' );
585
-
586
  unset( $item, $product );
587
  }
588
  $this->hf_log_data_change( 'csv-import', __( 'Finished processing products.', 'wf_csv_import_export' ) );
@@ -1231,7 +1231,8 @@ class WF_ProdImpExpCsv_Product_Import extends WP_Importer {
1231
  $this->add_import_result( 'imported', 'Import successful', $post_id, $processing_product_title, $processing_product_sku );
1232
  $this->hf_log_data_change( 'csv-import', sprintf( __('> Finished importing post ID %s.', 'wf_csv_import_export'), $post_id ) );
1233
  }
1234
-
 
1235
  unset( $post );
1236
  }
1237
 
578
  foreach ( $this->parsed_data as $key => &$item ) {
579
 
580
  $product = $this->parser->parse_product( $item, $this->merge_empty_cells );
581
+ if ( ! is_wp_error( $product ) ){
582
  $this->process_product( $product );
583
+ }else{
584
+ $this->add_import_result( 'failed', $product->get_error_message(), 'Not parsed', json_encode( $item ), '-' );
585
+ }
586
  unset( $item, $product );
587
  }
588
  $this->hf_log_data_change( 'csv-import', __( 'Finished processing products.', 'wf_csv_import_export' ) );
1231
  $this->add_import_result( 'imported', 'Import successful', $post_id, $processing_product_title, $processing_product_sku );
1232
  $this->hf_log_data_change( 'csv-import', sprintf( __('> Finished importing post ID %s.', 'wf_csv_import_export'), $post_id ) );
1233
  }
1234
+
1235
+ do_action('wf_refresh_after_product_import',$processing_product_object); // hook for forcefully refresh product
1236
  unset( $post );
1237
  }
1238
 
includes/importer/views/html-wf-import-options.php CHANGED
@@ -25,7 +25,7 @@ if ( ! defined( 'ABSPATH' ) ) {
25
  <th><?php _e('CSV column header(from imported file)', 'wf_csv_import_export'); ?></th>
26
  <th><?php _e('Evaluation Field', 'wf_csv_import_export'); ?>
27
  <?php $plugin_url = WC()->plugin_url(); ?>
28
- <img class="help_tip" style="float:none;" data-tip="<?php _e('Assign constant value HikeFoce to post_author:</br>=HikeFoce</br>Add $5 to Price:sale_price:</br>+5</br>Reduce $5 to Price:sale_price:</br>-5</br>Multiple 1.05 to Price:sale_price:</br>*1.05</br>Divide Price:sale_price by 2:</br>/2</br>Append a value By HikeFoce to post_title:</br>&By HikeFoce</br>Prepend a value HikeFoce to post_title:</br>&HikeFoce [VAL].', 'wf_csv_import_export'); ?>" src="<?php echo $plugin_url; ?>/assets/images/help.png" height="20" width="20" />
29
  </th>
30
  </tr>
31
  </thead>
25
  <th><?php _e('CSV column header(from imported file)', 'wf_csv_import_export'); ?></th>
26
  <th><?php _e('Evaluation Field', 'wf_csv_import_export'); ?>
27
  <?php $plugin_url = WC()->plugin_url(); ?>
28
+ <img class="help_tip" style="float:none;" data-tip="<?php _e('Assign constant value WebToffe to post_author:</br>=WebToffe</br>Add $5 to Price:sale_price:</br>+5</br>Reduce $5 to Price:sale_price:</br>-5</br>Multiple 1.05 to Price:sale_price:</br>*1.05</br>Divide Price:sale_price by 2:</br>/2</br>Append a value By WebToffe to post_title:</br>&By WebToffe</br>Prepend a value WebToffe to post_title:</br>&WebToffe [VAL].', 'wf_csv_import_export'); ?>" src="<?php echo $plugin_url; ?>/assets/images/help.png" height="20" width="20" />
29
  </th>
30
  </tr>
31
  </thead>
product-csv-import-export.php CHANGED
@@ -5,8 +5,8 @@
5
  Description: Import and Export Products From and To your WooCommerce Store.
6
  Author: WebToffee
7
  Author URI: https://www.webtoffee.com/product/product-import-export-woocommerce/
8
- Version: 1.5.3
9
- WC tested up to: 3.5.3
10
  License: GPLv3
11
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
12
  Text Domain: wf_csv_import_export
@@ -18,7 +18,7 @@ if (!defined('ABSPATH') || !is_admin()) {
18
 
19
 
20
  if (!defined('WF_PIPE_CURRENT_VERSION')) {
21
- define("WF_PIPE_CURRENT_VERSION", "1.5.3");
22
  }
23
  if (!defined('WF_PROD_IMP_EXP_ID')) {
24
  define("WF_PROD_IMP_EXP_ID", "wf_prod_imp_exp");
5
  Description: Import and Export Products From and To your WooCommerce Store.
6
  Author: WebToffee
7
  Author URI: https://www.webtoffee.com/product/product-import-export-woocommerce/
8
+ Version: 1.5.4
9
+ WC tested up to: 3.5.4
10
  License: GPLv3
11
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
12
  Text Domain: wf_csv_import_export
18
 
19
 
20
  if (!defined('WF_PIPE_CURRENT_VERSION')) {
21
+ define("WF_PIPE_CURRENT_VERSION", "1.5.4");
22
  }
23
  if (!defined('WF_PROD_IMP_EXP_ID')) {
24
  define("WF_PROD_IMP_EXP_ID", "wf_prod_imp_exp");
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.webtoffee.com/plugins/
4
  Tags: woocommerce product import, woocommerce import products, woocommerce export products, export woocommerce products, import products into woocommerce
5
  Requires at least: 3.0.1
6
  Tested up to: 5.0.3
7
- Stable tag: 1.5.3
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -20,7 +20,7 @@ Are you trying to import products into WooCommerce store or export WooCommerce p
20
 
21
  &#128312; Export Simple Products in to a CSV file.
22
  &#128312; Import Simple Products in CSV format in to WooCommerce Store.
23
- &#128312; Tested OK with WooCommerce 3.5.3.
24
 
25
 
26
  Highlights: WooCommerce Product Export, WooCommerce Product CSV Import Suite, WooCommerce bulk product upload, WooCommerce import products with images, import amazon products to WooCommerce, Export Products to xls. Pro Version supports both Simple and Variable products.
@@ -149,6 +149,11 @@ LibreOffice.
149
 
150
  == Changelog ==
151
 
 
 
 
 
 
152
  = 1.5.3 =
153
  * Updates: Tested OK with WP 5.0.3 and WC 3.5.3
154
  * Bug Fix:- Image Thumbnail Regeneration error reporting.
@@ -279,7 +284,7 @@ LibreOffice.
279
 
280
  == Upgrade Notice ==
281
 
282
- = 1.5.3 =
283
- * Updates: Tested OK with WP 5.0.3 and WC 3.5.3
284
- * Bug Fix:- Image Thumbnail Regeneration error reporting.
285
  * Content Update.
4
  Tags: woocommerce product import, woocommerce import products, woocommerce export products, export woocommerce products, import products into woocommerce
5
  Requires at least: 3.0.1
6
  Tested up to: 5.0.3
7
+ Stable tag: 1.5.4
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
20
 
21
  &#128312; Export Simple Products in to a CSV file.
22
  &#128312; Import Simple Products in CSV format in to WooCommerce Store.
23
+ &#128312; Tested OK with WooCommerce 3.5.4.
24
 
25
 
26
  Highlights: WooCommerce Product Export, WooCommerce Product CSV Import Suite, WooCommerce bulk product upload, WooCommerce import products with images, import amazon products to WooCommerce, Export Products to xls. Pro Version supports both Simple and Variable products.
149
 
150
  == Changelog ==
151
 
152
+ = 1.5.4 =
153
+ * Updates: Tested OK with WC 3.5.4
154
+ * Bug Fix:- Importing hierarchical category
155
+ * Content Update.
156
+
157
  = 1.5.3 =
158
  * Updates: Tested OK with WP 5.0.3 and WC 3.5.3
159
  * Bug Fix:- Image Thumbnail Regeneration error reporting.
284
 
285
  == Upgrade Notice ==
286
 
287
+ = 1.5.4 =
288
+ * Updates: Tested OK with WC 3.5.4
289
+ * Bug Fix:- Importing hierarchical category
290
  * Content Update.