Order Export & Order Import for WooCommerce - Version 1.4.7

Version Description

  • Tested OK with WP 5.2.1 and WC 3.6.3
  • Bug Fix:- Order fields getting blank on updating when the fields are not present in CSV.
  • Coupon import optimisation.
Download this release

Release Info

Developer webtoffee
Plugin Icon 128x128 Order Export & Order Import for WooCommerce
Version 1.4.7
Comparing to
See all releases

Code changes from version 1.4.5 to 1.4.7

Files changed (34) hide show
  1. Sample_Coupon.csv +0 -0
  2. Sample_Order.csv +0 -0
  3. Sample_Subscription.csv +0 -0
  4. images/calendar.png +0 -0
  5. images/storefrog.png +0 -0
  6. images/wf-ajax-loader.gif +0 -0
  7. images/wf-import.png +0 -0
  8. images/wf-notice.png +0 -0
  9. images/wf-success.png +0 -0
  10. includes/class-wf-cpnimpexpcsv-ajax-handler.php +0 -0
  11. includes/class-wf-orderimpexp-plugin-uninstall-feedback.php +0 -0
  12. includes/class-wf-orderimpexpcsv-ajax-handler.php +0 -0
  13. includes/exporter/class-wf-cpnimpexpcsv-exporter.php +11 -82
  14. includes/exporter/class-wf-orderimpexpcsv-exporter.php +1 -3
  15. includes/exporter/data/data-wf-post-columns-coupon.php +1 -2
  16. includes/exporter/data/data-wf-post-columns.php +0 -0
  17. includes/importer/class-wf-cpnimpexpcsv-coupon-import.php +481 -849
  18. includes/importer/class-wf-cpnimpexpcsv-importer.php +0 -0
  19. includes/importer/class-wf-csv-parser-coupon.php +160 -214
  20. includes/importer/class-wf-csv-parser.php +118 -130
  21. includes/importer/class-wf-orderimpexpcsv-order-import.php +45 -33
  22. includes/importer/data-coupon/data-wf-post-defaults.php +3 -6
  23. includes/importer/data-coupon/data-wf-postmeta-defaults.php +2 -1
  24. includes/importer/data-coupon/data-wf-reserved-fields.php +2 -1
  25. includes/importer/views-coupon/html-wf-import-options.php +1 -1
  26. includes/importer/views/html-wf-import-options.php +0 -0
  27. includes/views/export/html-wf-export-coupons.php +0 -0
  28. includes/views/html-wf-admin-screen.php +0 -0
  29. includes/views/import/html-wf-import-coupons.php +0 -0
  30. includes/views/market.php +0 -0
  31. languages/wf_order_import_export-de_DE.mo +0 -0
  32. languages/wf_order_import_export-fr_FR.mo +0 -0
  33. order-import-export-for-woocommerce.php +3 -3
  34. readme.txt +14 -8
Sample_Coupon.csv CHANGED
File without changes
Sample_Order.csv CHANGED
File without changes
Sample_Subscription.csv CHANGED
File without changes
images/calendar.png CHANGED
File without changes
images/storefrog.png CHANGED
File without changes
images/wf-ajax-loader.gif CHANGED
File without changes
images/wf-import.png CHANGED
File without changes
images/wf-notice.png CHANGED
File without changes
images/wf-success.png CHANGED
File without changes
includes/class-wf-cpnimpexpcsv-ajax-handler.php CHANGED
File without changes
includes/class-wf-orderimpexp-plugin-uninstall-feedback.php CHANGED
File without changes
includes/class-wf-orderimpexpcsv-ajax-handler.php CHANGED
File without changes
includes/exporter/class-wf-cpnimpexpcsv-exporter.php CHANGED
@@ -9,30 +9,21 @@ class WF_CpnImpExpCsv_Exporter {
9
  public static function do_export($post_type = 'shop_coupon') {
10
  global $wpdb;
11
 
12
- $cpn_categories = !empty($_POST['cpn_categories']) ? $_POST['cpn_categories'] : array('fixed_cart', 'percent', 'fixed_product', 'percent_product');
13
  $export_limit = !empty($_POST['limit']) ? intval($_POST['limit']) : 999999999;
14
  $export_count = 0;
15
  $limit = 100;
16
  $current_offset = !empty($_POST['offset']) ? intval($_POST['offset']) : 0;
17
  $sortcolumn = !empty($_POST['sortcolumn']) ? $_POST['sortcolumn'] : 'ID';
18
  $delimiter = !empty($_POST['delimiter']) ? $_POST['delimiter'] : ',';
19
-
20
  $csv_columns = include( 'data/data-wf-post-columns-coupon.php' );
21
- $user_columns_name = !empty($_POST['columns_name']) ? $_POST['columns_name'] : $csv_columns;
22
- $export_columns = !empty($_POST['columns']) ? $_POST['columns'] : '';
23
  if ($limit > $export_limit)
24
  $limit = $export_limit;
25
-
26
-
27
  $wpdb->hide_errors();
28
  @set_time_limit(0);
29
  if (function_exists('apache_setenv'))
30
  @apache_setenv('no-gzip', 1);
31
  @ini_set('zlib.output_compression', 0);
32
- if(apply_filters('wt_order_export_ob_clean_enable_flag', TRUE)){
33
- @ob_clean();
34
- }
35
-
36
 
37
  header('Content-Type: text/csv; charset=UTF-8');
38
  header('Content-Disposition: attachment; filename=woocommerce-coupon-export-' . date('Y_m_d_H_i_s', current_time('timestamp')) . '.csv');
@@ -41,36 +32,11 @@ class WF_CpnImpExpCsv_Exporter {
41
 
42
  $fp = fopen('php://output', 'w');
43
 
44
-
45
- $all_meta_pkeys = self::get_all_metakeys('shop_coupon');
46
- $all_meta_keys = $all_meta_pkeys;
47
-
48
- $found_coupon_meta = array();
49
- foreach ($all_meta_keys as $meta) {
50
- if (!$meta)
51
- continue;
52
- if (!in_array($meta, array_keys($csv_columns)) && substr((string) $meta, 0, 1) == '_')
53
- continue;
54
-
55
- if (in_array($meta, array_keys($csv_columns)))
56
- continue;
57
- $found_coupon_meta[] = $meta;
58
- }
59
- $found_coupon_meta = array_diff($found_coupon_meta, array_keys($csv_columns));
60
  $row = array();
61
  foreach ($csv_columns as $column => $value) {
62
- $temp_head = esc_attr($user_columns_name[$column]);
63
- if (!$export_columns || in_array($column, $export_columns))
64
- $row[] = $temp_head;
65
- }
66
-
67
- if (!$export_columns || in_array('meta', $export_columns)) {
68
- foreach ($found_coupon_meta as $coupon_meta) {
69
- $row[] = 'meta:' . self::format_data($coupon_meta);
70
- }
71
  }
72
 
73
-
74
  $row = array_map('WF_CpnImpExpCsv_Exporter::wrap_column', $row);
75
  fwrite($fp, implode($delimiter, $row) . "\n");
76
  unset($row);
@@ -84,41 +50,26 @@ class WF_CpnImpExpCsv_Exporter {
84
  'suppress_filters' => false,
85
  'order' => 'ASC',
86
  'offset' => $current_offset
87
- ));
88
-
89
 
90
  $coupons = get_posts($coupon_args);
91
  if (!$coupons || is_wp_error($coupons))
92
  break;
93
  foreach ($coupons as $product) {
94
  foreach ($csv_columns as $column => $value) {
95
-
96
  if(is_array($product->$column)){
97
  $product->$column = implode(',', $product->$column);
98
  }
99
-
100
- if (!$export_columns || in_array($column, $export_columns)) {
101
- if (isset($product->meta->$column)) {
102
- $row[] = self::format_data($product->meta->$column);
103
- } elseif (isset($product->$column) && !is_array($product->$column)) {
104
- if ($column === 'post_title') {
105
- $row[] = sanitize_text_field($product->$column);
106
- } else {
107
- $row[] = self::format_data($product->$column);
108
- }
109
  } else {
110
- $row[] = '';
111
- }
112
- }
113
- }
114
-
115
- if (!$export_columns || in_array('meta', $export_columns)) {
116
- foreach ($found_coupon_meta as $product_meta) {
117
- if (isset($product->meta->$product_meta)) {
118
- $row[] = self::format_data($product->meta->$product_meta);
119
- } else {
120
- $row[] = '';
121
  }
 
 
122
  }
123
  }
124
  $row = array_map('WF_CpnImpExpCsv_Exporter::wrap_column', $row);
@@ -130,7 +81,6 @@ class WF_CpnImpExpCsv_Exporter {
130
  $export_count += $limit;
131
  unset($coupons);
132
  }
133
-
134
  fclose($fp);
135
  exit;
136
  }
@@ -152,25 +102,4 @@ class WF_CpnImpExpCsv_Exporter {
152
  public static function wrap_column($data) {
153
  return '"' . str_replace('"', '""', $data) . '"';
154
  }
155
-
156
- /**
157
- * Get a list of all the meta keys for a post type. This includes all public, private,
158
- * used, no-longer used etc. They will be sorted once fetched.
159
- */
160
- public static function get_all_metakeys($post_type = 'shop_coupon') {
161
- global $wpdb;
162
-
163
- $meta = $wpdb->get_col($wpdb->prepare(
164
- "SELECT DISTINCT pm.meta_key
165
- FROM {$wpdb->postmeta} AS pm
166
- LEFT JOIN {$wpdb->posts} AS p ON p.ID = pm.post_id
167
- WHERE p.post_type = %s
168
- AND p.post_status IN ( 'publish', 'pending', 'private', 'draft' )", $post_type
169
- ));
170
-
171
- sort($meta);
172
-
173
- return $meta;
174
- }
175
-
176
  }
9
  public static function do_export($post_type = 'shop_coupon') {
10
  global $wpdb;
11
 
 
12
  $export_limit = !empty($_POST['limit']) ? intval($_POST['limit']) : 999999999;
13
  $export_count = 0;
14
  $limit = 100;
15
  $current_offset = !empty($_POST['offset']) ? intval($_POST['offset']) : 0;
16
  $sortcolumn = !empty($_POST['sortcolumn']) ? $_POST['sortcolumn'] : 'ID';
17
  $delimiter = !empty($_POST['delimiter']) ? $_POST['delimiter'] : ',';
 
18
  $csv_columns = include( 'data/data-wf-post-columns-coupon.php' );
 
 
19
  if ($limit > $export_limit)
20
  $limit = $export_limit;
 
 
21
  $wpdb->hide_errors();
22
  @set_time_limit(0);
23
  if (function_exists('apache_setenv'))
24
  @apache_setenv('no-gzip', 1);
25
  @ini_set('zlib.output_compression', 0);
26
+ @ob_end_clean();
 
 
 
27
 
28
  header('Content-Type: text/csv; charset=UTF-8');
29
  header('Content-Disposition: attachment; filename=woocommerce-coupon-export-' . date('Y_m_d_H_i_s', current_time('timestamp')) . '.csv');
32
 
33
  $fp = fopen('php://output', 'w');
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  $row = array();
36
  foreach ($csv_columns as $column => $value) {
37
+ $row[] = $value;
 
 
 
 
 
 
 
 
38
  }
39
 
 
40
  $row = array_map('WF_CpnImpExpCsv_Exporter::wrap_column', $row);
41
  fwrite($fp, implode($delimiter, $row) . "\n");
42
  unset($row);
50
  'suppress_filters' => false,
51
  'order' => 'ASC',
52
  'offset' => $current_offset
53
+ ));
 
54
 
55
  $coupons = get_posts($coupon_args);
56
  if (!$coupons || is_wp_error($coupons))
57
  break;
58
  foreach ($coupons as $product) {
59
  foreach ($csv_columns as $column => $value) {
 
60
  if(is_array($product->$column)){
61
  $product->$column = implode(',', $product->$column);
62
  }
63
+ if (isset($product->meta->$column)) {
64
+ $row[] = self::format_data($product->meta->$column);
65
+ } elseif (isset($product->$column) && !is_array($product->$column)) {
66
+ if ($column === 'post_title') {
67
+ $row[] = sanitize_text_field($product->$column);
 
 
 
 
 
68
  } else {
69
+ $row[] = self::format_data($product->$column);
 
 
 
 
 
 
 
 
 
 
70
  }
71
+ } else {
72
+ $row[] = '';
73
  }
74
  }
75
  $row = array_map('WF_CpnImpExpCsv_Exporter::wrap_column', $row);
81
  $export_count += $limit;
82
  unset($coupons);
83
  }
 
84
  fclose($fp);
85
  exit;
86
  }
102
  public static function wrap_column($data) {
103
  return '"' . str_replace('"', '""', $data) . '"';
104
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  }
includes/exporter/class-wf-orderimpexpcsv-exporter.php CHANGED
@@ -29,9 +29,7 @@ class WF_OrderImpExpCsv_Exporter {
29
  if (function_exists('apache_setenv'))
30
  @apache_setenv('no-gzip', 1);
31
  @ini_set('zlib.output_compression', 0);
32
- if(apply_filters('wt_order_export_ob_clean_enable_flag', TRUE)){
33
- @ob_clean();
34
- }
35
 
36
  header('Content-Type: text/csv; charset=UTF-8');
37
  header('Content-Disposition: attachment; filename=woocommerce-order-export.csv');
29
  if (function_exists('apache_setenv'))
30
  @apache_setenv('no-gzip', 1);
31
  @ini_set('zlib.output_compression', 0);
32
+ @ob_end_clean();
 
 
33
 
34
  header('Content-Type: text/csv; charset=UTF-8');
35
  header('Content-Disposition: attachment; filename=woocommerce-order-export.csv');
includes/exporter/data/data-wf-post-columns-coupon.php CHANGED
@@ -21,6 +21,7 @@ return apply_filters('coupon_csv_coupon_post_columns', array(
21
  'usage_limit_per_user' => 'usage_limit_per_user',
22
  'limit_usage_to_x_items' => 'limit_usage_to_x_items',
23
  'expiry_date' => 'expiry_date',
 
24
  'free_shipping' => 'free_shipping',
25
  'exclude_sale_items' => 'exclude_sale_items',
26
  'product_categories' => 'product_categories',
@@ -28,6 +29,4 @@ return apply_filters('coupon_csv_coupon_post_columns', array(
28
  'minimum_amount' => 'minimum_amount',
29
  'maximum_amount' => 'maximum_amount',
30
  'customer_email' => 'customer_email',
31
- 'date_expires' => 'date_expires',
32
- 'usage_count' => 'usage_count',
33
  ) );
21
  'usage_limit_per_user' => 'usage_limit_per_user',
22
  'limit_usage_to_x_items' => 'limit_usage_to_x_items',
23
  'expiry_date' => 'expiry_date',
24
+ 'date_expires' => 'date_expires',
25
  'free_shipping' => 'free_shipping',
26
  'exclude_sale_items' => 'exclude_sale_items',
27
  'product_categories' => 'product_categories',
29
  'minimum_amount' => 'minimum_amount',
30
  'maximum_amount' => 'maximum_amount',
31
  'customer_email' => 'customer_email',
 
 
32
  ) );
includes/exporter/data/data-wf-post-columns.php CHANGED
File without changes
includes/importer/class-wf-cpnimpexpcsv-coupon-import.php CHANGED
@@ -10,655 +10,426 @@ if ( ! class_exists( 'WP_Importer' ) )
10
 
11
  class WF_CpnImpExpCsv_Coupon_Import extends WP_Importer {
12
 
13
- var $id;
14
- var $file_url;
15
- var $delimiter;
16
- var $profile;
17
- var $merge_empty_cells;
 
 
 
18
 
19
- // mappings from old information to new
20
- var $processed_terms = array();
21
- var $processed_posts = array();
22
- var $post_orphans = array();
23
- var $attachments = array();
24
- var $upsell_skus = array();
25
- var $crosssell_skus = array();
26
-
27
- // Results
28
- var $import_results = array();
29
-
30
- /**
31
- * Constructor
32
- */
33
- public function __construct() {
34
 
35
- if (WC()->version < '2.7.0') {
36
- $this->log = new WC_Logger();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  } else {
38
- $this->log = wc_get_logger();
39
  }
40
- $this->import_page = 'coupon_csv';
41
- $this->file_url_import_enabled = apply_filters( 'coupon_csv_coupon_file_url_import_enabled', true );
42
- }
43
-
44
- /**
45
- * Registered callback function for the WordPress Importer
46
- *
47
- * Manages the three separate stages of the CSV import process
48
- */
49
- public function dispatch() {
50
- global $woocommerce, $wpdb;
51
-
52
- if ( ! empty( $_POST['delimiter'] ) ) {
53
- $this->delimiter = stripslashes( trim( $_POST['delimiter'] ) );
54
- }else if ( ! empty( $_GET['delimiter'] ) ) {
55
- $this->delimiter = stripslashes( trim( $_GET['delimiter'] ) );
56
- }
57
-
58
- if ( ! $this->delimiter )
59
- $this->delimiter = ',';
60
-
61
- if ( ! empty( $_POST['profile'] ) ) {
62
- $this->profile = stripslashes( trim( $_POST['profile'] ) );
63
- }else if ( ! empty( $_GET['profile'] ) ) {
64
- $this->profile = stripslashes( trim( $_GET['profile'] ) );
65
- }
66
- if ( ! $this->profile )
67
- $this->profile = '';
68
-
69
- if ( ! empty( $_POST['merge_empty_cells'] ) || ! empty( $_GET['merge_empty_cells'] ) ) {
70
- $this->merge_empty_cells = 1;
71
- } else{
72
- $this->merge_empty_cells = 0;
73
- }
74
-
75
- $step = empty( $_GET['step'] ) ? 0 : (int) $_GET['step'];
76
-
77
- switch ( $step ) {
78
- case 0 :
79
- $this->header();
80
- $this->greet();
81
- break;
82
- case 1 :
83
- $this->header();
84
-
85
- check_admin_referer( 'import-upload' );
86
-
87
- if(!empty($_GET['file_url']))
88
- $this->file_url = esc_attr( $_GET['file_url'] );
89
- if(!empty($_GET['file_id']))
90
- $this->id = $_GET['file_id'] ;
91
-
92
- if ( !empty($_GET['clearmapping']) || $this->handle_upload() )
93
- $this->import_options();
94
- else
95
- //_e( 'Error with handle_upload!', 'order-import-export-for-woocommerce' );
96
- wp_redirect(wp_get_referer().'&wf_coupon_ie_msg=3');
97
- exit;
98
- break;
99
- case 2 :
100
- $this->header();
101
-
102
- check_admin_referer( 'import-woocommerce' );
103
-
104
- $this->id = (int) $_POST['import_id'];
105
-
106
- if ( $this->file_url_import_enabled )
107
- $this->file_url = esc_attr( $_POST['import_url'] );
108
-
109
- if ( $this->id )
110
- $file = get_attached_file( $this->id );
111
- else if ( $this->file_url_import_enabled )
112
- $file = ABSPATH . $this->file_url;
113
-
114
- $file = str_replace( "\\", "/", $file );
115
-
116
- if ( $file ) {
117
- ?>
118
- <table id="import-progress" class="widefat_importer widefat">
119
- <thead>
120
- <tr>
121
- <th class="status">&nbsp;</th>
122
- <th class="row"><?php _e( 'Row', 'order-import-export-for-woocommerce' ); ?></th>
123
- <th><?php _e( 'Coupon Id', 'order-import-export-for-woocommerce' ); ?></th>
124
- <th><?php _e( 'Coupon Name', 'order-import-export-for-woocommerce' ); ?></th>
125
- <th class="reason"><?php _e( 'Status Msg', 'order-import-export-for-woocommerce' ); ?></th>
126
- </tr>
127
- </thead>
128
- <tfoot>
129
- <tr class="importer-loading">
130
- <td colspan="5"></td>
131
- </tr>
132
- </tfoot>
133
- <tbody></tbody>
134
- </table>
135
- <script type="text/javascript">
136
- jQuery(document).ready(function($) {
137
-
138
- if ( ! window.console ) { window.console = function(){}; }
139
-
140
- var processed_terms = [];
141
- var processed_posts = [];
142
- var post_orphans = [];
143
- var attachments = [];
144
- var upsell_skus = [];
145
- var crosssell_skus = [];
146
- var i = 1;
147
- var done_count = 0;
148
-
149
- function import_rows( start_pos, end_pos ) {
150
-
151
- var data = {
152
- action: 'coupon_csv_import_request',
153
- file: '<?php echo addslashes( $file ); ?>',
154
- mapping: '<?php echo @json_encode( $_POST['map_from'] ); ?>',
155
- profile: '<?php echo $this->profile; ?>',
156
- eval_field: '<?php echo @stripslashes(json_encode(($_POST['eval_field']),JSON_HEX_APOS)) ?>',
157
- delimiter: '<?php echo $this->delimiter; ?>',
158
- merge_empty_cells: '<?php echo $this->merge_empty_cells; ?>',
159
- start_pos: start_pos,
160
- end_pos: end_pos,
161
- };
162
- data.eval_field = $.parseJSON(data.eval_field);
163
- return $.ajax({
164
- url: '<?php echo add_query_arg( array( 'import_page' => $this->import_page, 'step' => '3', 'merge' => ! empty( $_GET['merge'] ) ? '1' : '0' ), admin_url( 'admin-ajax.php' ) ); ?>',
165
- data: data,
166
- type: 'POST',
167
- success: function( response ) {
168
- if ( response ) {
169
-
170
- try {
171
- // Get the valid JSON only from the returned string
172
- if ( response.indexOf("<!--WC_START-->") >= 0 )
173
- response = response.split("<!--WC_START-->")[1]; // Strip off before after WC_START
174
-
175
- if ( response.indexOf("<!--WC_END-->") >= 0 )
176
- response = response.split("<!--WC_END-->")[0]; // Strip off anything after WC_END
177
-
178
- // Parse
179
- var results = $.parseJSON( response );
180
-
181
- if ( results.error ) {
182
-
183
- $('#import-progress tbody').append( '<tr id="row-' + i + '" class="error"><td class="status" colspan="5">' + results.error + '</td></tr>' );
184
-
185
- i++;
186
-
187
- } else if ( results.import_results && $( results.import_results ).size() > 0 ) {
188
-
189
- $.each( results.processed_terms, function( index, value ) {
190
- processed_terms.push( value );
191
- });
192
-
193
- $.each( results.processed_posts, function( index, value ) {
194
- processed_posts.push( value );
195
- });
196
-
197
- $.each( results.post_orphans, function( index, value ) {
198
- post_orphans.push( value );
199
- });
200
-
201
- $.each( results.attachments, function( index, value ) {
202
- attachments.push( value );
203
- });
204
-
205
- upsell_skus = jQuery.extend( {}, upsell_skus, results.upsell_skus );
206
- crosssell_skus = jQuery.extend( {}, crosssell_skus, results.crosssell_skus );
207
-
208
- $( results.import_results ).each(function( index, row ) {
209
- $('#import-progress tbody').append( '<tr id="row-' + i + '" class="' + row['status'] + '"><td><mark class="result" title="' + row['status'] + '">' + row['status'] + '</mark></td><td class="row">' + i + '</td><td>' + row['post_id'] + '</td><td>' + row['post_title'] + '</td><td class="reason">' + row['reason'] + '</td></tr>' );
210
-
211
- i++;
212
- });
213
- }
214
-
215
- } catch(err) {}
216
-
217
- } else {
218
- $('#import-progress tbody').append( '<tr class="error"><td class="status" colspan="5">' + '<?php _e( 'AJAX Error', 'order-import-export-for-woocommerce' ); ?>' + '</td></tr>' );
219
- }
220
-
221
- var w = $(window);
222
- var row = $( "#row-" + ( i - 1 ) );
223
-
224
- if ( row.length ) {
225
- w.scrollTop( row.offset().top - (w.height()/2) );
226
- }
227
-
228
- done_count++;
229
-
230
- $('body').trigger( 'coupon_csv_import_request_complete' );
231
- }
232
- });
233
- }
234
-
235
- var rows = [];
236
-
237
- <?php
238
- $limit = apply_filters( 'coupon_csv_import_limit_per_request', 10 );
239
- $enc = mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
240
- if ( $enc )
241
- setlocale( LC_ALL, 'en_US.' . $enc );
242
- @ini_set( 'auto_detect_line_endings', true );
243
-
244
- $count = 0;
245
- $previous_position = 0;
246
- $position = 0;
247
- $import_count = 0;
248
-
249
- // Get CSV positions
250
- if ( ( $handle = fopen( $file, "r" ) ) !== FALSE ) {
251
-
252
- while ( ( $postmeta = fgetcsv( $handle, 0, $this->delimiter , '"', '"' ) ) !== FALSE ) {
253
- $count++;
254
-
255
- if ( $count >= $limit ) {
256
- $previous_position = $position;
257
- $position = ftell( $handle );
258
- $count = 0;
259
- $import_count ++;
260
-
261
- // Import rows between $previous_position $position
262
- ?>rows.push( [ <?php echo $previous_position; ?>, <?php echo $position; ?> ] ); <?php
263
- }
264
- }
265
-
266
- // Remainder
267
- if ( $count > 0 ) {
268
- ?>rows.push( [ <?php echo $position; ?>, '' ] ); <?php
269
- $import_count ++;
270
- }
271
-
272
- fclose( $handle );
273
- }
274
- ?>
275
-
276
- var data = rows.shift();
277
- var regen_count = 0;
278
- import_rows( data[0], data[1] );
279
-
280
- $('body').on( 'coupon_csv_import_request_complete', function() {
281
- if ( done_count == <?php echo $import_count; ?> ) {
282
-
283
- if ( attachments.length ) {
284
-
285
- $('#import-progress tbody').append( '<tr class="regenerating"><td colspan="5"><div class="progress"></div></td></tr>' );
286
-
287
- index = 0;
288
-
289
- $.each( attachments, function( i, value ) {
290
- regenerate_thumbnail( value );
291
- index ++;
292
- if ( index == attachments.length ) {
293
- import_done();
294
- }
295
- });
296
-
297
- } else {
298
- import_done();
299
- }
300
-
301
- } else {
302
- // Call next request
303
- data = rows.shift();
304
- import_rows( data[0], data[1] );
305
- }
306
- } );
307
-
308
- // Regenerate a specified image via AJAX
309
- function regenerate_thumbnail( id ) {
310
- $.ajax({
311
- type: 'POST',
312
- url: ajaxurl,
313
- data: { action: "coupon_csv_import_regenerate_thumbnail", id: id },
314
- success: function( response ) {
315
- if ( response !== Object( response ) || ( typeof response.success === "undefined" && typeof response.error === "undefined" ) ) {
316
- response = new Object;
317
- response.success = false;
318
- response.error = "<?php printf( esc_js( __( 'The resize request was abnormally terminated (ID %s). This is likely due to the image exceeding available memory or some other type of fatal error.', 'order-import-export-for-woocommerce' ) ), '" + id + "' ); ?>";
319
- }
320
-
321
- regen_count ++;
322
-
323
- $('#import-progress tbody .regenerating .progress').css( 'width', ( ( regen_count / attachments.length ) * 100 ) + '%' ).html( regen_count + ' / ' + attachments.length + ' <?php echo esc_js( __( 'thumbnails regenerated', 'order-import-export-for-woocommerce' ) ); ?>' );
324
-
325
- if ( ! response.success ) {
326
- $('#import-progress tbody').append( '<tr><td colspan="5">' + response.error + '</td></tr>' );
327
- }
328
- },
329
- error: function( response ) {
330
- $('#import-progress tbody').append( '<tr><td colspan="5">' + response.error + '</td></tr>' );
331
- }
332
- });
333
- }
334
-
335
- function import_done() {
336
- var data = {
337
- action: 'coupon_csv_import_request',
338
- file: '<?php echo $file; ?>',
339
- processed_terms: processed_terms,
340
- processed_posts: processed_posts,
341
- post_orphans: post_orphans,
342
- upsell_skus: upsell_skus,
343
- crosssell_skus: crosssell_skus
344
- };
345
-
346
- $.ajax({
347
- url: '<?php echo add_query_arg( array( 'import_page' => $this->import_page, 'step' => '4', 'merge' => ! empty( $_GET['merge'] ) ? 1 : 0 ), admin_url( 'admin-ajax.php' ) ); ?>',
348
- data: data,
349
- type: 'POST',
350
- success: function( response ) {
351
- //console.log( response );
352
- $('#import-progress tbody').append( '<tr class="complete"><td colspan="5">' + response + '</td></tr>' );
353
- $('.importer-loading').hide();
354
- }
355
- });
356
- }
357
- });
358
- </script>
359
- <?php
360
- } else {
361
- echo '<p class="error">' . __( 'Error finding uploaded file!', 'order-import-export-for-woocommerce' ) . '</p>';
362
- }
363
- break;
364
- case 3 :
365
- // Check access - cannot use nonce here as it will expire after multiple requests
366
- if ( ! current_user_can( 'manage_woocommerce' ) )
367
- die();
368
-
369
- add_filter( 'http_request_timeout', array( $this, 'bump_request_timeout' ) );
370
-
371
- if ( function_exists( 'gc_enable' ) )
372
- gc_enable();
373
-
374
- @set_time_limit(0);
375
- @ob_flush();
376
- @flush();
377
- $wpdb->hide_errors();
378
-
379
- $file = stripslashes( $_POST['file'] );
380
- $mapping = json_decode( stripslashes( $_POST['mapping'] ), true );
381
- $profile = isset( $_POST['profile'] ) ? $_POST['profile']:'';
382
- $eval_field = $_POST['eval_field'];
383
- $start_pos = isset( $_POST['start_pos'] ) ? absint( $_POST['start_pos'] ) : 0;
384
- $end_pos = isset( $_POST['end_pos'] ) ? absint( $_POST['end_pos'] ) : '';
385
-
386
- if($profile!== '')
387
- {
388
- $profile_array = get_option('wf_cpn_csv_imp_exp_mapping');
389
- $profile_array[$profile] = array($mapping,$eval_field);
390
- update_option('wf_cpn_csv_imp_exp_mapping', $profile_array);
391
- }
392
-
393
- $position = $this->import_start( $file, $mapping, $start_pos, $end_pos, $eval_field );
394
- $this->import();
395
- $this->import_end();
396
-
397
- $results = array();
398
- $results['import_results'] = $this->import_results;
399
- $results['processed_terms'] = $this->processed_terms;
400
- $results['processed_posts'] = $this->processed_posts;
401
- $results['post_orphans'] = $this->post_orphans;
402
- $results['attachments'] = $this->attachments;
403
- $results['upsell_skus'] = $this->upsell_skus;
404
- $results['crosssell_skus'] = $this->crosssell_skus;
405
-
406
- echo "<!--WC_START-->";
407
- echo json_encode( $results );
408
- echo "<!--WC_END-->";
409
- exit;
410
- break;
411
- case 4 :
412
- // Check access - cannot use nonce here as it will expire after multiple requests
413
- if ( ! current_user_can( 'manage_woocommerce' ) )
414
- die();
415
-
416
- add_filter( 'http_request_timeout', array( $this, 'bump_request_timeout' ) );
417
-
418
- if ( function_exists( 'gc_enable' ) )
419
- gc_enable();
420
-
421
- @set_time_limit(0);
422
- @ob_flush();
423
- @flush();
424
- $wpdb->hide_errors();
425
-
426
- $this->processed_terms = isset( $_POST['processed_terms'] ) ? $_POST['processed_terms'] : array();
427
- $this->processed_posts = isset( $_POST['processed_posts']) ? $_POST['processed_posts'] : array();
428
- $this->post_orphans = isset( $_POST['post_orphans']) ? $_POST['post_orphans'] : array();
429
- $this->crosssell_skus = isset( $_POST['crosssell_skus']) ? array_filter( (array) $_POST['crosssell_skus'] ) : array();
430
- $this->upsell_skus = isset( $_POST['upsell_skus']) ? array_filter( (array) $_POST['upsell_skus'] ) : array();
431
-
432
- _e( 'Step 1...', 'order-import-export-for-woocommerce' ) . ' ';
433
-
434
- wp_defer_term_counting( true );
435
- wp_defer_comment_counting( true );
436
-
437
- _e( 'Step 2...', 'order-import-export-for-woocommerce' ) . ' ';
438
-
439
- echo 'Step 3...' . ' '; // Easter egg
440
- _e( 'Finalizing...', 'order-import-export-for-woocommerce' ) . ' ';
441
-
442
-
443
- // SUCCESS
444
- _e( 'Finished. Import complete.', 'order-import-export-for-woocommerce' );
445
-
446
- $this->import_end();
447
- exit;
448
- break;
449
- }
450
-
451
- $this->footer();
452
- }
453
-
454
- /**
455
- * format_data_from_csv
456
- */
457
- public function format_data_from_csv( $data, $enc ) {
458
- return ( $enc == 'UTF-8' ) ? $data : utf8_encode( $data );
459
- }
460
-
461
- /**
462
- * Display pre-import options
463
- */
464
- public function import_options()
465
- {
466
- $j = 0;
467
-
468
- if ( $this->id )
469
- $file = get_attached_file( $this->id );
470
- else if ( $this->file_url_import_enabled )
471
- $file = ABSPATH . $this->file_url;
472
- else
473
- return;
474
-
475
- // Set locale
476
- $enc = mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
477
- if ( $enc ) setlocale( LC_ALL, 'en_US.' . $enc );
478
- @ini_set( 'auto_detect_line_endings', true );
479
-
480
- // Get headers
481
- if ( ( $handle = fopen( $file, "r" ) ) !== FALSE )
482
- {
483
- $row = $raw_headers = array();
484
-
485
- $header = fgetcsv( $handle, 0, $this->delimiter , '"', '"');
486
-
487
- while ( ( $postmeta = fgetcsv( $handle, 0, $this->delimiter , '"', '"') ) !== FALSE )
488
- {
489
- foreach ( $header as $key => $heading )
490
- {
491
- if ( ! $heading ) continue;
492
- $s_heading = strtolower( $heading );
493
- $row[$s_heading] = ( isset( $postmeta[$key] ) ) ? $this->format_data_from_csv( $postmeta[$key], $enc ) : '';
494
- $raw_headers[ $s_heading ] = $heading;
495
- }
496
- break;
497
- }
498
- fclose( $handle );
499
- }
500
-
501
- $mapping_from_db = get_option( 'wf_cpn_csv_imp_exp_mapping');
502
-
503
- if( $this->profile!=='' && !empty($_GET['clearmapping']))
504
- {
505
- unset($mapping_from_db[$this->profile]);
506
- update_option('wf_cpn_csv_imp_exp_mapping', $mapping_from_db);
507
- $this->profile = '';
508
  }
509
- if($this->profile !== '')
510
- $mapping_from_db = $mapping_from_db[$this->profile];
511
-
512
- $saved_mapping = null;
513
- $saved_evaluation = null;
514
- if($mapping_from_db && is_array($mapping_from_db) && count($mapping_from_db) == 2 && empty($_GET['clearmapping']))
515
- {
516
- $reset_action = 'admin.php?clearmapping=1&amp;profile='.$this->profile.'&amp;import=' . $this->import_page . '&amp;step=1&amp;merge=' . ( ! empty( $_GET['merge'] ) ? 1 : 0 ) . '&amp;file_url=' . $this->file_url . '&amp;delimiter=' . $this->delimiter . '&amp;merge_empty_cells=' . $this->merge_empty_cells . '&amp;file_id=' . $this->id . '';
517
- $reset_action = esc_attr(wp_nonce_url($reset_action, 'import-upload'));
518
- echo '<h3>' . __( 'Columns are pre-selected using the Mapping file: "<b style="color:gray">'.$this->profile.'</b>". <a href="'.$reset_action.'"> Delete</a> this mapping file.', 'order-import-export-for-woocommerce' ) . '</h3>';
519
- $saved_mapping = $mapping_from_db[0];
520
- $saved_evaluation = $mapping_from_db[1];
521
- }
522
-
523
- $merge = (!empty($_GET['merge']) && $_GET['merge']) ? 1 : 0;
524
- include( 'views-coupon/html-wf-import-options.php' );
525
- }
526
-
527
- /**
528
- * The main controller for the actual import stage.
529
- */
530
- public function import()
531
- {
532
- global $woocommerce, $wpdb;
533
-
534
- wp_suspend_cache_invalidation( true );
535
-
536
- $this->hf_coupon_log_data_change( 'coupon-csv-import', '---' );
537
- $this->hf_coupon_log_data_change( 'coupon-csv-import', __( 'Processing coupons.', 'order-import-export-for-woocommerce' ) );
538
- foreach ( $this->parsed_data as $key => &$item )
539
- {
540
- $coupon = $this->parser->parse_coupon( $item, $this->merge_empty_cells );
541
- if ( ! is_wp_error( $coupon ) )
542
- $this->process_coupon( $coupon );
543
- else
544
- $this->add_import_result( 'failed', $coupon->get_error_message(), 'Not parsed', json_encode( $item ) );
545
-
546
- unset( $item, $coupon );
547
- }
548
- $this->hf_coupon_log_data_change( 'coupon-csv-import', __( 'Finished processing coupons.', 'order-import-export-for-woocommerce' ) );
549
- wp_suspend_cache_invalidation( false );
550
- }
551
-
552
- /**
553
- * Parses the CSV file and prepares us for the task of processing parsed data
554
- *
555
- * @param string $file Path to the CSV file for importing
556
- */
557
- public function import_start( $file, $mapping, $start_pos, $end_pos, $eval_field ) {
558
-
559
-
560
- $memory = size_format( (WC()->version < '2.7.0')?woocommerce_let_to_num( ini_get( 'memory_limit' ) ):wc_let_to_num( ini_get( 'memory_limit' ) ) );
561
- $wp_memory = size_format( (WC()->version < '2.7.0')? woocommerce_let_to_num( WP_MEMORY_LIMIT ) : wc_let_to_num( WP_MEMORY_LIMIT ) );
562
-
563
- $this->hf_coupon_log_data_change( 'coupon-csv-import', '---[ New Import ] PHP Memory: ' . $memory . ', WP Memory: ' . $wp_memory );
564
- $this->hf_coupon_log_data_change( 'coupon-csv-import', __( 'Parsing coupons CSV.', 'order-import-export-for-woocommerce' ) );
565
-
566
- $this->parser = new WF_CSV_Parser_Coupon( 'shop_coupon' );
567
- list( $this->parsed_data, $this->raw_headers, $position ) = $this->parser->parse_data( $file, $this->delimiter, $mapping, $start_pos, $end_pos, $eval_field );
568
- $this->hf_coupon_log_data_change( 'coupon-csv-import', __( 'Finished parsing coupons CSV.', 'order-import-export-for-woocommerce' ) );
569
-
570
- unset( $import_data );
571
-
572
- wp_defer_term_counting( true );
573
- wp_defer_comment_counting( true );
574
-
575
- return $position;
576
- }
577
-
578
- /**
579
- * Performs post-import cleanup of files and the cache
580
- */
581
- public function import_end() {
582
-
583
- do_action( 'import_end' );
584
- }
585
-
586
- /**
587
- * Handles the CSV upload and initial parsing of the file to prepare for
588
- * displaying author import options
589
- *
590
- * @return bool False if error uploading or invalid file, true otherwise
591
- */
592
- public function handle_upload() {
593
- if($this->handle_ftp()){
594
- return true;
595
- }
596
- if ( empty( $_POST['file_url'] ) ) {
597
-
598
- $file = wp_import_handle_upload();
599
-
600
- if ( isset( $file['error'] ) ) {
601
- echo '<p><strong>' . __( 'Sorry, there has been an error.', 'order-import-export-for-woocommerce' ) . '</strong><br />';
602
- echo esc_html( $file['error'] ) . '</p>';
603
- return false;
604
- }
605
-
606
- $this->id = (int) $file['id'];
607
- return true;
608
-
609
- } else {
610
-
611
- if ( file_exists( ABSPATH . $_POST['file_url'] ) )
612
- {
613
- $this->file_url = esc_attr( $_POST['file_url'] );
614
- return true;
615
- } else {
616
- echo '<p><strong>' . __( 'Sorry, there has been an error.', 'order-import-export-for-woocommerce' ) . '</strong></p>';
617
- return false;
618
- }
619
 
620
- }
 
 
 
 
 
621
 
622
- return false;
623
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
624
 
625
- public function coupon_exists( $title, $ID = '', $post_name = '' )
626
- {
627
- global $wpdb;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
628
 
629
- // Post Title Check
630
- $post_title = stripslashes( sanitize_post_field( 'post_title', $title, 0, 'db' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
631
 
632
- $query = "SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_coupon' AND post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )";
633
- $args = array();
 
 
 
 
634
 
635
- if ( ! empty ( $post_name ) )
636
- {
637
- $query .= ' AND post_name = %s';
638
- $args[] = $post_name;
639
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
640
 
641
- if ( ! empty ( $args ) )
642
- {
643
- $posts_that_exist = $wpdb->get_col( $wpdb->prepare( $query, $args ) );
644
- if ( $posts_that_exist )
645
- {
646
- foreach( $posts_that_exist as $post_exists )
647
- {
648
- if ( $ID == $post_exists )
649
- {
650
- return true;
651
- }
652
- }
653
- }
654
- }
655
- return false;
656
- }
 
 
 
 
 
 
657
 
658
- /**
659
- * Create new posts based on import information
660
- */
661
- public function process_coupon($post) {
662
  $processing_coupon_id = absint($post['post_id']);
663
  $processing_coupon = get_post($processing_coupon_id);
664
  $processing_coupon_title = $processing_coupon ? $processing_coupon->post_title : '';
@@ -670,7 +441,6 @@ class WF_CpnImpExpCsv_Coupon_Import extends WP_Importer {
670
  }
671
  $post['post_type'] = 'shop_coupon';
672
 
673
-
674
  if (!empty($processing_coupon_id) && isset($this->processed_posts[$processing_coupon_id])) {
675
  $this->add_import_result('skipped', __('Coupon already processed', 'order-import-export-for-woocommerce'), $processing_coupon_id, $processing_coupon_title);
676
  $this->hf_coupon_log_data_change('coupon-csv-import', __('> Coupon ID already processed. Skipping.', 'order-import-export-for-woocommerce'), true);
@@ -684,6 +454,7 @@ class WF_CpnImpExpCsv_Coupon_Import extends WP_Importer {
684
  unset($post);
685
  return;
686
  }
 
687
  if (!$merging) {
688
  if ($this->coupon_exists($processing_coupon_title, $processing_coupon_id, $post['post_name'])) {
689
  if (!$processing_coupon_id) {
@@ -697,53 +468,50 @@ class WF_CpnImpExpCsv_Coupon_Import extends WP_Importer {
697
  return;
698
  }
699
 
700
- if ($processing_coupon_id && is_string(get_post_status($processing_coupon_id))) {
701
- $this->add_import_result('skipped', __('Importing coupon ID conflicts with an existing coupon ID', 'order-import-export-for-woocommerce'), $processing_coupon_id, get_the_title($processing_coupon_id));
702
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('> &#8220;%s&#8221; ID already exists.', 'order-import-export-for-woocommerce'), esc_html($processing_coupon_id)), true);
703
  unset($post);
704
  return;
705
  }
 
 
 
 
 
 
 
706
  }
707
-
708
- $is_post_exist_in_db = get_post_type($processing_coupon_id);
709
-
710
- if ($merging && $processing_coupon_id && !empty($is_post_exist_in_db) && (get_post_type($processing_coupon_id) !== $post['post_type'] )) {
711
- $this->add_import_result('skipped', __('Post is not a coupon', 'order-import-export-for-woocommerce'), $processing_coupon_id, $processing_coupon_title);
712
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('> &#8220;%s&#8221; is not a coupon.', 'order-import-export-for-woocommerce'), esc_html($processing_coupon_id)), true);
713
-
714
  unset($post);
715
  return;
716
  }
717
 
718
  if ($merging && !empty($is_post_exist_in_db)) {
719
  $post_id = $processing_coupon_id;
720
-
721
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('> Merging coupon ID %s.', 'order-import-export-for-woocommerce'), $post_id), true);
722
-
723
- $postdata = array(
724
- 'ID' => $post_id
725
- );
726
-
727
- if ($this->merge_empty_cells) {
728
- if (isset($post['post_content'])) {
729
- $postdata['post_content'] = $post['post_content'];
730
- }
731
- if (isset($post['post_excerpt'])) {
732
- $postdata['post_excerpt'] = $post['post_excerpt'];
733
- }
734
- } else {
735
  if (!empty($post['post_content'])) {
736
  $postdata['post_content'] = $post['post_content'];
737
  }
738
  if (!empty($post['post_excerpt'])) {
739
  $postdata['post_excerpt'] = $post['post_excerpt'];
740
  }
741
- }
742
-
743
  if (!empty($post['post_title'])) {
744
  $postdata['post_title'] = $post['post_title'];
745
  }
746
-
747
  if (!empty($post['post_author'])) {
748
  $postdata['post_author'] = absint($post['post_author']);
749
  }
@@ -759,10 +527,8 @@ class WF_CpnImpExpCsv_Coupon_Import extends WP_Importer {
759
  if (!empty($post['post_status'])) {
760
  $postdata['post_status'] = $post['post_status'];
761
  }
762
-
763
  if (sizeof($postdata) > 1) {
764
  $result = wp_update_post($postdata);
765
-
766
  if (!$result) {
767
  $this->add_import_result('failed', __('Failed to update coupon', 'order-import-export-for-woocommerce'), $post_id, $processing_coupon_title);
768
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('> Failed to update coupon %s', 'order-import-export-for-woocommerce'), $post_id), true);
@@ -774,7 +540,6 @@ class WF_CpnImpExpCsv_Coupon_Import extends WP_Importer {
774
  }
775
  } else {
776
  $merging = FALSE;
777
-
778
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('> Inserting %s', 'order-import-export-for-woocommerce'), esc_html($processing_coupon_title)), true);
779
  $postdata = array(
780
  'import_id' => $post['post_id'],
@@ -792,7 +557,6 @@ class WF_CpnImpExpCsv_Coupon_Import extends WP_Importer {
792
  $post_id = wp_insert_post($postdata, true);
793
 
794
  if (is_wp_error($post_id)) {
795
-
796
  $this->add_import_result('failed', __('Failed to import coupon', 'order-import-export-for-woocommerce'), $processing_coupon_id, $processing_coupon_title);
797
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('Failed to import coupon &#8220;%s&#8221;', 'order-import-export-for-woocommerce'), esc_html($processing_coupon_title)));
798
  unset($post);
@@ -816,13 +580,14 @@ class WF_CpnImpExpCsv_Coupon_Import extends WP_Importer {
816
  if ($key) {
817
  if ($key == 'product_categories' || $key == 'exclude_product_categories') {
818
  update_post_meta($post_id, $key, explode(",", $meta['value']));
819
- } else {
820
- if ($key == 'customer_email') {
821
- $data = explode(',', $meta['value']);
822
- update_post_meta($post_id, $key, ( $data));
823
- } else {
824
- update_post_meta($post_id, $key, maybe_unserialize($meta['value']));
825
- }
 
826
  }
827
  }
828
  }
@@ -839,186 +604,53 @@ class WF_CpnImpExpCsv_Coupon_Import extends WP_Importer {
839
  }
840
 
841
  /**
842
- * Log a row's import status
843
- */
844
- protected function add_import_result( $status, $reason, $post_id = '', $post_title = '' ) {
845
- $this->import_results[] = array(
846
- 'post_title' => $post_title,
847
- 'post_id' => $post_id,
848
- 'status' => $status,
849
- 'reason' => $reason
850
- );
851
- }
852
- /**
853
- * Attempt to download a remote file attachment
854
- */
855
- public function fetch_remote_file( $url, $post )
856
- {
857
-
858
- // extract the file name and extension from the url
859
- $file_name = basename( current( explode( '?', $url ) ) );
860
- $wp_filetype = wp_check_filetype( $file_name, null );
861
- $parsed_url = @parse_url( $url );
862
-
863
- // Check parsed URL
864
- if ( ! $parsed_url || ! is_array( $parsed_url ) )
865
- return new WP_Error( 'import_file_error', 'Invalid URL' );
866
-
867
- // Ensure url is valid
868
- $url = str_replace( " ", '%20', $url );
869
-
870
- // Get the file
871
- $response = wp_remote_get( $url, array(
872
- 'timeout' => 10
873
- ) );
874
-
875
- if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 )
876
- return new WP_Error( 'import_file_error', 'Error getting remote image' );
877
-
878
- // Ensure we have a file name and type
879
- if ( ! $wp_filetype['type'] ) {
880
-
881
- $headers = wp_remote_retrieve_headers( $response );
882
-
883
- if ( isset( $headers['content-disposition'] ) && strstr( $headers['content-disposition'], 'filename=' ) ) {
884
-
885
- $disposition = end( explode( 'filename=', $headers['content-disposition'] ) );
886
- $disposition = sanitize_file_name( $disposition );
887
- $file_name = $disposition;
888
-
889
- } elseif ( isset( $headers['content-type'] ) && strstr( $headers['content-type'], 'image/' ) ) {
890
-
891
- $file_name = 'image.' . str_replace( 'image/', '', $headers['content-type'] );
892
-
893
- }
894
-
895
- unset( $headers );
896
- }
897
-
898
- // Upload the file
899
- $upload = wp_upload_bits( $file_name, '', wp_remote_retrieve_body( $response ) );
900
 
901
- if ( $upload['error'] )
902
- return new WP_Error( 'upload_dir_error', $upload['error'] );
 
 
 
903
 
904
- // Get filesize
905
- $filesize = filesize( $upload['file'] );
 
 
906
 
907
- if ( 0 == $filesize ) {
908
- @unlink( $upload['file'] );
909
- unset( $upload );
910
- return new WP_Error( 'import_file_error', __('Zero size file downloaded', 'order-import-export-for-woocommerce') );
911
- }
 
 
 
 
 
912
 
913
- unset( $response );
 
 
 
 
 
 
914
 
915
- return $upload;
916
- }
917
- private function handle_ftp()
918
- {
919
- $enable_ftp_ie = !empty( $_POST['enable_ftp_ie'] ) ? true : false;
920
- if($enable_ftp_ie == false)
921
- {
922
- $settings_in_db = get_option( 'wf_coupon_tracking_importer_ftp', null );
923
- $settings_in_db['enable_ftp_ie'] = false;
924
- update_option( 'wf_coupon_tracking_importer_ftp', $settings_in_db );
925
- return false;
926
  }
927
-
928
- $ftp_server = ! empty( $_POST['ftp_server'] ) ? $_POST['ftp_server'] : '';
929
- $ftp_server_path = ! empty( $_POST['ftp_server_path'] ) ? $_POST['ftp_server_path'] : '';
930
- $ftp_user = ! empty( $_POST['ftp_user'] ) ? $_POST['ftp_user'] : '';
931
- $ftp_password = ! empty( $_POST['ftp_password'] ) ? $_POST['ftp_password'] : '';
932
- $use_ftps = ! empty( $_POST['use_ftps'] ) ? true : false;
933
-
934
-
935
- $settings = array();
936
- $settings[ 'ftp_server' ] = $ftp_server;
937
- $settings[ 'ftp_user' ] = $ftp_user;
938
- $settings[ 'ftp_password' ] = $ftp_password;
939
- $settings[ 'use_ftps' ] = $use_ftps;
940
- $settings[ 'enable_ftp_ie' ] = $enable_ftp_ie;
941
- $settings[ 'ftp_server_path' ] = $ftp_server_path;
942
-
943
-
944
- $local_file = 'wp-content/plugins/order-import-export-for-woocommerce/temp-import.csv';
945
- $server_file = $ftp_server_path;
946
-
947
- update_option( 'wf_coupon_tracking_importer_ftp', $settings );
948
-
949
- $ftp_conn = $use_ftps ? ftp_ssl_connect($ftp_server) : ftp_connect($ftp_server);
950
- $error_message = "";
951
- $success = false;
952
- if($ftp_conn == false){
953
- $error_message = "There is connection problem\n";
954
- }
955
-
956
- if(empty($error_message)){
957
- if(ftp_login($ftp_conn, $ftp_user, $ftp_password) == false){
958
- $error_message = "Not able to login \n";
959
- }
960
- }
961
- if(empty($error_message)){
962
-
963
- if (ftp_get($ftp_conn, ABSPATH.$local_file, $server_file, FTP_BINARY)) {
964
- $error_message = "";
965
- $success = true;
966
- } else {
967
- $error_message = "There was a problem\n";
968
- }
969
- }
970
-
971
- ftp_close($ftp_conn);
972
- if($success){
973
- $this->file_url = $local_file;
974
- }else{
975
- die($error_message);
976
- }
977
- return true;
978
- }
979
-
980
- // Display import page title
981
- public function header() {
982
- echo '<div class="wrap"><div class="icon32" id="icon-woocommerce-importer"><br></div>';
983
- echo '<h2>' . ( empty( $_GET['merge'] ) ? __( 'Import', 'order-import-export-for-woocommerce' ) : __( 'Merge Coupons', 'order-import-export-for-woocommerce' ) ) . '</h2>';
984
- }
985
-
986
- // Close div.wrap
987
- public function footer() {
988
- echo '</div>';
989
- }
990
-
991
- /**
992
- * Display introductory text and file upload form
993
- */
994
- public function greet()
995
- {
996
- $action = 'admin.php?import=coupon_csv&amp;step=1&amp;merge=' . ( ! empty( $_GET['merge'] ) ? 1 : 0 );
997
- $bytes = apply_filters( 'import_upload_size_limit', wp_max_upload_size() );
998
- $size = size_format( $bytes );
999
- $upload_dir = wp_upload_dir();
1000
- $ftp_settings = get_option( 'wf_coupon_tracking_importer_ftp');
1001
- include( 'views-coupon/html-wf-import-greeting.php' );
1002
- }
1003
-
1004
- /**
1005
- * Added to http_request_timeout filter to force timeout at 60 seconds during import
1006
- * @return int 60
1007
- */
1008
- public function bump_request_timeout( $val ) {
1009
- return 60;
1010
- }
1011
-
1012
- public function hf_coupon_log_data_change ($content = 'coupon-csv-import',$data='')
1013
- {
1014
- if (WC()->version < '2.7.0')
1015
- {
1016
- $this->log->add($content,$data);
1017
- }else
1018
- {
1019
- $context = array( 'source' => $content );
1020
- $this->log->log("debug", $data ,$context);
1021
- }
1022
- }
1023
-
1024
  }
10
 
11
  class WF_CpnImpExpCsv_Coupon_Import extends WP_Importer {
12
 
13
+ var $id;
14
+ var $file_url;
15
+ var $delimiter;
16
+ // var $merge_empty_cells;
17
+ // mappings from old information to new
18
+ var $processed_posts = array();
19
+ // Results
20
+ var $import_results = array();
21
 
22
+ /**
23
+ * Constructor
24
+ */
25
+ public function __construct() {
26
+ if (WC()->version < '2.7.0') {
27
+ $this->log = new WC_Logger();
28
+ } else {
29
+ $this->log = wc_get_logger();
30
+ }
31
+ $this->import_page = 'coupon_csv';
32
+ $this->file_url_import_enabled = apply_filters( 'coupon_csv_coupon_file_url_import_enabled', true );
33
+ }
 
 
 
34
 
35
+ /**
36
+ * Registered callback function for the WordPress Importer
37
+ *
38
+ * Manages the three separate stages of the CSV import process
39
+ */
40
+ public function dispatch() {
41
+ global $woocommerce, $wpdb;
42
+ if ( ! empty( $_POST['delimiter'] ) ) {
43
+ $this->delimiter = stripslashes( trim( $_POST['delimiter'] ) );
44
+ }else if ( ! empty( $_GET['delimiter'] ) ) {
45
+ $this->delimiter = stripslashes( trim( $_GET['delimiter'] ) );
46
+ }
47
+ if ( ! $this->delimiter )
48
+ $this->delimiter = ',';
49
+ // if ( ! empty( $_POST['merge_empty_cells'] ) || ! empty( $_GET['merge_empty_cells'] ) ) {
50
+ // $this->merge_empty_cells = 1;
51
+ // } else{
52
+ // $this->merge_empty_cells = 0;
53
+ // }
54
+ $step = empty( $_GET['step'] ) ? 0 : (int) $_GET['step'];
55
+ switch ( $step ) {
56
+ case 0 :
57
+ $this->header();
58
+ $this->greet();
59
+ break;
60
+ case 1 :
61
+ $this->header();
62
+ check_admin_referer( 'import-upload' );
63
+ if(!empty($_GET['file_url']))
64
+ $this->file_url = esc_attr( $_GET['file_url'] );
65
+ if(!empty($_GET['file_id']))
66
+ $this->id = $_GET['file_id'] ;
67
+ if ( !empty($_GET['clearmapping']) || $this->handle_upload() )
68
+ $this->import_options();
69
+ else
70
+ //_e( 'Error with handle_upload!', 'order-import-export-for-woocommerce' );
71
+ wp_redirect(wp_get_referer().'&wf_coupon_ie_msg=3');
72
+ exit;
73
+ break;
74
+ case 2 :
75
+ $this->header();
76
+ check_admin_referer( 'import-woocommerce' );
77
+ $this->id = (int) $_POST['import_id'];
78
+ if ( $this->file_url_import_enabled )
79
+ $this->file_url = esc_attr( $_POST['import_url'] );
80
+ if ( $this->id )
81
+ $file = get_attached_file( $this->id );
82
+ else if ( $this->file_url_import_enabled )
83
+ $file = ABSPATH . $this->file_url;
84
+ $file = str_replace( "\\", "/", $file );
85
+ if ( $file ) {
86
+ ?>
87
+ <table id="import-progress" class="widefat_importer widefat">
88
+ <thead>
89
+ <tr>
90
+ <th class="status">&nbsp;</th>
91
+ <th class="row"><?php _e( 'Row', 'order-import-export-for-woocommerce' ); ?></th>
92
+ <th><?php _e( 'Coupon Id', 'order-import-export-for-woocommerce' ); ?></th>
93
+ <th><?php _e( 'Coupon Name', 'order-import-export-for-woocommerce' ); ?></th>
94
+ <th class="reason"><?php _e( 'Status Msg', 'order-import-export-for-woocommerce' ); ?></th>
95
+ </tr>
96
+ </thead>
97
+ <tfoot>
98
+ <tr class="importer-loading">
99
+ <td colspan="5"></td>
100
+ </tr>
101
+ </tfoot>
102
+ <tbody></tbody>
103
+ </table>
104
+ <script type="text/javascript">
105
+ jQuery(document).ready(function($) {
106
+ if ( ! window.console ) { window.console = function(){}; }
107
+ var processed_posts = [];
108
+ var i = 1;
109
+ var done_count = 0;
110
+ function import_rows( start_pos, end_pos ) {
111
+ var data = {
112
+ action: 'coupon_csv_import_request',
113
+ file: '<?php echo addslashes( $file ); ?>',
114
+ delimiter: '<?php echo $this->delimiter; ?>',
115
+ //merge_empty_cells: '<?php //echo $this->merge_empty_cells; ?>',
116
+ start_pos: start_pos,
117
+ end_pos: end_pos,
118
+ };
119
+ return $.ajax({
120
+ url: '<?php echo add_query_arg( array( 'import_page' => $this->import_page, 'step' => '3', 'merge' => ! empty( $_GET['merge'] ) ? '1' : '0' ), admin_url( 'admin-ajax.php' ) ); ?>',
121
+ data: data,
122
+ type: 'POST',
123
+ success: function( response ) {
124
+ if ( response ) {
125
+ try {
126
+ // Get the valid JSON only from the returned string
127
+ if ( response.indexOf("<!--WC_START-->") >= 0 )
128
+ response = response.split("<!--WC_START-->")[1]; // Strip off before after WC_START
129
+ if ( response.indexOf("<!--WC_END-->") >= 0 )
130
+ response = response.split("<!--WC_END-->")[0]; // Strip off anything after WC_END
131
+ // Parse
132
+ var results = $.parseJSON( response );
133
+ if ( results.error ) {
134
+ $('#import-progress tbody').append( '<tr id="row-' + i + '" class="error"><td class="status" colspan="5">' + results.error + '</td></tr>' );
135
+ i++;
136
+ } else if ( results.import_results && $( results.import_results ).size() > 0 ) {
137
+ $.each( results.processed_posts, function( index, value ) {
138
+ processed_posts.push( value );
139
+ });
140
+ $( results.import_results ).each(function( index, row ) {
141
+ $('#import-progress tbody').append( '<tr id="row-' + i + '" class="' + row['status'] + '"><td><mark class="result" title="' + row['status'] + '">' + row['status'] + '</mark></td><td class="row">' + i + '</td><td>' + row['post_id'] + '</td><td>' + row['post_title'] + '</td><td class="reason">' + row['reason'] + '</td></tr>' );
142
+ i++;
143
+ });
144
+ }
145
+ } catch(err) {}
146
+ } else {
147
+ $('#import-progress tbody').append( '<tr class="error"><td class="status" colspan="5">' + '<?php _e( 'AJAX Error', 'order-import-export-for-woocommerce' ); ?>' + '</td></tr>' );
148
+ }
149
+ var w = $(window);
150
+ var row = $( "#row-" + ( i - 1 ) );
151
+ if ( row.length ) {
152
+ w.scrollTop( row.offset().top - (w.height()/2) );
153
+ }
154
+ done_count++;
155
+ $('body').trigger( 'coupon_csv_import_request_complete' );
156
+ }
157
+ });
158
+ }
159
+ var rows = [];
160
+
161
+ <?php
162
+ $limit = apply_filters( 'coupon_csv_import_limit_per_request', 10 );
163
+ $enc = mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
164
+ if ( $enc )
165
+ setlocale( LC_ALL, 'en_US.' . $enc );
166
+ @ini_set( 'auto_detect_line_endings', true );
167
+
168
+ $count = 0;
169
+ $previous_position = 0;
170
+ $position = 0;
171
+ $import_count = 0;
172
+
173
+ // Get CSV positions
174
+ if ( ( $handle = fopen( $file, "r" ) ) !== FALSE ) {
175
+ while ( ( $postmeta = fgetcsv( $handle, 0, $this->delimiter) ) !== FALSE ) {
176
+ $count++;
177
+ if ( $count >= $limit ) {
178
+ $previous_position = $position;
179
+ $position = ftell( $handle );
180
+ $count = 0;
181
+ $import_count ++;
182
+ // Import rows between $previous_position $position
183
+ ?>rows.push( [ <?php echo $previous_position; ?>, <?php echo $position; ?> ] ); <?php
184
+ }
185
+ }
186
+ // Remainder
187
+ if ( $count > 0 ) {
188
+ ?>rows.push( [ <?php echo $position; ?>, '' ] ); <?php
189
+ $import_count ++;
190
+ }
191
+ fclose( $handle );
192
+ }
193
+ ?>
194
+
195
+ var data = rows.shift();
196
+ var regen_count = 0;
197
+ import_rows( data[0], data[1] );
198
+ $('body').on( 'coupon_csv_import_request_complete', function() {
199
+ if ( done_count == <?php echo $import_count; ?> ) {
200
+ import_done();
201
+ } else {
202
+ // Call next request
203
+ data = rows.shift();
204
+ import_rows( data[0], data[1] );
205
+ }
206
+ });
207
+ function import_done() {
208
+ var data = {
209
+ action: 'coupon_csv_import_request',
210
+ file: '<?php echo $file; ?>',
211
+ processed_posts: processed_posts,
212
+ };
213
+
214
+ $.ajax({
215
+ url: '<?php echo add_query_arg( array( 'import_page' => $this->import_page, 'step' => '4', 'merge' => ! empty( $_GET['merge'] ) ? 1 : 0 ), admin_url( 'admin-ajax.php' ) ); ?>',
216
+ data: data,
217
+ type: 'POST',
218
+ success: function( response ) {
219
+ //console.log( response );
220
+ $('#import-progress tbody').append( '<tr class="complete"><td colspan="5">' + response + '</td></tr>' );
221
+ $('.importer-loading').hide();
222
+ }
223
+ });
224
+ }
225
+ });
226
+ </script>
227
+ <?php
228
  } else {
229
+ echo '<p class="error">' . __( 'Error finding uploaded file!', 'order-import-export-for-woocommerce' ) . '</p>';
230
  }
231
+ break;
232
+ case 3 :
233
+ // Check access - cannot use nonce here as it will expire after multiple requests
234
+ if ( ! current_user_can( 'manage_woocommerce' ) )
235
+ die();
236
+ add_filter( 'http_request_timeout', array( $this, 'bump_request_timeout' ) );
237
+ if ( function_exists( 'gc_enable' ) )
238
+ gc_enable();
239
+ @set_time_limit(0);
240
+ @ob_flush();
241
+ @flush();
242
+ $wpdb->hide_errors();
243
+ $file = stripslashes( $_POST['file'] );
244
+ $start_pos = isset( $_POST['start_pos'] ) ? absint( $_POST['start_pos'] ) : 0;
245
+ $end_pos = isset( $_POST['end_pos'] ) ? absint( $_POST['end_pos'] ) : '';
246
+ $position = $this->import_start( $file, $start_pos, $end_pos );
247
+ $this->import();
248
+ $this->import_end();
249
+
250
+ $results = array();
251
+ $results['import_results'] = $this->import_results;
252
+ $results['processed_posts'] = $this->processed_posts;
253
+
254
+ echo "<!--WC_START-->";
255
+ echo json_encode( $results );
256
+ echo "<!--WC_END-->";
257
+ exit;
258
+ break;
259
+ case 4 :
260
+ // Check access - cannot use nonce here as it will expire after multiple requests
261
+ if ( ! current_user_can( 'manage_woocommerce' ) )
262
+ die();
263
+
264
+ add_filter( 'http_request_timeout', array( $this, 'bump_request_timeout' ) );
265
+
266
+ if ( function_exists( 'gc_enable' ) )
267
+ gc_enable();
268
+
269
+ @set_time_limit(0);
270
+ @ob_flush();
271
+ @flush();
272
+ $wpdb->hide_errors();
273
+
274
+ $this->processed_posts = isset( $_POST['processed_posts']) ? $_POST['processed_posts'] : array();
275
+
276
+ _e( 'Step 1...', 'order-import-export-for-woocommerce' ) . ' ';
277
+ wp_defer_term_counting( true );
278
+ wp_defer_comment_counting( true );
279
+ _e( 'Step 2...', 'order-import-export-for-woocommerce' ) . ' ';
280
+ echo 'Step 3...' . ' '; // Easter egg
281
+ _e( 'Finalizing...', 'order-import-export-for-woocommerce' ) . ' ';
282
+ // SUCCESS
283
+ _e( 'Finished. Import complete.', 'order-import-export-for-woocommerce' );
284
+ $this->import_end();
285
+ exit;
286
+ break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
  }
288
+ $this->footer();
289
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
 
291
+ /**
292
+ * format_data_from_csv
293
+ */
294
+ public function format_data_from_csv( $data, $enc ) {
295
+ return ( $enc == 'UTF-8' ) ? $data : utf8_encode( $data );
296
+ }
297
 
298
+ /**
299
+ * Display pre-import options
300
+ */
301
+ public function import_options(){
302
+ $j = 0;
303
+ if ( $this->id )
304
+ $file = get_attached_file( $this->id );
305
+ else if ( $this->file_url_import_enabled )
306
+ $file = ABSPATH . $this->file_url;
307
+ else
308
+ return;
309
+ // Set locale
310
+ $enc = mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
311
+ if ( $enc ) setlocale( LC_ALL, 'en_US.' . $enc );
312
+ @ini_set( 'auto_detect_line_endings', true );
313
+ // Get headers
314
+ if ( ( $handle = fopen( $file, "r" ) ) !== FALSE ){
315
+ $row = $raw_headers = array();
316
+ $header = fgetcsv( $handle, 0, $this->delimiter );
317
+ while ( ( $postmeta = fgetcsv( $handle, 0, $this->delimiter ) ) !== FALSE ){
318
+ foreach ( $header as $key => $heading ){
319
+ if ( ! $heading ) continue;
320
+ $s_heading = strtolower( $heading );
321
+ $row[$s_heading] = ( isset( $postmeta[$key] ) ) ? $this->format_data_from_csv( $postmeta[$key], $enc ) : '';
322
+ $raw_headers[ $s_heading ] = $heading;
323
+ }
324
+ break;
325
+ }
326
+ fclose( $handle );
327
+ }
328
+ $merge = (!empty($_GET['merge']) && $_GET['merge']) ? 1 : 0;
329
+ include( 'views-coupon/html-wf-import-options.php' );
330
+ }
331
 
332
+ /**
333
+ * The main controller for the actual import stage.
334
+ */
335
+ public function import(){
336
+ wp_suspend_cache_invalidation( true );
337
+ $this->hf_coupon_log_data_change( 'coupon-csv-import', '---' );
338
+ $this->hf_coupon_log_data_change( 'coupon-csv-import', __( 'Processing coupons.', 'order-import-export-for-woocommerce' ) );
339
+ foreach ( $this->parsed_data as $key => &$item ){
340
+ //$coupon = $this->parser->parse_coupon( $item, $this->merge_empty_cells );
341
+ $coupon = $this->parser->parse_coupon( $item);
342
+ if ( ! is_wp_error( $coupon ) )
343
+ $this->process_coupon( $coupon);
344
+ else
345
+ $this->add_import_result( 'failed', $coupon->get_error_message(), 'Not parsed', json_encode( $item ) );
346
+ unset( $item, $coupon );
347
+ }
348
+ $this->hf_coupon_log_data_change( 'coupon-csv-import', __( 'Finished processing coupons.', 'order-import-export-for-woocommerce' ) );
349
+ wp_suspend_cache_invalidation( false );
350
+ }
351
 
352
+ /**
353
+ * Parses the CSV file and prepares us for the task of processing parsed data
354
+ *
355
+ * @param string $file Path to the CSV file for importing
356
+ */
357
+ public function import_start( $file, $start_pos, $end_pos) {
358
+ $memory = size_format( (WC()->version < '2.7.0')?woocommerce_let_to_num( ini_get( 'memory_limit' ) ):wc_let_to_num( ini_get( 'memory_limit' ) ) );
359
+ $wp_memory = size_format( (WC()->version < '2.7.0')? woocommerce_let_to_num( WP_MEMORY_LIMIT ) : wc_let_to_num( WP_MEMORY_LIMIT ) );
360
+ $this->hf_coupon_log_data_change( 'coupon-csv-import', '---[ New Import ] PHP Memory: ' . $memory . ', WP Memory: ' . $wp_memory );
361
+ $this->hf_coupon_log_data_change( 'coupon-csv-import', __( 'Parsing coupons CSV.', 'order-import-export-for-woocommerce' ) );
362
+ $this->parser = new WF_CSV_Parser_Coupon( 'shop_coupon' );
363
+ list( $this->parsed_data, $this->raw_headers, $position ) = $this->parser->parse_data( $file, $this->delimiter, $start_pos, $end_pos);
364
+ $this->hf_coupon_log_data_change( 'coupon-csv-import', __( 'Finished parsing coupons CSV.', 'order-import-export-for-woocommerce' ) );
365
+ unset( $import_data );
366
+ wp_defer_term_counting( true );
367
+ wp_defer_comment_counting( true );
368
+ return $position;
369
+ }
370
 
371
+ /**
372
+ * Performs post-import cleanup of files and the cache
373
+ */
374
+ public function import_end() {
375
+ do_action( 'import_end' );
376
+ }
377
 
378
+ /**
379
+ * Handles the CSV upload and initial parsing of the file to prepare for
380
+ * displaying author import options
381
+ *
382
+ * @return bool False if error uploading or invalid file, true otherwise
383
+ */
384
+ public function handle_upload() {
385
+ if ( empty( $_POST['file_url'] ) ) {
386
+ $file = wp_import_handle_upload();
387
+ if ( isset( $file['error'] ) ) {
388
+ echo '<p><strong>' . __( 'Sorry, there has been an error.', 'order-import-export-for-woocommerce' ) . '</strong><br />';
389
+ echo esc_html( $file['error'] ) . '</p>';
390
+ return false;
391
+ }
392
+ $this->id = (int) $file['id'];
393
+ return true;
394
+ } else {
395
+ if ( file_exists( ABSPATH . $_POST['file_url'] ) ){
396
+ $this->file_url = esc_attr( $_POST['file_url'] );
397
+ return true;
398
+ } else {
399
+ echo '<p><strong>' . __( 'Sorry, there has been an error.', 'order-import-export-for-woocommerce' ) . '</strong></p>';
400
+ return false;
401
+ }
402
+ }
403
+ return false;
404
+ }
405
 
406
+ public function coupon_exists( $title, $ID = '', $post_name = '' ){
407
+ global $wpdb;
408
+ // Post Title Check
409
+ $post_title = stripslashes( sanitize_post_field( 'post_title', $title, 0, 'db' ) );
410
+ $query = "SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_coupon' AND post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )";
411
+ $args = array();
412
+ if ( ! empty ( $post_name ) ) {
413
+ $query .= ' AND post_name = %s';
414
+ $args[] = $post_name;
415
+ }
416
+ if ( ! empty ( $args ) ) {
417
+ $posts_that_exist = $wpdb->get_col( $wpdb->prepare( $query, $args ) );
418
+ if ( $posts_that_exist ) {
419
+ foreach( $posts_that_exist as $post_exists ) {
420
+ if ( $ID == $post_exists ) {
421
+ return true;
422
+ }
423
+ }
424
+ }
425
+ }
426
+ return false;
427
+ }
428
 
429
+ /**
430
+ * Create new posts based on import information
431
+ */
432
+ public function process_coupon($post) {
433
  $processing_coupon_id = absint($post['post_id']);
434
  $processing_coupon = get_post($processing_coupon_id);
435
  $processing_coupon_title = $processing_coupon ? $processing_coupon->post_title : '';
441
  }
442
  $post['post_type'] = 'shop_coupon';
443
 
 
444
  if (!empty($processing_coupon_id) && isset($this->processed_posts[$processing_coupon_id])) {
445
  $this->add_import_result('skipped', __('Coupon already processed', 'order-import-export-for-woocommerce'), $processing_coupon_id, $processing_coupon_title);
446
  $this->hf_coupon_log_data_change('coupon-csv-import', __('> Coupon ID already processed. Skipping.', 'order-import-export-for-woocommerce'), true);
454
  unset($post);
455
  return;
456
  }
457
+ $is_post_exist_in_db = get_post_type($processing_coupon_id);
458
  if (!$merging) {
459
  if ($this->coupon_exists($processing_coupon_title, $processing_coupon_id, $post['post_name'])) {
460
  if (!$processing_coupon_id) {
468
  return;
469
  }
470
 
471
+ if ($processing_coupon_id && is_string(get_post_status($processing_coupon_id)) && ($is_post_exist_in_db == $post['post_type'] )) {
472
+ $this->add_import_result('skipped', __('Coupon with same ID already exists.', 'order-import-export-for-woocommerce'), $processing_coupon_id, get_the_title($processing_coupon_id));
473
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('> &#8220;%s&#8221; ID already exists.', 'order-import-export-for-woocommerce'), esc_html($processing_coupon_id)), true);
474
  unset($post);
475
  return;
476
  }
477
+
478
+ if ( $processing_coupon_id && is_string( get_post_status( $processing_coupon_id ) ) && ($is_post_exist_in_db !== $post['post_type'] ) ) {
479
+ $this->add_import_result( 'skipped', __( 'Importing coupon(ID) conflicts with an existing post.', 'wf_order_import_export' ), $processing_coupon_id, get_the_title( $processing_coupon_id ) );
480
+ $this->hf_coupon_log_data_change( 'coupon-csv-import', sprintf( __('> &#8220;%s&#8221; ID already exists.', 'wf_order_import_export'), esc_html( $processing_coupon_id ) ), true );
481
+ unset( $post );
482
+ return;
483
+ }
484
  }
485
+ if ($merging && $processing_coupon_id && !empty($is_post_exist_in_db) && ($is_post_exist_in_db !== $post['post_type'] )) {
486
+ $this->add_import_result('skipped', __('Importing coupon(ID) conflicts with an existing post which is not a coupon.', 'order-import-export-for-woocommerce'), $processing_coupon_id, $processing_coupon_title);
 
 
 
487
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('> &#8220;%s&#8221; is not a coupon.', 'order-import-export-for-woocommerce'), esc_html($processing_coupon_id)), true);
 
488
  unset($post);
489
  return;
490
  }
491
 
492
  if ($merging && !empty($is_post_exist_in_db)) {
493
  $post_id = $processing_coupon_id;
 
494
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('> Merging coupon ID %s.', 'order-import-export-for-woocommerce'), $post_id), true);
495
+ $postdata = array('ID' => $post_id);
496
+
497
+ // if ($this->merge_empty_cells) {
498
+ // if (isset($post['post_content'])) {
499
+ // $postdata['post_content'] = $post['post_content'];
500
+ // }
501
+ // if (isset($post['post_excerpt'])) {
502
+ // $postdata['post_excerpt'] = $post['post_excerpt'];
503
+ // }
504
+ // } else {
 
 
 
505
  if (!empty($post['post_content'])) {
506
  $postdata['post_content'] = $post['post_content'];
507
  }
508
  if (!empty($post['post_excerpt'])) {
509
  $postdata['post_excerpt'] = $post['post_excerpt'];
510
  }
511
+ // }
 
512
  if (!empty($post['post_title'])) {
513
  $postdata['post_title'] = $post['post_title'];
514
  }
 
515
  if (!empty($post['post_author'])) {
516
  $postdata['post_author'] = absint($post['post_author']);
517
  }
527
  if (!empty($post['post_status'])) {
528
  $postdata['post_status'] = $post['post_status'];
529
  }
 
530
  if (sizeof($postdata) > 1) {
531
  $result = wp_update_post($postdata);
 
532
  if (!$result) {
533
  $this->add_import_result('failed', __('Failed to update coupon', 'order-import-export-for-woocommerce'), $post_id, $processing_coupon_title);
534
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('> Failed to update coupon %s', 'order-import-export-for-woocommerce'), $post_id), true);
540
  }
541
  } else {
542
  $merging = FALSE;
 
543
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('> Inserting %s', 'order-import-export-for-woocommerce'), esc_html($processing_coupon_title)), true);
544
  $postdata = array(
545
  'import_id' => $post['post_id'],
557
  $post_id = wp_insert_post($postdata, true);
558
 
559
  if (is_wp_error($post_id)) {
 
560
  $this->add_import_result('failed', __('Failed to import coupon', 'order-import-export-for-woocommerce'), $processing_coupon_id, $processing_coupon_title);
561
  $this->hf_coupon_log_data_change('coupon-csv-import', sprintf(__('Failed to import coupon &#8220;%s&#8221;', 'order-import-export-for-woocommerce'), esc_html($processing_coupon_title)));
562
  unset($post);
580
  if ($key) {
581
  if ($key == 'product_categories' || $key == 'exclude_product_categories') {
582
  update_post_meta($post_id, $key, explode(",", $meta['value']));
583
+ } elseif ($key == 'customer_email') {
584
+ $data = explode(',', $meta['value']);
585
+ update_post_meta($post_id, $key, $data);
586
+ } elseif ($key == 'expiry_date') {
587
+ $data = strtotime($meta['value']);
588
+ update_post_meta($post_id, 'date_expires', $data);
589
+ }else {
590
+ update_post_meta($post_id, $key, maybe_unserialize($meta['value']));
591
  }
592
  }
593
  }
604
  }
605
 
606
  /**
607
+ * Log a row's import status
608
+ */
609
+ protected function add_import_result( $status, $reason, $post_id = '', $post_title = '' ) {
610
+ $this->import_results[] = array(
611
+ 'post_title' => $post_title,
612
+ 'post_id' => $post_id,
613
+ 'status' => $status,
614
+ 'reason' => $reason
615
+ );
616
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
617
 
618
+ // Display import page title
619
+ public function header() {
620
+ echo '<div class="wrap"><div class="icon32" id="icon-woocommerce-importer"><br></div>';
621
+ echo '<h2>' . ( empty( $_GET['merge'] ) ? __( 'Import', 'order-import-export-for-woocommerce' ) : __( 'Merge Coupons', 'order-import-export-for-woocommerce' ) ) . '</h2>';
622
+ }
623
 
624
+ // Close div.wrap
625
+ public function footer() {
626
+ echo '</div>';
627
+ }
628
 
629
+ /**
630
+ * Display introductory text and file upload form
631
+ */
632
+ public function greet() {
633
+ $action = 'admin.php?import=coupon_csv&amp;step=1&amp;merge=' . ( ! empty( $_GET['merge'] ) ? 1 : 0 );
634
+ $bytes = apply_filters( 'import_upload_size_limit', wp_max_upload_size() );
635
+ $size = size_format( $bytes );
636
+ $upload_dir = wp_upload_dir();
637
+ include( 'views-coupon/html-wf-import-greeting.php' );
638
+ }
639
 
640
+ /**
641
+ * Added to http_request_timeout filter to force timeout at 60 seconds during import
642
+ * @return int 60
643
+ */
644
+ public function bump_request_timeout( $val ) {
645
+ return 60;
646
+ }
647
 
648
+ public function hf_coupon_log_data_change ($content = 'coupon-csv-import',$data=''){
649
+ if (WC()->version < '2.7.0'){
650
+ $this->log->add($content,$data);
651
+ }else{
652
+ $context = array( 'source' => $content );
653
+ $this->log->log("debug", $data ,$context);
 
 
 
 
 
654
  }
655
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
656
  }
includes/importer/class-wf-cpnimpexpcsv-importer.php CHANGED
File without changes
includes/importer/class-wf-csv-parser-coupon.php CHANGED
@@ -3,221 +3,167 @@
3
  * WooCommerce CSV Importer class for managing parsing of CSV files.
4
  */
5
  class WF_CSV_Parser_Coupon {
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_coupon_types; // Allowed product types
14
-
15
- /**
16
- * Constructor
17
- */
18
- public function __construct( $post_type = 'shop_coupon' )
19
- {
20
- $this->post_type = $post_type;
21
- $this->reserved_fields = include( 'data-coupon/data-wf-reserved-fields.php' );
22
- $this->post_defaults = include( 'data-coupon/data-wf-post-defaults.php' );
23
- $this->postmeta_defaults = include( 'data-coupon/data-wf-postmeta-defaults.php' );
24
- $this->postmeta_allowed = include( 'data-coupon/data-wf-postmeta-allowed.php' );
25
- $this->allowed_coupon_types = array(
26
- 'fixed_cart' ,
27
- 'percent',
28
- 'fixed_product',
29
- 'percent_product'
30
- );
31
-
32
- }
33
-
34
- /**
35
- * Format data from the csv file
36
- * @param string $data
37
- * @param string $enc
38
- * @return string
39
- */
40
- public function format_data_from_csv( $data, $enc ) {
41
- return ( $enc == 'UTF-8' ) ? $data : utf8_encode( $data );
42
- }
43
-
44
- /**
45
- * Parse the data
46
- * @param string $file [description]
47
- * @param string $delimiter [description]
48
- * @param array $mapping [description]
49
- * @param integer $start_pos [description]
50
- * @param integer $end_pos [description]
51
- * @return array
52
- */
53
- public function parse_data( $file, $delimiter, $mapping, $start_pos = 0, $end_pos = null, $eval_field ) {
54
- // Set locale
55
- $enc = mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
56
- if ( $enc )
57
- setlocale( LC_ALL, 'en_US.' . $enc );
58
- @ini_set( 'auto_detect_line_endings', true );
59
-
60
- $parsed_data = array();
61
- $raw_headers = array();
62
-
63
- // Put all CSV data into an associative array
64
- if ( ( $handle = fopen( $file, "r" ) ) !== FALSE ) {
65
-
66
- $header = fgetcsv( $handle, 0, $delimiter , '"', '"' );
67
- if ( $start_pos != 0 )
68
- fseek( $handle, $start_pos );
69
-
70
- while ( ( $postmeta = fgetcsv( $handle, 0, $delimiter , '"', '"' ) ) !== FALSE ) {
71
- $row = array();
72
-
73
- foreach ( $header as $key => $heading ) {
74
- // Heading is the lowercase version of the column name
75
- $s_heading = strtolower( $heading );
76
-
77
- if ( $s_heading == '' )
78
- continue;
79
-
80
- // Add the heading to the parsed data
81
- $row[$s_heading] = ( isset( $postmeta[$key] ) ) ? $this->format_data_from_csv( $postmeta[$key], $enc ) : '';
82
-
83
- // Raw Headers stores the actual column name in the CSV
84
- $raw_headers[ $s_heading ] = $heading;
85
- }
86
- $parsed_data[] = $row;
87
-
88
- unset( $postmeta, $row );
89
-
90
- $position = ftell( $handle );
91
-
92
- if ( $end_pos && $position >= $end_pos )
93
- break;
94
- }
95
- fclose( $handle );
96
- }
97
- return array( $parsed_data, $raw_headers, $position );
98
- }
99
-
100
-
101
- /**
102
- * Parse product
103
- * @param array $item
104
- * @param integer $merge_empty_cells
105
- * @return array
106
- */
107
- public function parse_coupon( $item, $merge_empty_cells = 0 ) {
108
- global $WF_CSV_Coupon_Import, $wpdb;
109
- $this->row++;
110
-
111
- $terms_array = $postmeta = $product = array();
112
- $attributes = $default_attributes = $gpf_data = null;
113
- // Merging
114
- $merging = ( ! empty( $_GET['merge'] ) && $_GET['merge'] ) ? true : false;
115
- $this->post_defaults['post_type'] = 'shop_coupon';
116
-
117
- $post_id = ( ! empty( $item['id'] ) ) ? $item['id'] : 0;
118
- $post_id = ( ! empty( $item['post_id'] ) ) ? $item['post_id'] : $post_id;
119
- if ( $merging )
120
- {
121
- $product['merging'] = true;
122
- $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', sprintf( __('> Row %s - preparing for merge.', 'order-import-export-for-woocommerce'), $this->row ) );
123
- if ( ! $post_id )
124
- {
125
- $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', __( '> > Cannot merge without id or sku. Importing instead.', 'order-import-export-for-woocommerce') );
126
-
127
- $merging = false;
128
- } else
129
- {
130
- if ( ! $post_id )
131
- {
132
  $post_db_type = $this->post_defaults['post_type'];
133
  $post_pass_type = '"'.$post_db_type.'"';
134
- $db_query = $wpdb->prepare("
135
- SELECT $wpdb->posts.ID
136
- FROM $wpdb->posts
137
- LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
138
- WHERE $wpdb->posts.post_type = $post_pass_type
139
- AND $wpdb->posts.post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )
140
- AND $wpdb->posts.ID = '%d'
141
- ", $item['ID']);
142
- $found_product_id = $wpdb->get_var($db_query);
143
- if ( ! $found_product_id )
144
- {
145
- $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', sprintf(__( '> > Skipped. Cannot find coupon with sku %s. Importing instead.', 'order-import-export-for-woocommerce'), $item['sku']) );
146
- $merging = false;
147
-
148
- } else
149
- {
150
-
151
- $post_id = $found_product_id;
152
- $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', sprintf(__( '> > Found coupon with ID %s.', 'order-import-export-for-woocommerce'), $post_id) );
153
-
154
- }
155
- }
156
- $product['merging'] = true;
157
- }
158
- }
159
-
160
- if ( ! $merging )
161
- {
162
-
163
- $product['merging'] = false;
164
- $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', sprintf( __('> Row %s - preparing for import.', 'order-import-export-for-woocommerce'), $this->row ) );
165
- if ( isset($item['post_parent']) && $item['post_parent']=== '' && $item['post_title']=== '') {
166
- $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', __( '> > Skipped. No post_title set for new coupon.', 'order-import-export-for-woocommerce') );
167
- return new WP_Error( 'parse-error', __( 'No post_title set for new coupon.', 'order-import-export-for-woocommerce' ) );
168
- }
169
- if ( isset($item['post_parent']) && $item['post_parent']!== '' && $item['post_parent']!== null && $item['parent_sku'] === '' )
170
- {
171
- $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', __( '> > Skipped. No parent set for new variation product.', 'order-import-export-for-woocommerce') );
172
  return new WP_Error( 'parse-error', __( 'No parent set for new variation product.', 'order-import-export-for-woocommerce' ) );
173
- }
174
- }
175
-
176
- $product['post_id'] = $post_id;
177
- foreach ( $this->post_defaults as $column => $default )
178
- {
179
- if ( isset( $item[ $column ] ) ) $product[ $column ] = $item[ $column ];
180
- }
181
-
182
- // Get custom fields
183
- foreach ( $this->postmeta_defaults as $column => $default )
184
- {
185
- if ( isset( $item[$column] ) )
186
- $postmeta[$column] = (string) $item[$column];
187
- elseif ( isset( $item[$column] ) )
188
- $postmeta[$column] = (string) $item[$column];
189
-
190
- // Check custom fields are valid
191
- if ( isset( $postmeta[$column] ) && isset( $this->postmeta_allowed[$column] ) && ! in_array( $postmeta[$column], $this->postmeta_allowed[$column] ) )
192
- {
193
- $postmeta[$column] = $this->postmeta_defaults[$column];
194
- }
195
- }
196
-
197
- if ( ! $merging )
198
- {
199
- // Merge post meta with defaults
200
- $product = wp_parse_args( $product, $this->post_defaults );
201
- $postmeta = wp_parse_args( $postmeta, $this->postmeta_defaults );
202
- }
203
- if ( ! empty( $product['post_status'] ) )
204
- {
205
- if ( ! in_array( $product['post_status'], array( 'publish', 'private', 'draft', 'pending', 'future', 'inherit', 'trash' ) ) ) {
206
- $product['post_status'] = 'publish';
207
- }
208
-
209
- if ( ! in_array( $product['post_status'], array( 'private', 'publish' ) ) ) {
210
- $product['post_status'] = 'publish';
211
- }
212
-
213
- }
214
- foreach ( $postmeta as $key => $value ) {
215
- $product['postmeta'][] = array( 'key' => esc_attr($key), 'value' => $value );
216
- }
217
-
218
- $product['post_title'] = ( ! empty( $item['post_title'] ) ) ? $item['post_title'] : '';
219
- unset( $item, $terms_array, $postmeta, $attributes, $gpf_data, $images );
220
- return $product;
221
- }
222
-
223
  }
3
  * WooCommerce CSV Importer class for managing parsing of CSV files.
4
  */
5
  class WF_CSV_Parser_Coupon {
6
+ var $row;
7
+ var $post_type;
8
+ var $reserved_fields; // Fields we map/handle (not custom fields)
9
+ var $post_defaults; // Default post data
10
+ var $postmeta_defaults; // default post meta
11
+ var $postmeta_allowed; // post meta validation
12
+
13
+ /**
14
+ * Constructor
15
+ */
16
+ public function __construct( $post_type = 'shop_coupon' ) {
17
+ $this->post_type = $post_type;
18
+ $this->reserved_fields = include( 'data-coupon/data-wf-reserved-fields.php' );
19
+ $this->post_defaults = include( 'data-coupon/data-wf-post-defaults.php' );
20
+ $this->postmeta_defaults = include( 'data-coupon/data-wf-postmeta-defaults.php' );
21
+ $this->postmeta_allowed = include( 'data-coupon/data-wf-postmeta-allowed.php' );
22
+ }
23
+
24
+ /**
25
+ * Format data from the csv file
26
+ * @param string $data
27
+ * @param string $enc
28
+ * @return string
29
+ */
30
+ public function format_data_from_csv( $data, $enc ) {
31
+ return ( $enc == 'UTF-8' ) ? $data : utf8_encode( $data );
32
+ }
33
+
34
+ /**
35
+ * Parse the data
36
+ * @param string $file [description]
37
+ * @param string $delimiter [description]
38
+ * @param integer $start_pos [description]
39
+ * @param integer $end_pos [description]
40
+ * @return array
41
+ */
42
+ public function parse_data( $file, $delimiter, $start_pos = 0, $end_pos = null) {
43
+ // Set locale
44
+ $enc = mb_detect_encoding( $file, 'UTF-8, ISO-8859-1', true );
45
+ if ( $enc )
46
+ setlocale( LC_ALL, 'en_US.' . $enc );
47
+ @ini_set( 'auto_detect_line_endings', true );
48
+ $parsed_data = array();
49
+ $raw_headers = array();
50
+ // Put all CSV data into an associative array
51
+ if ( ( $handle = fopen( $file, "r" ) ) !== FALSE ) {
52
+ $header = fgetcsv( $handle, 0, $delimiter );
53
+ if ( $start_pos != 0 )
54
+ fseek( $handle, $start_pos );
55
+ while ( ( $postmeta = fgetcsv( $handle, 0, $delimiter , '"', '"' ) ) !== FALSE ) {
56
+ $row = array();
57
+ foreach ( $header as $key => $heading ) {
58
+ // Heading is the lowercase version of the column name
59
+ $s_heading = strtolower( $heading );
60
+ if ( $s_heading == '' )
61
+ continue;
62
+ // Add the heading to the parsed data
63
+ $row[$s_heading] = ( isset( $postmeta[$key] ) ) ? $this->format_data_from_csv( $postmeta[$key], $enc ) : '';
64
+ // Raw Headers stores the actual column name in the CSV
65
+ $raw_headers[ $s_heading ] = $heading;
66
+ }
67
+ $parsed_data[] = $row;
68
+ unset( $postmeta, $row );
69
+ $position = ftell( $handle );
70
+ if ( $end_pos && $position >= $end_pos )
71
+ break;
72
+ }
73
+ fclose( $handle );
74
+ }
75
+ return array( $parsed_data, $raw_headers, $position );
76
+ }
77
+
78
+
79
+ /**
80
+ * Parse Coupons
81
+ * @param array $item
82
+ * @return array
83
+ */
84
+ public function parse_coupon( $item ) {
85
+ global $WF_CSV_Coupon_Import, $wpdb;
86
+ $this->row++;
87
+ $postmeta = $coupon = array();
88
+ // Merging
89
+ $merging = ( ! empty( $_GET['merge'] ) && $_GET['merge'] ) ? true : false;
90
+ $this->post_defaults['post_type'] = 'shop_coupon';
91
+ $post_id = ( ! empty( $item['id'] ) ) ? $item['id'] : 0;
92
+ $post_id = ( ! empty( $item['post_id'] ) ) ? $item['post_id'] : $post_id;
93
+ if ( $merging ) {
94
+ $coupon['merging'] = true;
95
+ $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', sprintf( __('> Row %s - preparing for merge.', 'order-import-export-for-woocommerce'), $this->row ) );
96
+ if ( ! $post_id ) {
97
+ $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', __( '> > Cannot merge without id or sku. Importing instead.', 'order-import-export-for-woocommerce') );
98
+ $merging = false;
99
+ } else {
100
+ if ( ! $post_id ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  $post_db_type = $this->post_defaults['post_type'];
102
  $post_pass_type = '"'.$post_db_type.'"';
103
+ $db_query = $wpdb->prepare("SELECT $wpdb->posts.ID
104
+ FROM $wpdb->posts
105
+ LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
106
+ WHERE $wpdb->posts.post_type = $post_pass_type
107
+ AND $wpdb->posts.post_status IN ( 'publish', 'private', 'draft', 'pending', 'future' )
108
+ AND $wpdb->posts.ID = '%d'
109
+ ", $item['ID']);
110
+ $found_product_id = $wpdb->get_var($db_query);
111
+ if ( ! $found_product_id ) {
112
+ $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', sprintf(__( '> > Skipped. Cannot find coupon with sku %s. Importing instead.', 'order-import-export-for-woocommerce'), $item['sku']) );
113
+ $merging = false;
114
+ } else {
115
+ $post_id = $found_product_id;
116
+ $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', sprintf(__( '> > Found coupon with ID %s.', 'order-import-export-for-woocommerce'), $post_id) );
117
+ }
118
+ }
119
+ $coupon['merging'] = true;
120
+ }
121
+ }
122
+ if ( ! $merging ) {
123
+ $coupon['merging'] = false;
124
+ $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', sprintf( __('> Row %s - preparing for import.', 'order-import-export-for-woocommerce'), $this->row ) );
125
+ if ( isset($item['post_parent']) && $item['post_parent']=== '' && $item['post_title']=== '') {
126
+ $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', __( '> > Skipped. No post_title set for new coupon.', 'order-import-export-for-woocommerce') );
127
+ return new WP_Error( 'parse-error', __( 'No post_title set for new coupon.', 'order-import-export-for-woocommerce' ) );
128
+ }
129
+ if ( isset($item['post_parent']) && $item['post_parent']!== '' && $item['post_parent']!== null && $item['parent_sku'] === '' ) {
130
+ $WF_CSV_Coupon_Import->hf_coupon_log_data_change( 'coupon-csv-import', __( '> > Skipped. No parent set for new variation product.', 'order-import-export-for-woocommerce') );
 
 
 
 
 
 
 
 
 
 
131
  return new WP_Error( 'parse-error', __( 'No parent set for new variation product.', 'order-import-export-for-woocommerce' ) );
132
+ }
133
+ }
134
+ $coupon['post_id'] = $post_id;
135
+ foreach ( $this->post_defaults as $column => $default ) {
136
+ if ( isset( $item[ $column ] ) ) $coupon[ $column ] = $item[ $column ];
137
+ }
138
+ // Get custom fields
139
+ foreach ( $this->postmeta_defaults as $column => $default ) {
140
+ if ( isset( $item[$column] ) )
141
+ $postmeta[$column] = (string) $item[$column];
142
+ elseif ( isset( $item[$column] ) )
143
+ $postmeta[$column] = (string) $item[$column];
144
+ // Check custom fields are valid
145
+ if ( isset( $postmeta[$column] ) && isset( $this->postmeta_allowed[$column] ) && ! in_array( $postmeta[$column], $this->postmeta_allowed[$column] ) ) {
146
+ $postmeta[$column] = $this->postmeta_defaults[$column];
147
+ }
148
+ }
149
+ if ( ! $merging ) {
150
+ // Merge post meta with defaults
151
+ $coupon = wp_parse_args( $coupon, $this->post_defaults );
152
+ $postmeta = wp_parse_args( $postmeta, $this->postmeta_defaults );
153
+ }
154
+ if ( ! empty( $coupon['post_status'] ) ) {
155
+ if ( ! in_array( $coupon['post_status'], array( 'publish', 'private', 'draft', 'pending', 'future', 'inherit', 'trash' ) ) ) {
156
+ $coupon['post_status'] = 'publish';
157
+ }
158
+ if ( ! in_array( $coupon['post_status'], array( 'private', 'publish' ) ) ) {
159
+ $coupon['post_status'] = 'publish';
160
+ }
161
+ }
162
+ foreach ( $postmeta as $key => $value ) {
163
+ $coupon['postmeta'][] = array( 'key' => esc_attr($key), 'value' => $value );
164
+ }
165
+ $coupon['post_title'] = ( ! empty( $item['post_title'] ) ) ? $item['post_title'] : '';
166
+ unset( $item, $postmeta );
167
+ return $coupon;
168
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  }
includes/importer/class-wf-csv-parser.php CHANGED
@@ -99,11 +99,11 @@ class WF_CSV_Parser {
99
  // Put all CSV data into an associative array
100
  if (( $handle = fopen($file, "r") ) !== FALSE) {
101
 
102
- $header = fgetcsv($handle, 0, $delimiter, '"', '"');
103
  if ($start_pos != 0)
104
  fseek($handle, $start_pos);
105
 
106
- while (( $postmeta = fgetcsv($handle, 0, $delimiter, '"', '"') ) !== FALSE) {
107
  $row = array();
108
 
109
  foreach ($header as $key => $heading) {
@@ -278,6 +278,7 @@ class WF_CSV_Parser {
278
 
279
 
280
  if (!empty($item['status'])) {
 
281
  $found_status = false;
282
  $available_statuses = array();
283
  foreach ($shop_order_status as $status_slug => $status_name) {
@@ -292,13 +293,13 @@ class WF_CSV_Parser {
292
  unset($item);
293
  return;
294
  }
295
- } else {
296
- $item['status'] = 'processing';
297
  }
298
 
299
- if (!empty($item['order_date']))
300
  $item['date'] = $item['order_date'];
301
-
 
 
302
  if (!empty($item['date'])) {
303
  if(preg_match("/^(\d{2})-(\d{2})-(\d{2}) (\d{1}|\d{2}):(\d{2})$/", $item['date'])){
304
  $item['date'] = date_create_from_format('d-m-y H:i', $item['date']);
@@ -311,8 +312,7 @@ class WF_CSV_Parser {
311
  unset($item);
312
  return;
313
  }
314
- } else {
315
- $item['date'] = time();
316
  }
317
 
318
 
@@ -322,8 +322,7 @@ class WF_CSV_Parser {
322
  }
323
 
324
  // build the order data object
325
- $order['status'] = $item['status'];
326
- $order['date'] = $item['date'];
327
  $order['order_comments'] = !empty($item['customer_note']) ? $item['customer_note'] : null;
328
  $order['notes'] = $order_notes;
329
  if (!is_null($order_number))
@@ -341,79 +340,85 @@ class WF_CSV_Parser {
341
  switch ($column) {
342
 
343
  case 'shipping_method':
344
- $value = isset($item[$column]) ? $item[$column] : '';
345
-
346
- // look up shipping method by id or title
347
- $shipping_method = isset($available_methods[$value]) ? $value : null;
348
-
349
- if (!$shipping_method) {
350
- // try by title
351
- foreach ($available_methods as $method) {
352
- if (0 === strcasecmp($method->title, $value)) {
353
- $shipping_method = $method->id;
354
- break; // go with the first one we find
 
 
355
  }
356
  }
357
- }
358
 
359
- if ($shipping_method) {
360
- //known shipping method found
361
- $postmeta[] = array('key' => '_shipping_method', 'value' => $shipping_method);
362
- $postmeta[] = array('key' => '_shipping_method_title', 'value' => $available_methods[$shipping_method]->title);
363
- } elseif ($csv_export_file && $value) {
364
- //Order CSV Export format, shipping method title with no corresponding shipping method type found, so just use the title
365
- $postmeta[] = array('key' => '_shipping_method', 'value' => '');
366
- $postmeta[] = array('key' => '_shipping_method_title', 'value' => $value);
367
- } elseif ($value) {
368
- //Shipping method but no title
369
- $postmeta[] = array('key' => '_shipping_method', 'value' => $value);
370
- $postmeta[] = array('key' => '_shipping_method_title', 'value' => '');
371
- } else {
372
- //none
373
- $postmeta[] = array('key' => '_shipping_method', 'value' => '');
374
- $postmeta[] = array('key' => '_shipping_method_title', 'value' => '');
 
375
  }
376
  break;
377
 
378
  case 'payment_method':
379
- $value = isset($item[$column]) ? $item[$column] : '';
380
-
381
- // look up shipping method by id or title
382
- $payment_method = isset($available_gateways[$value]) ? $value : null;
383
- if (!$payment_method) {
384
- // try by title
385
- foreach ($available_gateways as $method) {
386
- if (0 === strcasecmp($method->title, $value)) {
387
- $payment_method = $method->id;
388
- break; // go with the first one we find
 
 
389
  }
390
  }
391
- }
392
 
393
- if ($payment_method) {
394
- //Known payment method found
395
- $postmeta[] = array('key' => '_payment_method', 'value' => $payment_method);
396
- $postmeta[] = array('key' => '_payment_method_title', 'value' => $available_gateways[$payment_method]->title);
397
- } elseif ($csv_export_file && $value) {
398
- //Order CSV Export format, payment method title with no corresponding payments method type found, so just use the title
399
- $postmeta[] = array('key' => '_payment_method', 'value' => '');
400
- $postmeta[] = array('key' => '_payment_method_title', 'value' => $value);
401
- } elseif ($value) {
402
- //payment method but no title
403
- $postmeta[] = array('key' => '_payment_method', 'value' => $value);
404
- $postmeta[] = array('key' => '_payment_method_title', 'value' => '');
405
- } else {
406
- //none
407
- $postmeta[] = array('key' => '_payment_method', 'value' => '');
408
- $postmeta[] = array('key' => '_payment_method_title', 'value' => '');
 
409
  }
410
  break;
411
 
412
  // handle numerics
413
  case 'order_shipping': // legacy
414
  case 'shipping_total':
415
- $order_shipping = isset($item[$column]) ? $item[$column] : 0; // save the order shipping total for later use
416
- $postmeta[] = array('key' => '_order_shipping', 'value' => number_format((float) $order_shipping, 2, '.', ''));
 
 
417
  break;
418
  case 'order_shipping_tax': // legacy
419
  case 'shipping_tax_total':
@@ -432,18 +437,22 @@ class WF_CSV_Parser {
432
  case 'order_discount':
433
  case 'cart_discount':
434
  case 'order_total':
435
- $value = isset($item[$column]) ? $item[$column] : 0;
436
- $postmeta[] = array('key' => '_' . $column, 'value' => number_format((float) $value, 2, '.', ''));
 
 
437
  break;
438
 
439
  case 'billing_country':
440
  case 'shipping_country':
441
- $value = isset($item[$column]) ? $item[$column] : '';
442
- // support country name or code by converting to code
443
- $country_code = array_search($value, WC()->countries->countries);
444
- if ($country_code)
445
- $value = $country_code;
446
- $postmeta[] = array('key' => '_' . $column, 'value' => $value);
 
 
447
  break;
448
 
449
  case 'Download Permissions Granted':
@@ -459,35 +468,17 @@ class WF_CSV_Parser {
459
  }
460
  break;
461
 
462
- default: $postmeta[] = array('key' => '_' . $column, 'value' => isset($item[$column]) ? $item[$column] : "");
 
 
 
 
463
  }
464
  }
465
 
466
  if (!empty($item['customer_id']))
467
  $postmeta[] = array('key' => '_customer_user', 'value' => $item['customer_id']);
468
 
469
- // Get any custom meta fields
470
- foreach ($item as $key => $value) {
471
-
472
- if (!$value) {
473
- continue;
474
- }
475
-
476
- // Handle meta: columns - import as custom fields
477
- if (strstr($key, 'meta:')) {
478
-
479
- // Get meta key name
480
- $meta_key = ( isset($raw_headers[$key]) ) ? $raw_headers[$key] : $key;
481
- $meta_key = trim(str_replace('meta:', '', $meta_key));
482
-
483
- // Add to postmeta array
484
- $postmeta[] = array(
485
- 'key' => esc_attr($meta_key),
486
- 'value' => $value,
487
- );
488
- }
489
- }
490
-
491
  $order_shipping_methods = array();
492
  $_shipping_methods = array();
493
 
@@ -562,10 +553,10 @@ class WF_CSV_Parser {
562
  $order_items = array();
563
  if ($csv_export_file) {
564
  // standard format
565
- if (!empty($item['line_item_1'])) {
566
  // one or more order items
567
  $i = 1;
568
- while (!empty($item['line_item_' . $i])) {
569
 
570
  // $_item_meta = preg_split("~\\\\.(*SKIP)(*FAIL)|\|~s", $item['line_item_' . $i]);
571
  $_item_meta = array();
@@ -630,7 +621,6 @@ class WF_CSV_Parser {
630
 
631
  $item_meta[$name] = $value;
632
  }
633
-
634
  $order_items[] = array('product_id' => $product_id, 'qty' => $qty, 'total' => $total,'tax' => $tax, 'tax_data' => $tax_data, 'meta' => $item_meta, 'unknown_product_name' => $unknown_product_name);
635
 
636
  $i++;
@@ -667,12 +657,11 @@ class WF_CSV_Parser {
667
  $tax_items = array();
668
 
669
  // standard tax item format which supports multiple tax items in numbered columns containing a pipe-delimated, colon-labeled format
670
- if (!empty($item['tax_items'])) {
671
  // one or more order tax items
672
  // get the first tax item
673
  $tax_item = explode(';', $item['tax_items']);
674
-
675
- $tax_amount_sum = $shipping_tax_amount_sum = 0;
676
  foreach ($tax_item as $tax) {
677
 
678
  $tax_item_data = array();
@@ -690,7 +679,6 @@ class WF_CSV_Parser {
690
 
691
  // have a tax amount or shipping tax amount
692
  if (isset($tax_item_data['total']) || isset($tax_item_data['shipping_tax_amount'])) {
693
-
694
  // try and look up rate id by label if needed
695
  if (isset($tax_item_data['label']) && $tax_item_data['label'] && !$tax_item_data['rate_id']) {
696
  foreach ($tax_rates as $tax_rate) {
@@ -739,38 +727,38 @@ class WF_CSV_Parser {
739
  );
740
 
741
  // sum up the order totals, in case it wasn't part of the import
742
- $tax_amount_sum += $tax_item_data['total'];
743
- $shipping_tax_amount_sum += $tax_item_data['shipping_tax_amount'];
744
  }
745
  }
746
 
747
- if (!is_numeric($order_tax)) {
748
- $order_tax = $tax_amount_sum;
749
- }
750
- if (!is_numeric($order_shipping_tax)) {
751
- $order_shipping_tax = $shipping_tax_amount_sum;
752
- }
753
  }
754
 
755
  // default to zero if not set
756
- if (!is_numeric($order_tax)) {
757
- $order_tax = 0;
758
- }
759
- if (!is_numeric($order_shipping_tax)) {
760
- $order_shipping_tax = 0;
761
- }
762
  // no tax items specified, so create a default one using the tax totals
763
- if (0 == count($tax_items)) {
764
-
765
- $tax_items[] = array(
766
- 'title' => '',
767
- 'rate_id' => 0,
768
- 'label' => 'Tax',
769
- 'compound' => '',
770
- 'tax_amount' => $order_tax,
771
- 'shipping_tax_amount' => $order_shipping_tax,
772
- );
773
- }
774
 
775
  // add the order tax totals to the order meta
776
  $postmeta[] = array('key' => '_order_tax', 'value' => number_format((float) $order_tax, 2, '.', ''));
99
  // Put all CSV data into an associative array
100
  if (( $handle = fopen($file, "r") ) !== FALSE) {
101
 
102
+ $header = fgetcsv($handle, 0, $delimiter);
103
  if ($start_pos != 0)
104
  fseek($handle, $start_pos);
105
 
106
+ while (( $postmeta = fgetcsv($handle, 0, $delimiter) ) !== FALSE) {
107
  $row = array();
108
 
109
  foreach ($header as $key => $heading) {
278
 
279
 
280
  if (!empty($item['status'])) {
281
+ $order['status'] = $item['status'];
282
  $found_status = false;
283
  $available_statuses = array();
284
  foreach ($shop_order_status as $status_slug => $status_name) {
293
  unset($item);
294
  return;
295
  }
 
 
296
  }
297
 
298
+ if (!empty($item['order_date'])){
299
  $item['date'] = $item['order_date'];
300
+ } elseif (isset($item['order_date'])) {
301
+ $item['date'] = time();
302
+ }
303
  if (!empty($item['date'])) {
304
  if(preg_match("/^(\d{2})-(\d{2})-(\d{2}) (\d{1}|\d{2}):(\d{2})$/", $item['date'])){
305
  $item['date'] = date_create_from_format('d-m-y H:i', $item['date']);
312
  unset($item);
313
  return;
314
  }
315
+ $order['date'] = $item['date'];
 
316
  }
317
 
318
 
322
  }
323
 
324
  // build the order data object
325
+ $order['order_id'] = !empty($item['order_id']) ? $item['order_id'] : null;
 
326
  $order['order_comments'] = !empty($item['customer_note']) ? $item['customer_note'] : null;
327
  $order['notes'] = $order_notes;
328
  if (!is_null($order_number))
340
  switch ($column) {
341
 
342
  case 'shipping_method':
343
+ if(isset($item[$column])){
344
+ $value = $item[$column];
345
+
346
+ // look up shipping method by id or title
347
+ $shipping_method = isset($available_methods[$value]) ? $value : null;
348
+
349
+ if (!$shipping_method) {
350
+ // try by title
351
+ foreach ($available_methods as $method) {
352
+ if (0 === strcasecmp($method->title, $value)) {
353
+ $shipping_method = $method->id;
354
+ break; // go with the first one we find
355
+ }
356
  }
357
  }
 
358
 
359
+ if ($shipping_method) {
360
+ //known shipping method found
361
+ $postmeta[] = array('key' => '_shipping_method', 'value' => $shipping_method);
362
+ $postmeta[] = array('key' => '_shipping_method_title', 'value' => $available_methods[$shipping_method]->title);
363
+ } elseif ($csv_export_file && $value) {
364
+ //Order CSV Export format, shipping method title with no corresponding shipping method type found, so just use the title
365
+ $postmeta[] = array('key' => '_shipping_method', 'value' => '');
366
+ $postmeta[] = array('key' => '_shipping_method_title', 'value' => $value);
367
+ } elseif ($value) {
368
+ //Shipping method but no title
369
+ $postmeta[] = array('key' => '_shipping_method', 'value' => $value);
370
+ $postmeta[] = array('key' => '_shipping_method_title', 'value' => '');
371
+ } else {
372
+ //none
373
+ $postmeta[] = array('key' => '_shipping_method', 'value' => '');
374
+ $postmeta[] = array('key' => '_shipping_method_title', 'value' => '');
375
+ }
376
  }
377
  break;
378
 
379
  case 'payment_method':
380
+ if (isset($item[$column])) {
381
+ $value = $item[$column];
382
+
383
+ // look up shipping method by id or title
384
+ $payment_method = isset($available_gateways[$value]) ? $value : null;
385
+ if (!$payment_method) {
386
+ // try by title
387
+ foreach ($available_gateways as $method) {
388
+ if (0 === strcasecmp($method->title, $value)) {
389
+ $payment_method = $method->id;
390
+ break; // go with the first one we find
391
+ }
392
  }
393
  }
 
394
 
395
+ if ($payment_method) {
396
+ //Known payment method found
397
+ $postmeta[] = array('key' => '_payment_method', 'value' => $payment_method);
398
+ $postmeta[] = array('key' => '_payment_method_title', 'value' => $available_gateways[$payment_method]->title);
399
+ } elseif ($csv_export_file && $value) {
400
+ //Order CSV Export format, payment method title with no corresponding payments method type found, so just use the title
401
+ $postmeta[] = array('key' => '_payment_method', 'value' => '');
402
+ $postmeta[] = array('key' => '_payment_method_title', 'value' => $value);
403
+ } elseif ($value) {
404
+ //payment method but no title
405
+ $postmeta[] = array('key' => '_payment_method', 'value' => $value);
406
+ $postmeta[] = array('key' => '_payment_method_title', 'value' => '');
407
+ } else {
408
+ //none
409
+ $postmeta[] = array('key' => '_payment_method', 'value' => '');
410
+ $postmeta[] = array('key' => '_payment_method_title', 'value' => '');
411
+ }
412
  }
413
  break;
414
 
415
  // handle numerics
416
  case 'order_shipping': // legacy
417
  case 'shipping_total':
418
+ if (isset($item[$column])) {
419
+ $order_shipping = $item[$column]; // save the order shipping total for later use
420
+ $postmeta[] = array('key' => '_order_shipping', 'value' => number_format((float) $order_shipping, 2, '.', ''));
421
+ }
422
  break;
423
  case 'order_shipping_tax': // legacy
424
  case 'shipping_tax_total':
437
  case 'order_discount':
438
  case 'cart_discount':
439
  case 'order_total':
440
+ if (isset($item[$column])) {
441
+ $value = $item[$column];
442
+ $postmeta[] = array('key' => '_' . $column, 'value' => number_format((float) $value, 2, '.', ''));
443
+ }
444
  break;
445
 
446
  case 'billing_country':
447
  case 'shipping_country':
448
+ if (isset($item[$column])) {
449
+ $value = $item[$column];
450
+ // support country name or code by converting to code
451
+ $country_code = array_search($value, WC()->countries->countries);
452
+ if ($country_code)
453
+ $value = $country_code;
454
+ $postmeta[] = array('key' => '_' . $column, 'value' => $value);
455
+ }
456
  break;
457
 
458
  case 'Download Permissions Granted':
468
  }
469
  break;
470
 
471
+ default:
472
+
473
+ if (isset($item[$column])){
474
+ $postmeta[] = array('key' => '_' . $column, 'value' => $item[$column]);
475
+ }
476
  }
477
  }
478
 
479
  if (!empty($item['customer_id']))
480
  $postmeta[] = array('key' => '_customer_user', 'value' => $item['customer_id']);
481
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
482
  $order_shipping_methods = array();
483
  $_shipping_methods = array();
484
 
553
  $order_items = array();
554
  if ($csv_export_file) {
555
  // standard format
556
+ if (isset($item['line_item_1']) && !empty($item['line_item_1'])) {
557
  // one or more order items
558
  $i = 1;
559
+ while (isset($item['line_item_' . $i]) && !empty($item['line_item_' . $i])) {
560
 
561
  // $_item_meta = preg_split("~\\\\.(*SKIP)(*FAIL)|\|~s", $item['line_item_' . $i]);
562
  $_item_meta = array();
621
 
622
  $item_meta[$name] = $value;
623
  }
 
624
  $order_items[] = array('product_id' => $product_id, 'qty' => $qty, 'total' => $total,'tax' => $tax, 'tax_data' => $tax_data, 'meta' => $item_meta, 'unknown_product_name' => $unknown_product_name);
625
 
626
  $i++;
657
  $tax_items = array();
658
 
659
  // standard tax item format which supports multiple tax items in numbered columns containing a pipe-delimated, colon-labeled format
660
+ if (isset($item['tax_items']) && !empty($item['tax_items'])) {
661
  // one or more order tax items
662
  // get the first tax item
663
  $tax_item = explode(';', $item['tax_items']);
664
+ // $tax_amount_sum = $shipping_tax_amount_sum = 0;
 
665
  foreach ($tax_item as $tax) {
666
 
667
  $tax_item_data = array();
679
 
680
  // have a tax amount or shipping tax amount
681
  if (isset($tax_item_data['total']) || isset($tax_item_data['shipping_tax_amount'])) {
 
682
  // try and look up rate id by label if needed
683
  if (isset($tax_item_data['label']) && $tax_item_data['label'] && !$tax_item_data['rate_id']) {
684
  foreach ($tax_rates as $tax_rate) {
727
  );
728
 
729
  // sum up the order totals, in case it wasn't part of the import
730
+ // $tax_amount_sum += $tax_item_data['total'];
731
+ // $shipping_tax_amount_sum += $tax_item_data['shipping_tax_amount'];
732
  }
733
  }
734
 
735
+ // if (!is_numeric($order_tax)) {
736
+ // $order_tax = $tax_amount_sum;
737
+ // }
738
+ // if (!is_numeric($order_shipping_tax)) {
739
+ // $order_shipping_tax = $shipping_tax_amount_sum;
740
+ // }
741
  }
742
 
743
  // default to zero if not set
744
+ // if (!is_numeric($order_tax)) {
745
+ // $order_tax = 0;
746
+ // }
747
+ // if (!is_numeric($order_shipping_tax)) {
748
+ // $order_shipping_tax = 0;
749
+ // }
750
  // no tax items specified, so create a default one using the tax totals
751
+ // if (0 == count($tax_items)) {
752
+ //
753
+ // $tax_items[] = array(
754
+ // 'title' => '',
755
+ // 'rate_id' => 0,
756
+ // 'label' => 'Tax',
757
+ // 'compound' => '',
758
+ // 'tax_amount' => $order_tax,
759
+ // 'shipping_tax_amount' => $order_shipping_tax,
760
+ // );
761
+ // }
762
 
763
  // add the order tax totals to the order meta
764
  $postmeta[] = array('key' => '_order_tax', 'value' => number_format((float) $order_tax, 2, '.', ''));
includes/importer/class-wf-orderimpexpcsv-order-import.php CHANGED
@@ -206,7 +206,7 @@ class WF_OrderImpExpCsv_Order_Import extends WP_Importer {
206
  // Get CSV positions
207
  if (( $handle = fopen($file, "r") ) !== FALSE) {
208
 
209
- while (( $postmeta = fgetcsv($handle, 0, $this->delimiter, '"', '"') ) !== FALSE) {
210
  $count++;
211
 
212
  if ($count >= $limit) {
@@ -375,11 +375,10 @@ class WF_OrderImpExpCsv_Order_Import extends WP_Importer {
375
 
376
  // Get headers
377
  if (( $handle = fopen($file, "r") ) !== FALSE) {
378
-
379
  $row = $raw_headers = array();
380
- $header = fgetcsv($handle, 0, $this->delimiter, '"', '"');
381
 
382
- while (( $postmeta = fgetcsv($handle, 0, $this->delimiter, '"', '"') ) !== FALSE) {
383
  foreach ($header as $key => $heading) {
384
  if (!$heading)
385
  continue;
@@ -539,16 +538,23 @@ class WF_OrderImpExpCsv_Order_Import extends WP_Importer {
539
  // check class-wc-checkout.php for reference
540
 
541
  $order_data = array(
542
- 'import_id' => $post['order_number'], //Suggest import to keep the given ID
543
- 'post_date' => date('Y-m-d H:i:s', $post['date']),
544
  'post_type' => 'shop_order',
545
- 'post_title' => 'Order &ndash; ' . date('F j, Y @ h:i A', $post['date']),
546
- 'post_status' => 'wc-' . preg_replace('/^wc-/', '', $post['status']),
547
  'ping_status' => 'closed',
548
- 'post_excerpt' => isset($post['order_comments']) ? ($post['order_comments']) : '',
549
  'post_author' => 1,
550
  'post_password' => uniqid('order_'), // Protects the post just in case
551
  );
 
 
 
 
 
 
 
 
 
 
 
552
 
553
 
554
  if (!$dry_run) {
@@ -558,7 +564,7 @@ class WF_OrderImpExpCsv_Order_Import extends WP_Importer {
558
 
559
  // Check if post exists when importing
560
  $new_added = false;
561
- $is_order_exist = $this->order_exists($post['order_number']);
562
  $meta_array = array();
563
  if (!empty($post['postmeta'])) {
564
  foreach ($post['postmeta'] as $meta) {
@@ -586,7 +592,7 @@ class WF_OrderImpExpCsv_Order_Import extends WP_Importer {
586
  return;
587
  } else {
588
  if ($is_order_exist) {
589
- $order_id = $post['order_number'];
590
  $order_data['ID'] = $order_id;
591
  $wp_result = wp_update_post($order_data);
592
  } else {
@@ -633,16 +639,17 @@ class WF_OrderImpExpCsv_Order_Import extends WP_Importer {
633
  }
634
  }
635
 
636
- if($merging && $is_order_exist){
637
- $coup_str = 'coupon';
638
- $wpdb->query( $wpdb->prepare( "DELETE FROM itemmeta USING {$wpdb->prefix}woocommerce_order_itemmeta itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items items WHERE itemmeta.order_item_id = items.order_item_id and items.order_id = %d and items.order_item_type != %s", $order_id ,$coup_str) );
639
- $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d and order_item_type != %s", $order_id ,$coup_str) );
640
- }
641
- $order = wc_get_order($order_id);
642
 
643
  // handle order items
644
  $order_items = array();
645
  $order_item_meta = null;
 
 
 
 
 
 
 
646
 
647
  foreach ($post['order_items'] as $item) {
648
 
@@ -725,24 +732,29 @@ class WF_OrderImpExpCsv_Order_Import extends WP_Importer {
725
  }
726
 
727
  // create the tax order items
728
- foreach ($post['tax_items'] as $tax_item) {
 
 
 
 
 
729
 
730
- $tax_order_item = array(
731
- 'order_item_name' => $tax_item['title'],
732
- 'order_item_type' => 'tax',
733
- );
734
 
735
- $tax_order_item_id = wc_add_order_item($order_id, $tax_order_item);
736
 
737
- if ($tax_order_item_id) {
738
- wc_add_order_item_meta($tax_order_item_id, 'rate_id', $tax_item['rate_id']);
739
- wc_add_order_item_meta($tax_order_item_id, 'label', $tax_item['label']);
740
- wc_add_order_item_meta($tax_order_item_id, 'compound', $tax_item['compound']);
741
- wc_add_order_item_meta($tax_order_item_id, 'tax_amount', $tax_item['tax_amount']);
742
- wc_add_order_item_meta($tax_order_item_id, 'shipping_tax_amount', $tax_item['shipping_tax_amount']);
 
743
  }
744
  }
745
-
746
  // Grant downloadalbe product permissions
747
  if ($add_download_permissions) {
748
  wc_downloadable_product_permissions($order_id);
@@ -786,7 +798,7 @@ class WF_OrderImpExpCsv_Order_Import extends WP_Importer {
786
  $order->add_order_note(sprintf(__("Original order #%s", 'order-import-export-for-woocommerce'), $post['order_number_formatted']));
787
 
788
  // get the order so we can display the correct order number
789
- $order = wc_get_order($order_id);
790
  }
791
 
792
  $this->processed_posts[$post['order_number_formatted']] = $post['order_number_formatted'];
@@ -796,8 +808,8 @@ class WF_OrderImpExpCsv_Order_Import extends WP_Importer {
796
  else
797
  $out_msg = 'Order Imported Successfully.';
798
 
799
- $this->add_import_result('imported', __($out_msg, 'order-import-export-for-woocommerce'), $order_id, $order_data['post_title'], $order_id);
800
- $this->hf_order_log_data_change('order-csv-import', sprintf(__('> &#8220;%s&#8221;' . $out_msg, 'order-import-export-for-woocommerce'), esc_html($order_data['post_title'])), true);
801
  $this->imported++;
802
  $this->hf_order_log_data_change('order-csv-import', sprintf(__('> Finished importing order %s', 'order-import-export-for-woocommerce'), $dry_run ? "" : $order->get_order_number() ));
803
 
206
  // Get CSV positions
207
  if (( $handle = fopen($file, "r") ) !== FALSE) {
208
 
209
+ while (( $postmeta = fgetcsv($handle, 0, $this->delimiter) ) !== FALSE) {
210
  $count++;
211
 
212
  if ($count >= $limit) {
375
 
376
  // Get headers
377
  if (( $handle = fopen($file, "r") ) !== FALSE) {
 
378
  $row = $raw_headers = array();
379
+ $header = fgetcsv($handle, 0, $this->delimiter);
380
 
381
+ while (( $postmeta = fgetcsv($handle, 0, $this->delimiter) ) !== FALSE) {
382
  foreach ($header as $key => $heading) {
383
  if (!$heading)
384
  continue;
538
  // check class-wc-checkout.php for reference
539
 
540
  $order_data = array(
541
+ 'import_id' => $post['order_id'], //Suggest import to keep the given ID
 
542
  'post_type' => 'shop_order',
 
 
543
  'ping_status' => 'closed',
 
544
  'post_author' => 1,
545
  'post_password' => uniqid('order_'), // Protects the post just in case
546
  );
547
+ if(!empty($post['date'])){
548
+ $order_data['post_date'] = date('Y-m-d H:i:s', $post['date']);
549
+ $order_data['post_date_gmt'] = date('Y-m-d H:i:s', $post['date']);
550
+ $order_data['post_title'] = 'Order &ndash; ' . date('F j, Y @ h:i A', $post['date']);
551
+ }
552
+ if(!empty($post['status'])){
553
+ $order_data['post_status'] = 'wc-' . preg_replace('/^wc-/', '', $post['status']);
554
+ }
555
+ if(!empty($post['order_comments'])){
556
+ $order_data['post_excerpt'] = $post['order_comments'];
557
+ }
558
 
559
 
560
  if (!$dry_run) {
564
 
565
  // Check if post exists when importing
566
  $new_added = false;
567
+ $is_order_exist = $this->order_exists($post['order_id']);
568
  $meta_array = array();
569
  if (!empty($post['postmeta'])) {
570
  foreach ($post['postmeta'] as $meta) {
592
  return;
593
  } else {
594
  if ($is_order_exist) {
595
+ $order_id = $post['order_id'];
596
  $order_data['ID'] = $order_id;
597
  $wp_result = wp_update_post($order_data);
598
  } else {
639
  }
640
  }
641
 
 
 
 
 
 
 
642
 
643
  // handle order items
644
  $order_items = array();
645
  $order_item_meta = null;
646
+ if ($merging && $is_order_exist && !empty($post['order_items'])) {
647
+ $wpdb->query($wpdb->prepare("DELETE items,itemmeta FROM {$wpdb->prefix}woocommerce_order_itemmeta itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items items ON itemmeta.order_item_id = items.order_item_id WHERE items.order_id = %d and items.order_item_type = 'line_item'", $order_id));
648
+ }
649
+ if ($merging && $is_order_exist && !empty($post['order_shipping'])) {
650
+ $wpdb->query($wpdb->prepare("DELETE items,itemmeta FROM {$wpdb->prefix}woocommerce_order_itemmeta itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items items ON itemmeta.order_item_id = items.order_item_id WHERE items.order_id = %d and items.order_item_type = 'shipping'", $order_id));
651
+ }
652
+ $order = wc_get_order($order_id);
653
 
654
  foreach ($post['order_items'] as $item) {
655
 
732
  }
733
 
734
  // create the tax order items
735
+ if(!empty($post['tax_items'])){
736
+ if ($merging && $is_order_exist) {
737
+ $tax_str = 'tax';
738
+ $wpdb->query($wpdb->prepare("DELETE items,itemmeta FROM {$wpdb->prefix}woocommerce_order_itemmeta itemmeta INNER JOIN {$wpdb->prefix}woocommerce_order_items items WHERE itemmeta.order_item_id = items.order_item_id and items.order_id = %d and items.order_item_type = %s", $order_id, $tax_str));
739
+ }
740
+ foreach ($post['tax_items'] as $tax_item) {
741
 
742
+ $tax_order_item = array(
743
+ 'order_item_name' => $tax_item['title'],
744
+ 'order_item_type' => 'tax',
745
+ );
746
 
747
+ $tax_order_item_id = wc_add_order_item($order_id, $tax_order_item);
748
 
749
+ if ($tax_order_item_id) {
750
+ wc_add_order_item_meta($tax_order_item_id, 'rate_id', $tax_item['rate_id']);
751
+ wc_add_order_item_meta($tax_order_item_id, 'label', $tax_item['label']);
752
+ wc_add_order_item_meta($tax_order_item_id, 'compound', $tax_item['compound']);
753
+ wc_add_order_item_meta($tax_order_item_id, 'tax_amount', $tax_item['tax_amount']);
754
+ wc_add_order_item_meta($tax_order_item_id, 'shipping_tax_amount', $tax_item['shipping_tax_amount']);
755
+ }
756
  }
757
  }
 
758
  // Grant downloadalbe product permissions
759
  if ($add_download_permissions) {
760
  wc_downloadable_product_permissions($order_id);
798
  $order->add_order_note(sprintf(__("Original order #%s", 'order-import-export-for-woocommerce'), $post['order_number_formatted']));
799
 
800
  // get the order so we can display the correct order number
801
+ // $order = wc_get_order($order_id);
802
  }
803
 
804
  $this->processed_posts[$post['order_number_formatted']] = $post['order_number_formatted'];
808
  else
809
  $out_msg = 'Order Imported Successfully.';
810
 
811
+ $this->add_import_result('imported', __($out_msg, 'order-import-export-for-woocommerce'), $order_id, isset($order_data['post_title']) ? $order_data['post_title'] : '', $order_id);
812
+ $this->hf_order_log_data_change('order-csv-import', sprintf(__('> &#8220;%s&#8221;' . $out_msg, 'order-import-export-for-woocommerce'), esc_html($order_id)), true);
813
  $this->imported++;
814
  $this->hf_order_log_data_change('order-csv-import', sprintf(__('> Finished importing order %s', 'order-import-export-for-woocommerce'), $dry_run ? "" : $order->get_order_number() ));
815
 
includes/importer/data-coupon/data-wf-post-defaults.php CHANGED
@@ -7,16 +7,13 @@ if ( ! defined( 'ABSPATH' ) ) {
7
  return array(
8
  'post_type' => 'shop_coupon',
9
  'menu_order' => '',
10
- 'postmeta' => array(),
11
  'post_status' => 'publish',
12
  'post_title' => '',
13
- 'post_name' => '',
14
- 'post_date' => '',
15
  'post_date_gmt' => '',
16
- //'post_content' => '',
17
  'post_excerpt' => '',
18
  'post_parent' => '',
19
- //'post_password' => '',
20
  'post_author' => '',
21
- //'comment_status'=> 'open'
22
  );
7
  return array(
8
  'post_type' => 'shop_coupon',
9
  'menu_order' => '',
10
+ 'postmeta' => array(),
11
  'post_status' => 'publish',
12
  'post_title' => '',
13
+ 'post_name' => '',
14
+ 'post_date' => '',
15
  'post_date_gmt' => '',
 
16
  'post_excerpt' => '',
17
  'post_parent' => '',
 
18
  'post_author' => '',
 
19
  );
includes/importer/data-coupon/data-wf-postmeta-defaults.php CHANGED
@@ -13,7 +13,8 @@ return apply_filters( 'coupon_csv_product_postmeta_defaults', array(
13
  'usage_limit' => '',
14
  'usage_limit_per_user' => '',
15
  'limit_usage_to_x_items' => '',
16
- 'expiry_date' => '',
 
17
  'free_shipping' => 'no',
18
  'exclude_sale_items' => 'no',
19
  'product_categories' => '',
13
  'usage_limit' => '',
14
  'usage_limit_per_user' => '',
15
  'limit_usage_to_x_items' => '',
16
+ 'expiry_date' => '', /* removed from WC version 3.6 onwards */
17
+ 'date_expires' => '',
18
  'free_shipping' => 'no',
19
  'exclude_sale_items' => 'no',
20
  'product_categories' => '',
includes/importer/data-coupon/data-wf-reserved-fields.php CHANGED
@@ -23,7 +23,8 @@ return array(
23
  'usage_limit',
24
  'usage_limit_per_user',
25
  'limit_usage_to_x_items',
26
- 'expiry_date',
 
27
  'free_shipping',
28
  'exclude_sale_items',
29
  'product_categories',
23
  'usage_limit',
24
  'usage_limit_per_user',
25
  'limit_usage_to_x_items',
26
+ 'expiry_date', /* removed in wc version 3.6 onwards */
27
+ 'date_expires',
28
  'free_shipping',
29
  'exclude_sale_items',
30
  'product_categories',
includes/importer/views-coupon/html-wf-import-options.php CHANGED
@@ -8,7 +8,7 @@
8
  <p class="submit">
9
  <input style="display:none" type="submit" class="button button-primary" value="<?php esc_attr_e('Submit', 'order-import-export-for-woocommerce'); ?>" />
10
  <input type="hidden" name="delimiter" value="<?php echo $this->delimiter ?>" />
11
- <input type="hidden" name="merge_empty_cells" value="<?php echo $this->merge_empty_cells ?>" />
12
  </p>
13
  </form>
14
  <script type="text/javascript">
8
  <p class="submit">
9
  <input style="display:none" type="submit" class="button button-primary" value="<?php esc_attr_e('Submit', 'order-import-export-for-woocommerce'); ?>" />
10
  <input type="hidden" name="delimiter" value="<?php echo $this->delimiter ?>" />
11
+ <?php /* <input type="hidden" name="merge_empty_cells" value="<?php echo $this->merge_empty_cells ?>" /> */ ?>
12
  </p>
13
  </form>
14
  <script type="text/javascript">
includes/importer/views/html-wf-import-options.php CHANGED
File without changes
includes/views/export/html-wf-export-coupons.php CHANGED
File without changes
includes/views/html-wf-admin-screen.php CHANGED
File without changes
includes/views/import/html-wf-import-coupons.php CHANGED
File without changes
includes/views/market.php CHANGED
File without changes
languages/wf_order_import_export-de_DE.mo CHANGED
File without changes
languages/wf_order_import_export-fr_FR.mo CHANGED
File without changes
order-import-export-for-woocommerce.php CHANGED
@@ -6,9 +6,9 @@ Plugin URI: https://wordpress.org/plugins/order-import-export-for-woocommerce/
6
  Description: Export and Import Order detail including line items, From and To your WooCommerce Store.
7
  Author: WebToffee
8
  Author URI: https://www.webtoffee.com/product/woocommerce-order-coupon-subscription-export-import/
9
- Version: 1.4.5
10
  Text Domain: order-import-export-for-woocommerce
11
- WC tested up to: 3.6.2
12
  License: GPLv3
13
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
14
  */
@@ -24,7 +24,7 @@ define("WF_CPN_IMP_EXP_ID", "wf_cpn_imp_exp");
24
  define("wf_coupon_csv_im_ex", "wf_coupon_csv_im_ex");
25
 
26
  if (!defined('WF_ORDERIMPEXP_CURRENT_VERSION')) {
27
- define("WF_ORDERIMPEXP_CURRENT_VERSION", "1.4.5");
28
  }
29
 
30
  /**
6
  Description: Export and Import Order detail including line items, From and To your WooCommerce Store.
7
  Author: WebToffee
8
  Author URI: https://www.webtoffee.com/product/woocommerce-order-coupon-subscription-export-import/
9
+ Version: 1.4.7
10
  Text Domain: order-import-export-for-woocommerce
11
+ WC tested up to: 3.6.3
12
  License: GPLv3
13
  License URI: https://www.gnu.org/licenses/gpl-3.0.html
14
  */
24
  define("wf_coupon_csv_im_ex", "wf_coupon_csv_im_ex");
25
 
26
  if (!defined('WF_ORDERIMPEXP_CURRENT_VERSION')) {
27
+ define("WF_ORDERIMPEXP_CURRENT_VERSION", "1.4.7");
28
  }
29
 
30
  /**
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: webtoffee
3
  Donate link: https://www.webtoffee.com/plugins/
4
  Tags: Order Export, Order Import, WooCommerce Export Orders , WooCommerce Import Orders , Export Orders, Import Orders
5
  Requires at least: 3.0.1
6
- Tested up to: 5.1.1
7
- Stable tag: 1.4.5
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -21,7 +21,7 @@ This is perfect tool if you are migrating an existing shop on a different eComme
21
  &#128312; Import Coupons from CSV file.
22
  &#128312; Export Subscription Orders to CSV file(Premium Feature).
23
  &#128312; Import Subscription Orders from CSV file(Premium Feature).
24
- &#128312; Tested OK with WooCommerce 3.6.2
25
  &#128312; Tested OK with PHP 7.3.5
26
 
27
  <blockquote>
@@ -111,6 +111,13 @@ Yes. You can import or export order line item details.
111
 
112
  == Changelog ==
113
 
 
 
 
 
 
 
 
114
  = 1.4.5 =
115
  * Tested OK with WC 3.6.2
116
  * New Feature:- Filters added in order export(offset & limit).
@@ -230,8 +237,7 @@ Yes. You can import or export order line item details.
230
  * Export /Import WooCommerce Orders.
231
 
232
  == Upgrade Notice ==
233
- = 1.4.5 =
234
- * Tested OK with WC 3.6.2
235
- * New Feature:- Filters added in order export(offset & limit).
236
- * Order notes optimisation.
237
- * Compatibility with PHP 7.3.5
3
  Donate link: https://www.webtoffee.com/plugins/
4
  Tags: Order Export, Order Import, WooCommerce Export Orders , WooCommerce Import Orders , Export Orders, Import Orders
5
  Requires at least: 3.0.1
6
+ Tested up to: 5.2
7
+ Stable tag: 1.4.7
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
21
  &#128312; Import Coupons from CSV file.
22
  &#128312; Export Subscription Orders to CSV file(Premium Feature).
23
  &#128312; Import Subscription Orders from CSV file(Premium Feature).
24
+ &#128312; Tested OK with WooCommerce 3.6.3
25
  &#128312; Tested OK with PHP 7.3.5
26
 
27
  <blockquote>
111
 
112
  == Changelog ==
113
 
114
+ = 1.4.7 =
115
+ * Tested OK with WP 5.2.1 and WC 3.6.3
116
+ * Bug Fix:- Order fields getting blank on updating when the fields are not present in CSV.
117
+ * Coupon import optimisation.
118
+ = 1.4.6 =
119
+ * Tested OK with WP 5.2
120
+ * Bug Fix:- Issue with Coupon Expiry Date export and import.
121
  = 1.4.5 =
122
  * Tested OK with WC 3.6.2
123
  * New Feature:- Filters added in order export(offset & limit).
237
  * Export /Import WooCommerce Orders.
238
 
239
  == Upgrade Notice ==
240
+ = 1.4.7 =
241
+ * Tested OK with WP 5.2.1 and WC 3.6.3
242
+ * Bug Fix:- Order fields getting blank on updating when the fields are not present in CSV.
243
+ * Coupon import optimisation.