Import users from CSV with meta - Version 1.15.4

Version Description

  • WooCommerce Subscriptions importer included to create subscriptions at the same time you are importing users
  • New hooks added
  • Code improved
Download this release

Release Info

Developer carazo
Plugin Icon 128x128 Import users from CSV with meta
Version 1.15.4
Comparing to
See all releases

Code changes from version 1.15.3.6 to 1.15.4

addons/woocommerce-membership.php CHANGED
@@ -42,7 +42,7 @@ function acui_wm_post_import_single_user( $headers, $row, $user_id ){
42
  $columns = array();
43
 
44
  foreach ( $keys as $key ) {
45
- $columns[ $key ] = array_search ( $key, $headers );
46
  }
47
 
48
  $membership_plan_id = isset( $columns['membership_plan_id'] ) && ! empty( $row[ $columns['membership_plan_id'] ] ) ? (int) $row[ $columns['membership_plan_id'] ] : null;
42
  $columns = array();
43
 
44
  foreach ( $keys as $key ) {
45
+ $columns[ $key ] = array_search( $key, $headers );
46
  }
47
 
48
  $membership_plan_id = isset( $columns['membership_plan_id'] ) && ! empty( $row[ $columns['membership_plan_id'] ] ) ? (int) $row[ $columns['membership_plan_id'] ] : null;
addons/woocommerce-subscriptions.php ADDED
@@ -0,0 +1,826 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) exit;
4
+
5
+ if( !is_plugin_active( 'woocommerce-subscriptions/woocommerce-subscriptions.php' ) ){
6
+ return;
7
+ }
8
+
9
+ class ACUI_WooCommerceSubscritpions{
10
+ private $all_virtual;
11
+
12
+ function __construct(){
13
+ add_filter( 'acui_restricted_fields', array( $this, 'restricted_fields' ), 10, 1 );
14
+ add_action( 'acui_header_table_extra_rows', array( $this, 'header_table_extra_rows' ) );
15
+ add_action( 'acui_documentation_after_plugins_activated', array( $this, 'documentation' ) );
16
+ add_action( 'after_acui_import_users', array( $this, 'end' ) );
17
+ add_action( 'post_acui_import_single_user', array( $this, 'import' ), 10, 3 );
18
+
19
+ $this->all_virtual = true;
20
+ }
21
+
22
+ function header_table_extra_rows(){
23
+ ?>
24
+ <th><?php _e( "WooCommerce Subscriptions import warnings", 'import-users-from-csv-with-meta' ); ?></th>
25
+ <th><?php _e( "WooCommerce Subscriptions import errors", 'import-users-from-csv-with-meta' ); ?></th>
26
+ <?php
27
+ }
28
+
29
+ function restricted_fields( $acui_restricted_fields ){
30
+ return array_merge( $acui_restricted_fields, $this->fields() );
31
+ }
32
+
33
+ function fields(){
34
+ return array_merge( $this->order_totals_fields(), array( 'subscription_status', 'start_date', 'trial_end_date', 'next_payment_date', 'end_date', 'billing_period', 'billing_interval', 'order_items', 'coupon_items', 'fee_items', 'tax_items', 'order_currency', 'shipping_method', 'download_permissions', 'order_notes', 'payment_method', 'payment_method_title', 'payment_method_post_meta', 'payment_method_user_meta', 'customer_note', 'custom_post_meta', 'custom_user_post_meta' ) );
35
+ }
36
+
37
+ function order_totals_fields(){
38
+ return array(
39
+ 'order_shipping',
40
+ 'order_shipping_tax',
41
+ 'cart_discount',
42
+ 'cart_discount_tax',
43
+ 'order_total',
44
+ 'order_tax',
45
+ );
46
+ }
47
+
48
+ function user_meta_fields(){
49
+ return array(
50
+ 'billing_first_name', // Billing Address Info
51
+ 'billing_last_name',
52
+ 'billing_company',
53
+ 'billing_address_1',
54
+ 'billing_address_2',
55
+ 'billing_city',
56
+ 'billing_state',
57
+ 'billing_postcode',
58
+ 'billing_country',
59
+ 'billing_email',
60
+ 'billing_phone',
61
+
62
+ 'shipping_first_name', // Shipping Address Info
63
+ 'shipping_last_name',
64
+ 'shipping_company',
65
+ 'shipping_address_1',
66
+ 'shipping_address_2',
67
+ 'shipping_city',
68
+ 'shipping_state',
69
+ 'shipping_postcode',
70
+ 'shipping_country',
71
+ );
72
+ }
73
+
74
+ function documentation(){
75
+ ?>
76
+ <tr valign="top">
77
+ <th scope="row"><?php _e( "WooCommerce Subscriptions is activated", 'import-users-from-csv-with-meta' ); ?></th>
78
+ <td>
79
+ <ol>
80
+ <li><?php _e( 'You can import subscriptions with their info', 'import-users-from-csv-with-meta' ); ?>.</li>
81
+ <li><?php printf( __( 'Data format: use the column names <a href="%s">described here</a>, except the ones that are not used because we have the own ones:', 'import-users-from-csv-with-meta' ), "https://github.com/woocommerce/woocommerce-subscriptions-importer-exporter#csv-columns" ); ?> customer_id, customer_email and customer_username.</li>
82
+ <li><?php printf( __( 'Download <a href="%s">this sample file</a> to see how it works', 'import-users-from-csv-with-meta' ), esc_url( plugins_url( 'samples/wcs-import-sample.csv', dirname( __FILE__ ) ) ) ); ?>.</li>
83
+ <li><?php printf( __( 'This subscription importer is based in the official <a href="%S">WooCommerce Subscription Importer Exporter</a>.', 'import-users-from-csv-with-meta' ), "https://github.com/woocommerce/woocommerce-subscriptions-importer-exporter" ); ?></li>
84
+ </ol>
85
+ </td>
86
+ </tr>
87
+ <?php
88
+ }
89
+
90
+ function end(){
91
+ $this->add_order_key_post_meta_if_missing();
92
+ }
93
+
94
+ function add_order_key_post_meta_if_missing() {
95
+ global $wpdb;
96
+
97
+ // Get the post_ids of the subscriptions whose order_key post meta is NULL or empty or missing
98
+ $subscription_ids_needing_order_key = $wpdb->get_results( "
99
+ SELECT ID FROM {$wpdb->prefix}posts WHERE
100
+ post_type = 'shop_subscription'
101
+ AND
102
+ ID NOT IN (
103
+ SELECT post_id FROM {$wpdb->prefix}postmeta WHERE
104
+ meta_key = '_order_key'
105
+ AND
106
+ meta_value IS NOT NULL
107
+ AND
108
+ meta_value <> ''
109
+ )
110
+ AND
111
+ post_status IN ( '" . implode( "','", array_keys( wcs_get_subscription_statuses() ) ) . "' )"
112
+ );
113
+
114
+ //Set the order_key post meta for each of them
115
+ foreach( $subscription_ids_needing_order_key as $key => $post ) {
116
+ update_post_meta( $post->ID, '_order_key', uniqid( 'order_' ) );
117
+ }
118
+ }
119
+
120
+ function import( $headers, $row, $user_id ){
121
+ foreach ( $this->fields() as $key ) {
122
+ $pos = array_search( $key, $headers );
123
+
124
+ if( $pos !== FALSE ){
125
+ $columns[ $key ] = $pos;
126
+ $data[ $key ] = $row[ $columns[ $key ] ];
127
+ }
128
+ }
129
+
130
+ global $wpdb;
131
+
132
+ $set_manual = $requires_manual_renewal = false;
133
+ $post_meta = $order_items = array();
134
+ $result = array(
135
+ 'warning' => array(),
136
+ 'error' => array(),
137
+ 'items' => '',
138
+ );
139
+
140
+ $missing_shipping_addresses = $missing_billing_addresses = array();
141
+
142
+ foreach ( array_merge( $this->order_totals_fields(), $this->user_meta_fields(), array( 'payment_method' ) ) as $column ) {
143
+ switch ( $column ) {
144
+ case 'cart_discount':
145
+ case 'cart_discount_tax':
146
+ case 'order_shipping':
147
+ case 'order_shipping_tax':
148
+ case 'order_total':
149
+ $value = ( ! empty( $data[ $column ] ) ) ? $data[ $column ] : 0;
150
+ $post_meta[] = array( 'key' => '_' . $column, 'value' => $value );
151
+ break;
152
+
153
+ case 'payment_method':
154
+ $payment_method = ( ! empty( $data[ $column ] ) ) ? strtolower( $data[ $column ] ) : '';
155
+ $title = ( ! empty( $data[ 'payment_method_title' ] ) ) ? $data[ 'payment_method_title' ] : $payment_method;
156
+
157
+ if ( ! empty( $payment_method ) && 'manual' != $payment_method ) {
158
+ $post_meta[] = array( 'key' => '_' . $column, 'value' => $payment_method );
159
+ $post_meta[] = array( 'key' => '_payment_method_title', 'value' => $title );
160
+ } else {
161
+ $set_manual = true;
162
+ }
163
+
164
+ if ( ! empty( $data[ 'requires_manual_renewal'] ) && 'true' == $data[ 'requires_manual_renewal'] ) {
165
+ $requires_manual_renewal = true;
166
+ }
167
+ break;
168
+
169
+ case 'shipping_address_1':
170
+ case 'shipping_city':
171
+ case 'shipping_postcode':
172
+ case 'shipping_state':
173
+ case 'shipping_country':
174
+ case 'billing_address_1':
175
+ case 'billing_city':
176
+ case 'billing_postcode':
177
+ case 'billing_state':
178
+ case 'billing_country':
179
+ case 'billing_phone':
180
+ case 'billing_company':
181
+ case 'billing_email':
182
+ $value = ( ! empty( $data[ $column ] ) ) ? $data[ $column ] : '';
183
+
184
+ if ( empty( $value ) ) {
185
+ $metadata = get_user_meta( $user_id, $column );
186
+ $value = ( ! empty( $metadata[0] ) ) ? $metadata[0] : '';
187
+ }
188
+
189
+ if ( empty( $value ) && 'billing_email' == $column ) {
190
+ $value = ( ! empty( $data[ 'customer_email'] ) ) ? $data[ 'customer_email'] : get_userdata( $user_id )->user_email;
191
+ }
192
+
193
+ if ( empty( $value ) ) {
194
+ if ( 0 === strpos( $column, 'billing_' ) ) {
195
+ $missing_billing_addresses[] = $column;
196
+ } else {
197
+ $missing_shipping_addresses[] = $column;
198
+ }
199
+ }
200
+
201
+ $post_meta[] = array( 'key' => '_' . $column, 'value' => $value );
202
+ break;
203
+
204
+ default:
205
+ $value = ( ! empty( $data[ $column ] ) ) ? $data[ $column ] : '';
206
+ $post_meta[] = array( 'key' => '_' . $column, 'value' => $value );
207
+ }
208
+ }
209
+
210
+ if ( empty( $data[ 'subscription_status'] ) ) {
211
+ $status = 'pending';
212
+ $result['warning'][] = esc_html__( 'No subscription status was specified. The subscription will be created with the status "pending". ', 'import-users-from-csv-with-meta' );
213
+ } else {
214
+ $status = ( 'wc-' === substr( $data[ 'subscription_status'], 0, 3 ) ) ? substr( $data[ 'subscription_status'], 3 ) : $data[ 'subscription_status'];
215
+ }
216
+
217
+ $dates_to_update = array( 'start' => ( ! empty( $data[ 'start_date'] ) ) ? gmdate( 'Y-m-d H:i:s', strtotime( $data[ 'start_date'] ) ) : gmdate( 'Y-m-d H:i:s', time() - 1 ) );
218
+
219
+ foreach ( array( 'trial_end_date', 'next_payment_date', 'end_date', 'last_payment_date' ) as $date_type ) {
220
+ $dates_to_update[ $date_type ] = ( ! empty( $data[ $date_type ] ) ) ? gmdate( 'Y-m-d H:i:s', strtotime( $data[ $date_type ] ) ) : '';
221
+ }
222
+
223
+ foreach ( $dates_to_update as $date_type => $datetime ) {
224
+
225
+ if ( empty( $datetime ) ) {
226
+ continue;
227
+ }
228
+
229
+ switch ( $date_type ) {
230
+ case 'end_date' :
231
+ if ( ! empty( $dates_to_update['next_payment_date'] ) && strtotime( $datetime ) <= strtotime( $dates_to_update['next_payment_date'] ) ) {
232
+ $result['error'][] = sprintf( __( 'The %s date must occur after the next payment date.', 'import-users-from-csv-with-meta' ), $date_type );
233
+ }
234
+ case 'next_payment_date' :
235
+ if ( ! empty( $dates_to_update['trial_end_date'] ) && strtotime( $datetime ) < strtotime( $dates_to_update['trial_end_date'] ) ) {
236
+ $result['error'][] = sprintf( __( 'The %s date must occur after the trial end date.', 'import-users-from-csv-with-meta' ), $date_type );
237
+ }
238
+ case 'trial_end_date' :
239
+ if ( strtotime( $datetime ) <= strtotime( $dates_to_update['start'] ) ) {
240
+ $result['error'][] = sprintf( __( 'The %s must occur after the start date.', 'import-users-from-csv-with-meta' ), $date_type );
241
+ }
242
+ }
243
+ }
244
+
245
+ // make the sure end of prepaid term exists for subscription that are about to be set to pending-cancellation - continue to use the next payment date if that exists
246
+ if ( 'pending-cancel' == $status && ( empty( $dates_to_update['next_payment_date'] ) || strtotime( $dates_to_update['next_payment_date'] ) < current_time( 'timestamp', true ) ) ) {
247
+ if ( ! empty( $dates_to_update['end_date'] ) && strtotime( $dates_to_update['end_date'] ) > current_time( 'timestamp', true ) ) {
248
+ $dates_to_update['next_payment_date'] = $dates_to_update['end_date'];
249
+ unset( $dates_to_update['end_date'] );
250
+ } else {
251
+ $result['error'][] = __( 'Importing a pending cancelled subscription requires an end date in the future.', 'import-users-from-csv-with-meta' );
252
+ }
253
+ }
254
+
255
+ if ( empty( $result['error'] ) ) {
256
+ try {
257
+ $wpdb->query( 'START TRANSACTION' );
258
+
259
+ $subscription = wcs_create_subscription( array(
260
+ 'customer_id' => $user_id,
261
+ 'start_date' => $dates_to_update['start'],
262
+ 'billing_interval' => ( ! empty( $data[ 'billing_interval'] ) ) ? $data[ 'billing_interval'] : 1,
263
+ 'billing_period' => ( ! empty( $data[ 'billing_period'] ) ) ? $data[ 'billing_period'] : '',
264
+ 'created_via' => 'importer',
265
+ 'customer_note' => ( ! empty( $data[ 'customer_note'] ) ) ? $data[ 'customer_note'] : '',
266
+ 'currency' => ( ! empty( $data[ 'order_currency'] ) ) ? $data[ 'order_currency'] : '',
267
+ )
268
+ );
269
+
270
+ if ( is_wp_error( $subscription ) ) {
271
+ throw new Exception( sprintf( esc_html__( 'Could not create subscription: %s', 'import-users-from-csv-with-meta' ), $subscription->get_error_message() ) );
272
+ }
273
+
274
+ $subscription_id = version_compare( WC()->version, '3.0', '>=' ) ? $subscription->get_id() : $subscription->id;
275
+
276
+ foreach ( $post_meta as $meta_data ) {
277
+ update_post_meta( $subscription_id, $meta_data['key'], $meta_data['value'] );
278
+ }
279
+
280
+ if( !empty( $data['custom_post_meta'] ) ){
281
+ foreach ( $data['custom_post_meta'] as $meta_key ) {
282
+ if ( ! empty( $data[ $meta_key ] ) ) {
283
+ update_post_meta( $subscription_id, $meta_key, $data[ $meta_key ] );
284
+ }
285
+ }
286
+ }
287
+
288
+ if( !empty( $data['custom_user_post_meta'] ) ){
289
+ foreach ( $data['custom_user_post_meta'] as $meta_key ) {
290
+ if ( ! empty( $data[ $meta_key ] ) ) {
291
+ update_post_meta( $subscription_id, $meta_key, $data[ $meta_key ] );
292
+ update_user_meta( $user_id, $meta_key, $data[ $meta_key ] );
293
+ }
294
+ }
295
+ }
296
+
297
+ // Now that we've set all the meta data, reinit the object so the data is set
298
+ $subscription = wcs_get_subscription( $subscription_id );
299
+
300
+ $subscription->update_dates( $dates_to_update );
301
+
302
+ if ( ! $set_manual && ! in_array( $status, wcs_get_subscription_ended_statuses() ) ) { // don't bother trying to set payment meta on a subscription that won't ever renew
303
+ $result['warning'] = array_merge( $result['warning'], $this->set_payment_meta( $subscription, $data ) );
304
+ }
305
+
306
+ if ( $set_manual || $requires_manual_renewal ) {
307
+ $subscription->set_requires_manual_renewal( true );
308
+ }
309
+
310
+ if ( ! empty( $data[ 'order_notes'] ) ) {
311
+ $order_notes = explode( ';', $data[ 'order_notes'] );
312
+
313
+ foreach ( $order_notes as $order_note ) {
314
+ $subscription->add_order_note( $order_note );
315
+ }
316
+ }
317
+
318
+ if ( $set_manual ) {
319
+ $result['warning'][] = esc_html__( 'No payment method was given in CSV and so the subscription has been set to manual renewal.', 'import-users-from-csv-with-meta' );
320
+ } else if ( $requires_manual_renewal ) {
321
+ $result['warning'][] = esc_html__( 'Import forced manual renewal.', 'import-users-from-csv-with-meta' );
322
+ }
323
+
324
+ if ( ! empty( $data[ 'coupon_items'] ) ) {
325
+ $this->add_coupons( $subscription, $data );
326
+ }
327
+
328
+ $chosen_tax_rate_id = 0;
329
+ if ( ! empty( $data[ 'tax_items'] ) ) {
330
+ $chosen_tax_rate_id = $this->add_taxes( $subscription, $data );
331
+ }
332
+
333
+ if ( ! empty( $data[ 'order_items'] ) ) {
334
+ if ( is_numeric( $data[ 'order_items'] ) ) {
335
+ $product_id = absint( $data[ 'order_items'] );
336
+ $result['items'] = $this->add_product( $subscription, array( 'product_id' => $product_id ), $chosen_tax_rate_id );
337
+ $order_items[] = $product_id;
338
+ } else {
339
+ $order_items_row = explode( ';', $data[ 'order_items'] );
340
+
341
+ if ( ! empty( $order_items_row ) ) {
342
+ foreach ( $order_items_row as $order_item ) {
343
+ $item_data = array();
344
+
345
+ foreach ( explode( '|', $order_item ) as $item ) {
346
+ list( $name, $value ) = explode( ':', $item );
347
+ $item_data[ trim( $name ) ] = trim( $value );
348
+ }
349
+
350
+ $result['items'] .= $this->add_product( $subscription, $item_data, $chosen_tax_rate_id ) . '<br/>';
351
+ $order_items[] = $item_data['product_id'];
352
+ }
353
+ }
354
+ }
355
+ }
356
+
357
+ if ( ! empty( $data[ 'fee_items'] ) ) {
358
+ $this->add_fees( $subscription, $data, $chosen_tax_rate_id );
359
+ }
360
+
361
+ if ( ! empty( $data[ 'shipping_method'] ) ) {
362
+ $shipping_method = $this->add_shipping_lines( $subscription, $data, $chosen_tax_rate_id );
363
+ }
364
+
365
+ // only show the following warnings on the import when the subscription requires shipping
366
+ if ( ! $this->all_virtual ) {
367
+ if ( ! empty( $missing_shipping_addresses ) ) {
368
+ $result['warning'][] = sprintf( esc_html__( 'The following shipping address fields have been left empty: %s. ', 'import-users-from-csv-with-meta' ), rtrim( implode( ', ', $missing_shipping_addresses ), ',' ) );
369
+ }
370
+
371
+ if ( ! empty( $missing_billing_addresses ) ) {
372
+ $result['warning'][] = sprintf( esc_html__( 'The following billing address fields have been left empty: %s. ', 'import-users-from-csv-with-meta' ), rtrim( implode( ', ', $missing_billing_addresses ), ',' ) );
373
+ }
374
+
375
+ if ( empty( $shipping_method ) ) {
376
+ $result['warning'][] = esc_html__( 'Shipping method and title for the subscription have been left as empty. ', 'import-users-from-csv-with-meta' );
377
+ }
378
+ }
379
+
380
+
381
+ add_filter( 'woocommerce_can_subscription_be_updated_to_cancelled', '__return_true' );
382
+ add_filter( 'woocommerce_can_subscription_be_updated_to_pending-cancel', '__return_true' );
383
+
384
+ $subscription->update_status( $status );
385
+
386
+ remove_filter( 'woocommerce_can_subscription_be_updated_to_cancelled', '__return_true' );
387
+ remove_filter( 'woocommerce_can_subscription_be_updated_to_pending-cancel', '__return_true' );
388
+
389
+ foreach ( $order_items as $product_id ) {
390
+ $this->maybe_add_memberships( $user_id, $subscription->id, $product_id );
391
+ }
392
+
393
+ $subscription->save();
394
+
395
+ $wpdb->query( 'COMMIT' );
396
+
397
+ } catch ( Exception $e ) {
398
+ $wpdb->query( 'ROLLBACK' );
399
+ $result['error'][] = $e->getMessage();
400
+ }
401
+ }
402
+
403
+ if ( empty( $result['error'] ) ) {
404
+ $result['status'] = 'success';
405
+ $result['subscription'] = sprintf( '<a href="%s">#%s</a>', esc_url( admin_url( 'post.php?post=' . absint( $subscription_id ) . '&action=edit' ) ), $subscription->get_order_number() );
406
+ $result['subscription_status'] = $subscription->get_status();
407
+
408
+ }
409
+
410
+ // print result
411
+ if( !empty( $result['warning'] ) ){
412
+ foreach ( $result['warning'] as $warning ) {
413
+ echo "<td>" . $warning . "</td>";
414
+ }
415
+ }
416
+ else{
417
+ echo "<td></td>";
418
+ }
419
+
420
+ if( !empty( $result['error'] ) ){
421
+ foreach ( $result['error'] as $error ) {
422
+ echo "<td>" . $error . "</td>";
423
+ }
424
+ }
425
+ else{
426
+ echo "<td></td>";
427
+ }
428
+ }
429
+
430
+ function set_payment_meta( $subscription, $data ) {
431
+ $warnings = array();
432
+ $payment_gateways = WC()->payment_gateways->get_available_payment_gateways();
433
+ $subscription_id = version_compare( WC()->version, '3.0', '>=' ) ? $subscription->get_id() : $subscription->id;
434
+ $payment_method = version_compare( WC()->version, '3.0', '>=' ) ? $subscription->get_payment_method() : $subscription->payment_method;
435
+
436
+ if ( ! empty( $payment_method ) ) {
437
+ $payment_method_table = apply_filters( 'woocommerce_subscription_payment_meta', array(), $subscription );
438
+ $payment_gateway = ( isset( $payment_gateways[ $payment_method ] ) ) ? $payment_gateways[ $payment_method ] : '';
439
+
440
+ if ( ! empty( $payment_gateway ) && isset( $payment_method_table[ $payment_gateway->id ] ) ) {
441
+ $payment_post_meta = $payment_user_meta = array();
442
+
443
+ if ( ! empty( $data[ 'payment_method_post_meta'] ) ) {
444
+ foreach ( explode( '|', $data[ 'payment_method_post_meta'] ) as $meta ) {
445
+ list( $name, $value ) = explode( ':', $meta );
446
+ $payment_post_meta[ trim( $name ) ] = trim( $value );
447
+ }
448
+ }
449
+
450
+ if ( ! empty( $data[ 'payment_method_user_meta'] ) ) {
451
+ foreach ( explode( '|', $data[ 'payment_method_user_meta'] ) as $meta ) {
452
+ list( $name, $value ) = explode( ':', $meta );
453
+ $payment_user_meta[ trim( $name ) ] = trim( $value );
454
+ }
455
+ }
456
+
457
+ $payment_method_data = $payment_method_table[ $payment_gateway->id ];
458
+ $meta_set = false;
459
+
460
+ foreach ( $payment_method_data as $meta_table => &$meta ) {
461
+ if ( ! is_array( $meta ) ) {
462
+ continue;
463
+ }
464
+
465
+ foreach ( $meta as $meta_key => &$meta_data ) {
466
+ switch ( $meta_table ) {
467
+ case 'post_meta':
468
+ case 'postmeta':
469
+ $value = ( ! empty( $payment_post_meta[ $meta_key ] ) ) ? $payment_post_meta[ $meta_key ] : '';
470
+ break;
471
+ case 'user_meta':
472
+ case 'usermeta':
473
+ $value = ( ! empty( $payment_user_meta[ $meta_key ] ) ) ? $payment_user_meta[ $meta_key ] : '';
474
+ break;
475
+ default :
476
+ $value = '';
477
+ }
478
+
479
+ if ( ! empty( $value ) ) {
480
+ $meta_data['value'] = $value;
481
+ $meta_set = true;
482
+ }
483
+ }
484
+ }
485
+
486
+ if ( $meta_set ) {
487
+ // Reload the subscription to update the meta values.
488
+ $subscription = wcs_get_subscription( $subscription->get_id() );
489
+ $subscription->set_payment_method( $payment_gateway, $payment_method_data );
490
+ $subscription->save();
491
+ } else {
492
+ $warnings[] = sprintf( esc_html__( 'No payment meta was set for your %1$s subscription (%2$s). The next renewal is going to fail if you leave this.', 'import-users-from-csv-with-meta' ), $payment_method, $subscription_id );
493
+ }
494
+ } else {
495
+ if ( 'paypal' == $payment_method ) {
496
+ $warnings[] = sprintf( esc_html__( 'Could not set payment method as PayPal, defaulted to manual renewals. Either PayPal was not enabled or your PayPal account does not have Reference Transaction setup. Learn more about enabling Reference Transactions %1$shere%2$s.', 'import-users-from-csv-with-meta' ), '<a href="https://support.woocommerce.com/hc/en-us/articles/205151193-PayPal-Reference-Transactions-for-Subscriptions">', '</a>' );
497
+ } else {
498
+ $warnings[] = sprintf( esc_html__( 'The payment method "%s" is either not enabled or does not support the new features of Subscriptions 2.0 and can not be properly attached to your subscription. This subscription has been set to manual renewals.', 'import-users-from-csv-with-meta' ), $payment_method );
499
+ }
500
+ $subscription->set_requires_manual_renewal( true );
501
+ }
502
+ }
503
+ return $warnings;
504
+ }
505
+
506
+ function save_download_permissions( $subscription, $product, $quantity = 1 ) {
507
+
508
+ if ( $product && $product->exists() && $product->is_downloadable() ) {
509
+ $downloads = $product->get_downloads();
510
+
511
+ foreach ( array_keys( $downloads ) as $download_id ) {
512
+ wc_downloadable_file_permission( $download_id, $product->get_id(), $subscription, $quantity );
513
+ }
514
+ }
515
+ }
516
+
517
+ function maybe_add_memberships( $user_id, $subscription_id, $product_id ) {
518
+ if ( function_exists( 'wc_memberships_get_membership_plans' ) ) {
519
+ $membership_plans = wc_memberships_get_membership_plans();
520
+
521
+ foreach ( $membership_plans as $plan ) {
522
+ if ( $plan->has_product( $product_id ) ) {
523
+ $plan->grant_access_from_purchase( $user_id, $product_id, $subscription_id );
524
+ }
525
+
526
+ // if the product is a variation we want to also check if the parent variable product has any plans as well and add them
527
+ $product = wc_get_product( $product_id );
528
+ $parent_id = wcs_get_objects_property( $product, 'parent_id' );
529
+ if ( $product && $product->is_type( 'variation' ) && ! empty( $parent_id ) && $plan->has_product( $parent_id ) ) {
530
+ $plan->grant_access_from_purchase( $user_id, $product->parent->id, $subscription_id );
531
+ }
532
+ }
533
+ }
534
+ }
535
+
536
+ function add_coupons( $subscription, $data ) {
537
+ $coupon_items = explode( ';', $data[ 'coupon_items'] );
538
+
539
+ if ( ! empty( $coupon_items ) ) {
540
+ foreach ( $coupon_items as $coupon_item ) {
541
+ $coupon_data = array();
542
+
543
+ foreach ( explode( '|', $coupon_item ) as $item ) {
544
+ list( $name, $value ) = explode( ':', $item );
545
+ $coupon_data[ trim( $name ) ] = trim( $value );
546
+ }
547
+
548
+ $coupon_code = isset( $coupon_data['code'] ) ? $coupon_data['code'] : '';
549
+ $coupon = new WC_Coupon( $coupon_code );
550
+
551
+ if ( ! $coupon ) {
552
+ throw new Exception( sprintf( esc_html__( 'Could not find coupon with code "%s" in your store.', 'import-users-from-csv-with-meta' ), $coupon_code ) );
553
+ } elseif ( isset( $coupon_data['amount'] ) ) {
554
+ $discount_amount = floatval( $coupon_data['amount'] );
555
+ } else {
556
+ $discount_amount = version_compare( WC()->version, '3.0', '>=' ) ? $coupon->get_discount_amount( 0 ) : $coupon->discount_amount;
557
+ }
558
+
559
+
560
+ $coupon_line_item = new WC_Order_Item_Coupon();
561
+ $coupon_line_item->set_props( array(
562
+ 'code' => $coupon_code,
563
+ 'discount' => $discount_amount,
564
+ 'discount_tax' => 0,
565
+ 'order_id' => $subscription->get_id(),
566
+ ) );
567
+ $coupon_line_item->save();
568
+ $subscription->add_item( $coupon_line_item );
569
+ $coupon_id = $coupon_line_item->get_id();
570
+
571
+ if ( ! $coupon_id ) {
572
+ throw new Exception( sprintf( esc_html__( 'Coupon "%s" could not be added to subscription.', 'import-users-from-csv-with-meta' ), $coupon_code ) );
573
+ }
574
+ }
575
+ }
576
+ }
577
+
578
+ function add_product( $subscription, $data, $chosen_tax_rate_id ) {
579
+ $item_args = array();
580
+ $item_args['qty'] = isset( $data['quantity'] ) ? $data['quantity'] : 1;
581
+
582
+ if ( ! isset( $data['product_id'] ) ) {
583
+ throw new Exception( __( 'The product_id is missing from CSV.', 'import-users-from-csv-with-meta' ) );
584
+ }
585
+
586
+ $_product = wc_get_product( $data['product_id'] );
587
+
588
+ if ( ! $_product ) {
589
+ throw new Exception( sprintf( __( 'No product or variation in your store matches the product ID #%s.', 'import-users-from-csv-with-meta' ), $data['product_id'] ) );
590
+ }
591
+
592
+ $_product_id = version_compare( WC()->version, '3.0', '>=' ) ? $_product->get_id() : $_product->id;
593
+ $line_item_name = ( ! empty( $data['name'] ) ) ? $data['name'] : $_product->get_title();
594
+ $product_string = sprintf( '<a href="%s">%s</a>', get_edit_post_link( $_product_id ), $line_item_name );
595
+
596
+ foreach ( array( 'total', 'tax', 'subtotal', 'subtotal_tax' ) as $line_item_data ) {
597
+
598
+ switch ( $line_item_data ) {
599
+ case 'total' :
600
+ $default = WC_Subscriptions_Product::get_price( $data['product_id'] );
601
+ break;
602
+ case 'subtotal' :
603
+ $default = ( ! empty( $data['total'] ) ) ? $data['total'] : WC_Subscriptions_Product::get_price( $data['product_id'] );
604
+ break;
605
+ default :
606
+ $default = 0;
607
+ }
608
+ $item_args['totals'][ $line_item_data ] = ( ! empty( $data[ $line_item_data ] ) ) ? $data[ $line_item_data ] : $default;
609
+ }
610
+
611
+ // Add this site's variation meta data if no line item meta data was specified in the CSV
612
+ if ( empty( $data['meta'] ) && $_product->is_type( 'variable' ) ) {
613
+ $_product_variation_data = version_compare( WC()->version, '3.0', '>=' ) ? $_product->get_available_variations() : $_product->variation_data;
614
+
615
+ $item_args['variation'] = array();
616
+
617
+ foreach ( $_product_variation_data as $attribute => $variation ) {
618
+ $item_args['variation'][ $attribute ] = $variation;
619
+ }
620
+ $product_string .= ' [#' . $data['product_id'] . ']';
621
+ }
622
+
623
+ if ( $this->all_virtual && ! $_product->is_virtual() ) {
624
+ $this->all_virtual = false;
625
+ }
626
+
627
+ if ( ! empty( $item_args['totals']['tax'] ) && ! empty( $chosen_tax_rate_id ) ) {
628
+ $item_args['totals']['tax_data']['total'] = array( $chosen_tax_rate_id => $item_args['totals']['tax'] );
629
+ $item_args['totals']['tax_data']['subtotal'] = array( $chosen_tax_rate_id => $item_args['totals']['tax'] );
630
+ }
631
+
632
+ $item_id = $subscription->add_product( $_product, $item_args['qty'], $item_args );
633
+
634
+ // Set the name used in the CSV if it's different to the product's current title (which is what WC_Abstract_Order::add_product() uses)
635
+ if ( ! empty( $data['name'] ) && $_product->get_title() != $data['name'] ) {
636
+ wc_update_order_item( $item_id, array( 'order_item_name' => $data['name'] ) );
637
+ }
638
+
639
+ // Add any meta data for the line item
640
+ if ( ! empty( $data['meta'] ) ) {
641
+ foreach ( explode( '+', $data['meta'] ) as $meta ) {
642
+ $meta = explode( '=', $meta );
643
+ wc_update_order_item_meta( $item_id, $meta[0], $meta[1] );
644
+ }
645
+ }
646
+
647
+ if ( ! $item_id ) {
648
+ throw new Exception( __( 'An unexpected error occurred when trying to add product "%s" to your subscription. The error was caught and no subscription for this row will be created. Please fix up the data from your CSV and try again.', 'import-users-from-csv-with-meta' ) );
649
+ }
650
+
651
+ if ( ! empty( $data[ 'download_permissions'] ) && ( 'true' == $data[ 'download_permissions'] || 1 == (int) $data[ 'download_permissions'] ) ) {
652
+ $this->save_download_permissions( $subscription, $_product, $item_args['qty'] );
653
+ }
654
+
655
+ return $product_string;
656
+ }
657
+
658
+ function add_fees( $subscription, $data, $chosen_tax_rate_id ) {
659
+ $fee_items = explode( ';', $data[ 'fee_items'] );
660
+
661
+ if ( ! empty( $fee_items ) ) {
662
+ foreach ( $fee_items as $fee_item ) {
663
+ $fee_data = array();
664
+
665
+ foreach ( explode( '|', $fee_item ) as $item ) {
666
+ list( $name, $value ) = explode( ':', $item );
667
+ $fee_data[ trim( $name ) ] = trim( $value );
668
+ }
669
+
670
+ if ( empty( $fee_data['name'] ) ) {
671
+ throw new Exception( __( 'Fee name is missing from your CSV. This subscription has not been imported.', 'import-users-from-csv-with-meta' ) );
672
+ }
673
+
674
+ $fee = new stdClass();
675
+ $fee->id = sanitize_title( $fee_data['name'] );
676
+ $fee->name = $fee_data['name'];
677
+ $fee->amount = isset( $fee_data['total'] ) ? floatval( $fee_data['total'] ) : 0;
678
+ $fee->taxable = false;
679
+ $fee->tax = 0;
680
+ $fee->tax_data = array();
681
+ $fee->tax_class = 0;
682
+
683
+ if ( ! empty( $fee_data['tax'] ) ) {
684
+ $fee->tax = wc_format_decimal( $fee_data['tax'] );
685
+ $fee->tax_class = ( ! empty( $fee_data['tax_class'] ) ) ? $fee_data['tax_class'] : 0;
686
+ $fee->taxable = true;
687
+
688
+ if ( ! empty( $chosen_tax_rate_id ) ) {
689
+ $fee->tax_data = array( 'total' => array( $chosen_tax_rate_id => $fee->tax ), 'subtotal' => array( $chosen_tax_rate_id => $fee->tax ) );
690
+ }
691
+ }
692
+
693
+
694
+ $fee_line_item = new WC_Order_Item_Fee();
695
+ $fee_line_item->set_props( array(
696
+ 'name' => $fee->name,
697
+ 'tax_class' => $fee->taxable ? $fee->tax_class : 0,
698
+ 'total' => $fee->amount,
699
+ 'total_tax' => $fee->tax,
700
+ 'taxes' => array(
701
+ 'total' => $fee->tax_data,
702
+ ),
703
+ 'order_id' => $subscription->get_id(),
704
+ ) );
705
+ $fee_line_item->save();
706
+ $subscription->add_item( $fee_line_item );
707
+
708
+ $fee_id = $fee_line_item->get_id();
709
+
710
+ if ( ! $fee_id ) {
711
+ throw new Exception( __( 'Could not add the fee to your subscription, the subscription has not been imported.', 'import-users-from-csv-with-meta' ) );
712
+ }
713
+ }
714
+ }
715
+ }
716
+
717
+ function add_shipping_lines( $subscription, $data, $chosen_tax_rate_id ) {
718
+ $shipping_items = explode( ';', $data[ 'shipping_method'] );
719
+ $shipping_method = '';
720
+ $default_total = ( ! empty( $data[ 'order_shipping'] ) ) ? $data[ 'order_shipping'] : 0;
721
+
722
+ if ( ! empty( $shipping_items ) ) {
723
+ foreach ( $shipping_items as $shipping_item ) {
724
+ $shipping_line = array();
725
+
726
+ if ( false !== strpos( $shipping_item, ':' ) ) {
727
+ foreach ( explode( '|', $shipping_item ) as $item ) {
728
+ list( $name, $value ) = explode( ':', $item );
729
+ $shipping_line[ trim( $name ) ] = trim( $value );
730
+ }
731
+ } else {
732
+ $shipping_line['method_id'] = $shipping_item;
733
+ }
734
+
735
+ $shipping_method = isset( $shipping_line['method_id'] ) ? $shipping_line['method_id'] : '';
736
+ $shipping_title = isset( $shipping_line['method_title'] ) ? $shipping_line['method_title'] : $shipping_method;
737
+ $shipping_rate = new WC_Shipping_Rate( $shipping_method, $shipping_title, isset( $shipping_line['total'] ) ? floatval( $shipping_line['total'] ) : $default_total, array(), $shipping_method );
738
+
739
+ if ( ! empty( $data[ 'order_shipping_tax'] ) && ! empty( $chosen_tax_rate_id ) ) {
740
+ $shipping_rate->taxes = array( $chosen_tax_rate_id => $data[ 'order_shipping_tax'] );
741
+ }
742
+
743
+ $shipping_line_item = new WC_Order_Item_Shipping();
744
+ $shipping_line_item->set_props( array(
745
+ 'method_title' => $shipping_rate->label,
746
+ 'method_id' => $shipping_rate->id,
747
+ 'total' => wc_format_decimal( $shipping_rate->cost ),
748
+ 'taxes' => $shipping_rate->taxes,
749
+ 'order_id' => $subscription->get_id(),
750
+ ) );
751
+ foreach ( $shipping_rate->get_meta_data() as $key => $value ) {
752
+ $shipping_line_item->add_meta_data( $key, $value, true );
753
+ }
754
+ $shipping_line_item->save();
755
+ $subscription->add_item( $shipping_line_item );
756
+ wc_do_deprecated_action( 'woocommerce_order_add_shipping', array( $subscription->get_id(), $shipping_line_item->get_id(), $shipping_rate ), '3.0', 'woocommerce_new_order_item action instead.' );
757
+ $shipping_id = $shipping_line_item->get_id();
758
+
759
+ if ( ! $shipping_id ) {
760
+ throw new Exception( __( 'An error occurred when trying to add the shipping item to the subscription, a subscription not been created for this row.', 'import-users-from-csv-with-meta' ) );
761
+ }
762
+
763
+ update_post_meta( $subscription->get_id(), '_shipping_method', $shipping_method );
764
+ update_post_meta( $subscription->get_id(), '_shipping_method_title', $shipping_title );
765
+ }
766
+ }
767
+
768
+ return $shipping_method;
769
+ }
770
+
771
+ function add_taxes( $subscription, $data ) {
772
+ global $wpdb;
773
+
774
+ $tax_items = explode( ';', $data[ 'tax_items'] );
775
+ $chosen_tax_rate_id = 0;
776
+
777
+ if ( ! empty( $tax_items ) ) {
778
+ foreach ( $tax_items as $tax_item ) {
779
+ $tax_data = array();
780
+
781
+ if ( false !== strpos( $tax_item, ':' ) ) {
782
+ foreach ( explode( '|', $tax_item ) as $item ) {
783
+ list( $name, $value ) = explode( ':', $item );
784
+ $tax_data[ trim( $name ) ] = trim( $value );
785
+ }
786
+ } elseif ( 1 == count( $tax_items ) ) {
787
+ if ( is_numeric( $tax_item ) ) {
788
+ $tax_data['id'] = $tax_item;
789
+ } else {
790
+ $tax_data['code'] = $tax_item;
791
+ }
792
+ }
793
+
794
+ if ( ! empty( $tax_data['id'] ) ) {
795
+ $tax_rate = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %s", $tax_data['id'] ) );
796
+ } elseif ( ! empty( $tax_data['code'] ) ) {
797
+ $tax_rate = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_name = %s ORDER BY tax_rate_priority LIMIT 1", $tax_data['code'] ) );
798
+ } else {
799
+ $result['warning'][] = sprintf( esc_html__( 'Missing tax code or ID from column: %s', 'import-users-from-csv-with-meta' ), $data['tax_items'] );
800
+ }
801
+
802
+ if ( ! empty( $tax_rate ) ) {
803
+ $tax_rate = array_pop( $tax_rate );
804
+
805
+ $tax_line_item = new WC_Order_Item_Tax();
806
+ $tax_line_item->set_props( array(
807
+ 'rate_id' => $tax_rate->tax_rate_id,
808
+ 'tax_total' => ( ! empty( $data[ 'order_tax'] ) ) ? $data[ 'order_tax'] : 0,
809
+ 'shipping_tax_total' => ( ! empty( $data[ 'order_shipping_tax'] ) ) ? $data[ 'order_shipping_tax'] : 0,
810
+ ) );
811
+ $tax_line_item->set_rate( $tax_rate->tax_rate_id );
812
+ $tax_line_item->set_order_id( $subscription->get_id() );
813
+ $tax_line_item->save();
814
+ $subscription->add_item( $tax_line_item );
815
+ $tax_id = $tax_line_item->get_id();
816
+
817
+ $chosen_tax_rate_id = $tax_rate->tax_rate_id;
818
+ }
819
+ }
820
+ }
821
+
822
+ return $chosen_tax_rate_id;
823
+ }
824
+ }
825
+
826
+ new ACUI_WooCommerceSubscritpions();
import-users-from-csv-with-meta.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Import and export users and customers
4
  Plugin URI: https://www.codection.com
5
  Description: Using this plugin you will be able to import and export users or customers choosing many options and interacting with lots of other plugins
6
- Version: 1.15.3.6
7
  Author: codection
8
  Author URI: https://codection.com
9
  License: GPL2
3
  Plugin Name: Import and export users and customers
4
  Plugin URI: https://www.codection.com
5
  Description: Using this plugin you will be able to import and export users or customers choosing many options and interacting with lots of other plugins
6
+ Version: 1.15.4
7
  Author: codection
8
  Author URI: https://codection.com
9
  License: GPL2
importer.php CHANGED
@@ -157,7 +157,13 @@ function acui_import_users( $file, $form_data, $attach_id = 0, $is_cron = false,
157
  </style>
158
  <h3><?php echo apply_filters( 'acui_log_inserting_updating_data_title', __( 'Inserting and updating data', 'import-users-from-csv-with-meta' ) ); ?></h3>
159
  <table>
160
- <tr><th><?php _e( 'Row', 'import-users-from-csv-with-meta' ); ?></th><?php foreach( $headers as $element ) echo "<th>" . $element . "</th>"; ?></tr>
 
 
 
 
 
 
161
  <?php
162
  $row++;
163
  else:
@@ -513,14 +519,12 @@ function acui_import_users( $file, $form_data, $attach_id = 0, $is_cron = false,
513
  endfor;
514
  }
515
 
516
- do_action('post_acui_import_single_user', $headers, $data, $user_id, $role );
517
-
518
  $styles = "";
519
  if( $problematic_row )
520
  $styles = "background-color:red; color:white;";
521
 
522
  echo "<tr style='$styles' ><td>" . ($row - 1) . "</td>";
523
- foreach ($data as $element){
524
  if( is_array( $element ) )
525
  $element = implode ( ',' , $element );
526
 
@@ -528,6 +532,8 @@ function acui_import_users( $file, $form_data, $attach_id = 0, $is_cron = false,
528
  echo "<td>$element</td>";
529
  }
530
 
 
 
531
  echo "</tr>\n";
532
 
533
  flush();
157
  </style>
158
  <h3><?php echo apply_filters( 'acui_log_inserting_updating_data_title', __( 'Inserting and updating data', 'import-users-from-csv-with-meta' ) ); ?></h3>
159
  <table>
160
+ <tr>
161
+ <th><?php _e( 'Row', 'import-users-from-csv-with-meta' ); ?></th>
162
+ <?php foreach( $headers as $element ):
163
+ echo "<th>" . $element . "</th>";
164
+ endforeach; ?>
165
+ <?php do_action( 'acui_header_table_extra_rows' ); ?>
166
+ </tr>
167
  <?php
168
  $row++;
169
  else:
519
  endfor;
520
  }
521
 
 
 
522
  $styles = "";
523
  if( $problematic_row )
524
  $styles = "background-color:red; color:white;";
525
 
526
  echo "<tr style='$styles' ><td>" . ($row - 1) . "</td>";
527
+ foreach ( $data as $element ){
528
  if( is_array( $element ) )
529
  $element = implode ( ',' , $element );
530
 
532
  echo "<td>$element</td>";
533
  }
534
 
535
+ do_action('post_acui_import_single_user', $headers, $data, $user_id, $role );
536
+
537
  echo "</tr>\n";
538
 
539
  flush();
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://codection.com/go/donate-import-users-from-csv-with-meta/
4
  Tags: csv, import, importer, meta data, meta, user, users, user meta, editor, profile, custom, fields, delimiter, update, insert
5
  Requires at least: 3.4
6
  Tested up to: 5.3.2
7
- Stable tag: 1.15.3.6
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -98,6 +98,11 @@ Plugin will automatically detect:
98
 
99
  == Changelog ==
100
 
 
 
 
 
 
101
  = 1.15.3.6 =
102
  * New shortcut into WordPress importer and exporter default tools to find this one easier
103
 
4
  Tags: csv, import, importer, meta data, meta, user, users, user meta, editor, profile, custom, fields, delimiter, update, insert
5
  Requires at least: 3.4
6
  Tested up to: 5.3.2
7
+ Stable tag: 1.15.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
98
 
99
  == Changelog ==
100
 
101
+ = 1.15.4 =
102
+ * WooCommerce Subscriptions importer included to create subscriptions at the same time you are importing users
103
+ * New hooks added
104
+ * Code improved
105
+
106
  = 1.15.3.6 =
107
  * New shortcut into WordPress importer and exporter default tools to find this one easier
108
 
samples/wcs-import-sample.csv ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ Username,Email,subscription_status,start_date,trial_end_date,next_payment_date,last_payment_date,end_date,billing_period,billing_interval,order_shipping,order_shipping_tax,order_tax,cart_discount,cart_discount_tax,order_total,order_currency,payment_method,payment_method_title,payment_method_post_meta,payment_method_user_meta,shipping_method,billing_first_name,billing_last_name,billing_email,billing_phone,billing_address_1,billing_address_2,billing_postcode,billing_city,billing_state,billing_country,billing_company,shipping_first_name,shipping_last_name,shipping_address_1,shipping_address_2,shipping_postcode,shipping_city,shipping_state,shipping_country,shipping_company,customer_note,order_notes,coupon_items,fee_items,tax_items,download_permissions
2
+ johnadams,john@example.com,wc-active,2016-04-29 00:42:51,0,2016-05-29 00:42:51,2016-04-29 00:42:53,0,month,1,5.55,555,4.75,27.5,2.75,58.36,USD,manual,Manual,,,method_id:flat_rate|method_title:Flat Rate|total:5.55,John,Adams,john@example.com,(555) 555-5555,969 Market,,94103,San Francisco,CA,US,Prospress Inc.,John,Adams,969 Market,,94103,San Francisco,CA,US,,,Payment received.;Status changed from Pending to Active.,,,id:4|code:Sales Tax|total:5.31,0
3
+ benji,benji@example.com,wc-on-hold,2016-04-22 00:30:03,0,2016-06-20 03:00:00,2016-04-22 00:30:01,2016-08-20 03:00:04,month,1,3.33,333,3.6,12,1.2,43.26,USD,manual,Manual,,,method_id:flat_rate|method_title:Flat Rate|total:3.33,Benjamin,Franklin,benji@example.com,(123) 581-3213,36 Craven Street,,WC2N 5NF,London,London,GB,Prospress Inc.,Benjamin,Franklin,36 Craven Street,,WC2N 5NF,London,London,GB,,,"Payment method changed from ""Credit card (Stripe)"" to ""Credit card (Stripe)"" by the subscriber from their account page.;Payment received.;Status changed from Pending to Active.;Payment received.",,,id:4|code:Sales Tax|total:3.93,0
4
+ tj_rules,tj@example.com,wc-on-hold,2016-03-23 07:16:40,2016-04-23 07:16:40,2016-04-23 07:16:40,2016-03-29 10:14:14,0,month,1,0,0,0,0,0,11,USD,manual,Manual,,,method_id:free_shipping|method_title:Free Shipping|total:0.00,Thomas,Jefferson,tj@example.com,(555) 555-5555,969 Market,,94103,San Francisco,CA,US,Prospress Inc.,Thomas,Jefferson,969 Market,,94103,San Francisco,CA,US,,,"Payment failed.;Payment failed.;Payment failed.;Payment failed.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Order #6240 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Payment failed.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Order #6231 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Order #6224 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Payment failed.;Payment failed.;Payment failed.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Order #6211 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Process renewal order action requested by admin.;Order #6208 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Payment failed.;Payment failed.;Payment failed.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Order #6195 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Payment failed.;Subscription renewal payment due: Status changed from Active to On hold.;Order #6188 created to record renewal.;Status changed from On hold to Active.;Payment failed.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Order #6179 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Payment failed.;Payment failed.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Subscription renewal payment due: Status changed from Active to On hold.;Order #6166 created to record renewal.;Status changed from On hold to Active.;Payment failed.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Subscription renewal payment due: Status changed from Active to On hold.;Order #6157 created to record renewal.;Status changed from On hold to Active.;Payment failed.;Payment failed.;Payment failed.;Payment failed.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Order #6144 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Process renewal order action requested by admin.;Payment failed.;Order #6139 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Process renewal order action requested by admin.;Payment failed.;Order #6134 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Payment failed.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Order #6123 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Process renewal order action requested by admin.;Payment failed.;Order #6118 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Process renewal order action requested by admin.;Payment failed.;Order #6113 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Process renewal order action requested by admin.;Payment failed.;Order #6108 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Subscription status changed by bulk edit: Status changed from On hold to Active.;Payment failed.;Order #6104 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Order #6100 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Order #6096 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Subscription renewal payment due: Status changed from Active to On hold.;Order #6092 created to record renewal.;Status changed from On hold to Active.;Payment received.;Payment failed.;Payment failed.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Subscription renewal payment due: Status changed from Active to On hold.;Order #6077 created to record renewal.;Status changed from On hold to Active.;Process renewal order action requested by admin.;Payment failed.;Subscription renewal payment due: Status changed from Active to On hold.;Order #6072 created to record renewal.;Payment received.;Status changed from On hold to Active.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Order #6060 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Order #6055 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Order #6046 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Subscription status changed by bulk edit: Status changed from On hold to Active.;Subscription status changed by bulk edit: Status changed from Active to On hold.;Payment received.;Status changed from On hold to Active.;Payment failed.;Payment failed.;Payment failed.;Process renewal order action requested by admin.;Payment failed.;Subscription renewal payment due: Status changed from Active to On hold.;Order #6027 created to record renewal.;Subscription status changed by bulk edit: Status changed from On hold to Active.;Subscription status changed by bulk edit: Status changed from Active to On hold.;Subscription status changed by bulk edit: Status changed from On hold to Active.;Subscription status changed by bulk edit: Status changed from Active to On hold.;Status changed from On hold to Active.;Process renewal order action requested by admin.;Payment failed.;Order #6018 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Process renewal order action requested by admin.;Payment failed.;Order #6010 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Process renewal order action requested by admin.;Payment failed.;Subscription renewal payment due: Status changed from Active to On hold.;Order #6005 created to record renewal.;Status changed from On hold to Active.;Payment failed.;Order #6000 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Order #5995 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Order #5991 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Order #5987 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Order #5984 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Order #5981 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment failed.;Subscription renewal payment due: Status changed from Active to On hold.;Order #5978 created to record renewal.;Status changed from On hold to Active.;Order #5975 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Process renewal order action requested by admin.;Status changed from On hold to Active.;Payment received.;Order #5972 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Pickup location changed to Crown Colony, 377 Mandarin Drive, Daly City, CA 94015;Status changed from Pending to Active.;Sign-up complete.",,,id:4|code:Sales Tax|total:0.00,0
5
+ james,james@example.com,wc-active,2015-10-02 07:31:11,0,2016-03-04 07:31:09,2016-03-25 02:18:18,0,week,2,0,0,2.5,0,0,27.5,USD,manual,Manual,,,method_id:free_shipping|method_title:Free Shipping|total:0.00,James,Madison,james@example.com,(555) 555-5555,969 Market,,94103,San Francisco,CA,US,Prospress Inc.,James,Madison,969 Market,,94103,San Francisco,CA,US,,,Order #5746 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Order #5605 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Subscription renewal payment due: Status changed from Active to On hold.;Order #5492 created to record renewal.;Status changed from On hold to Active.;Payment received.;Order #5436 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Order #5350 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Order #5259 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Subscription renewal payment due: Status changed from Active to On hold.;Order #5145 created to record renewal.;Status changed from On hold to Active.;Payment received.;Order #5016 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from Pending to Active.;Payment received.,,,id:4|code:Sales Tax|total:2.50,0
6
+ alexander,alex@example.com,wc-cancelled,2015-08-31 20:59:11,0,0,2015-08-31 20:59:11,2015-09-14 21:51:02,month,1,12,1.2,2,0,0,35.2,USD,manual,Manual,,,method_id:local_delivery|method_title:Local Delivery|total:12.00,Alexander,Hamilton,alex@example.com,(555) 555-5555,969 Market,,94103,San Francisco,CA,US,Prospress Inc.,Alexander,Hamilton,969 Market,,94103,San Francisco,CA,US,,,Subscription status changed by bulk edit: Status changed from Pending Cancellation to Cancelled.;Status changed from Active to Pending Cancellation.;Subscription cancelled by the subscriber from their account page.;Payment received.;Status changed from Pending to Active.,,,id:4|code:Sales Tax|total:3.20,0
7
+ jimmy_m,jimmy@example.com,wc-active,2015-07-22 19:24:09,0,2016-05-22 19:24:09,2016-04-25 18:44:11,0,month,1,6.66,666,2.4,0,0,33.73,USD,manual,Manual,,,method_id:flat_rate:flat-rate-per-item|method_title:Flat Rate Per Item|total:6.66,James,Monroe,jimmy@example.com,(555) 555-5555,969 Market,,94103,San Francisco,CA,US,Prospress Inc.,James,Monroe,969 Market,,94103,San Francisco,CA,US,,,"Status changed from On hold to Active.;Payment received.;Order #6436 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Order #5912 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Order #5617 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Order #5440 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Order #5287 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Order #5059 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Payment received.;Status changed from On hold to Active.;Order #4815 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from On hold to Active.;Payment received.;Order <a href=""http://local.dev/subs20/wp-admin/post.php?post=#4481 created to record renewal.;Subscription renewal payment due: Status changed from Active to On hold.;Status changed from Pending to Active.",,,id:4|code:Sales Tax|total:3.07,0
8
+ johnadams,john@example.com,wc-active,2016-04-29 00:44:44,0,2016-05-29 00:44:44,2016-04-29 00:44:46,2018-04-29 00:44:44,month,1,4.44,444,4.3,22,2.2,46.68,USD,manual,Manual,,,method_id:flat_rate|method_title:Flat Rate|total:4.44,John,Adams,john@example.com,(555) 555-5555,969 Market,,94103,San Francisco,CA,US,Prospress Inc.,John,Adams,969 Market,,94103,San Francisco,CA,US,,,This is a note to the customer added by the store owner via Edit Subscription admin screen.;This is a private order note added by the store owner via Edit Subscription admin screen.;Payment received.;Status changed from Pending to Active.,code:rd5|description:|amount:20.00;code:rd5pc|description:|amount:2.00,name:Custom Fee|total:5.00|tax:0.50,id:4|code:Sales Tax|total:4.74,0
9
+ benji,benji@example.com,wc-active,2016-04-29 00:44:44,0,2016-05-29 00:44:44,2016-04-29 00:44:46,2018-04-29 00:44:44,month,1,4.44,444,4.3,22,2.2,46.68,USD,manual,Manual,,,method_id:flat_rate|method_title:Flat Rate|total:4.44,Benjamin,Franklin,benji@example.com,(123) 581-3213,36 Craven Street,,WC2N 5NF,London,London,GB,Prospress Inc.,Benjamin,Franklin,36 Craven Street,,WC2N 5NF,London,London,GB,,,This is a note to the customer added by the store owner via Edit Subscription admin screen.;This is a private order note added by the store owner via Edit Subscription admin screen.;Payment received.;Status changed from Pending to Active.,code:rd5|description:|amount:20.00;code:rd5pc|description:|amount:2.00,name:Custom Fee|total:5.00|tax:0.50,id:4|code:Sales Tax|total:4.74,1
10
+ tj_rules,tj@example.com,wc-active,2016-04-29 00:44:44,0,2016-05-29 00:44:44,2016-04-29 00:44:46,2018-04-29 00:44:44,month,1,4.44,444,4.3,22,2.2,46.68,USD,stripe,Credit card (Stripe),_stripe_customer_id:cus_fakeimportedtoken|_stripe_source_id:,,method_id:flat_rate|method_title:Flat Rate|total:4.44,Thomas,Jefferson,tj@example.com,(555) 555-5555,969 Market,,94103,San Francisco,CA,US,Prospress Inc.,Thomas,Jefferson,969 Market,,94103,San Francisco,CA,US,,This is a customer note placed on the order/subscription by the customer at checkout and displayed to the store owner via the Edit Subscription and Edit Order administration screens.,This is a note to the customer added by the store owner via Edit Subscription admin screen.;This is a private order note added by the store owner via Edit Subscription admin screen.;Payment received.;Status changed from Pending to Active.,,,id:4|code:Sales Tax|total:4.74,0