PluginProbe
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More / 2.2.0
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More v2.2.0
2.3.0 2.2.0 2.1.1 2.1.0 2.0.0 1.10.0 1.9.1 1.9.0 1.2.1 1.2.2 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 All 59 releases
storeengine / addons / csv / utils / import.php

import.php in StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More 2.2.0, at addons/csv/utils/import.php

657 lines 24.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace StoreEngine\Addons\Csv\Utils;
4
5 use StoreEngine\Addons\Subscription\Classes\Subscription;
6 use StoreEngine\Classes\Customer;
7 use StoreEngine\Classes\DownloadPermission;
8 use StoreEngine\Classes\EventStreamServer;
9 use StoreEngine\Classes\Exceptions\StoreEngineException;
10 use StoreEngine\Classes\Order;
11 use StoreEngine\Classes\Refund;
12 use StoreEngine\Integrations\AbstractIntegration;
13 use StoreEngine\Utils\Formatting;
14 use StoreEngine\Utils\Helper;
15 use WP_Error;
16
17 class Import {
18
19 public static function validate_csv_structure( string $file, array $expected_header ) {
20 $handle = fopen( $file, 'r' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen
21 if ( ! $handle ) {
22 return new WP_Error( 'invalid_csv', __( 'Unable to open file.', 'storeengine' ) );
23 }
24
25 $header = fgetcsv( $handle, 0, ',' );
26 fclose( $handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
27 if ( false === $header ) {
28 return new WP_Error( 'invalid_csv', __( 'CSV is empty.', 'storeengine' ) );
29 }
30
31 $header = array_map( 'trim', $header );
32 if ( $header !== $expected_header ) {
33 return new WP_Error( 'invalid_csv', __( 'CSV header does not match the expected format.', 'storeengine' ) );
34 }
35
36 return true;
37 }
38
39 public static function import_chunk_customers( string $filename, int $start_index, EventStreamServer $stream ) {
40 $filename = Helper::get_filename_without_extension( $filename );
41 $customers = get_transient( 'storeengine_csv_customers_' . $filename . '_' . $start_index );
42 if ( ! $customers ) {
43 $stream->emitEvent( [
44 'type' => 'error',
45 'message' => __( 'Unable to retrieve chunked customers.', 'storeengine' ),
46 ], true );
47 }
48
49 $index = ( $start_index * 30 ) + 1;
50 $customers_count = get_transient( 'storeengine_csv_customers_' . $filename . '_count' );
51 foreach ( $customers as $customer_data ) {
52 $customer = new Customer();
53 $username = $customer_data['username'] ?? null;
54 if ( ! $username && isset( $customer_data['first_name'], $customer_data['last_name'] ) ) {
55 $username = self::generate_unique_username( $customer_data['first_name'], $customer_data['last_name'] );
56 }
57
58 $email = $customer_data['email'];
59 if ( empty( $username ) || empty( $email ) || username_exists( $username ) || email_exists( $email ) ) {
60 continue;
61 }
62
63 foreach ( $customer_data as $key => $value ) {
64 if ( method_exists( $customer, "set_$key" ) ) {
65 $customer->{"set_$key"}( $value );
66 }
67 }
68 $customer->set_password( '' );
69 $customer->save();
70
71 $roles = explode( ',', $customer_data['roles'] );
72 if ( is_array( $roles ) && ! empty( $roles ) ) {
73 foreach ( $roles as $role ) {
74 $customer->get_wp_user()->add_role( trim( $role ) );
75 }
76 }
77
78 do_action( 'storeengine/csv/customer_imported', $customer, $customer_data );
79
80 $stream->emitEvent( [
81 'type' => 'progress',
82 'percentage' => round( ( $index / $customers_count ) * 100 ),
83 ] );
84 $index ++;
85 }
86
87 delete_transient( 'storeengine_csv_customers_' . $filename . '_' . $start_index );
88 wp_cache_flush();
89
90 $stream->emitEvent( [
91 'type' => 'completed',
92 ], true );
93 }
94
95 public static function import_chunk_orders( string $filename, int $start_index, EventStreamServer $stream ) {
96 $filename = Helper::get_filename_without_extension( $filename );
97 $orders = get_transient( 'storeengine_csv_orders_' . $filename . '_' . $start_index );
98 if ( ! $orders ) {
99 $stream->emitEvent( [
100 'type' => 'error',
101 'message' => __( 'Unable to retrieve chunked orders.', 'storeengine' ),
102 ], true );
103 }
104
105 remove_all_actions( 'storeengine/order/status_changed' );
106 remove_all_actions( 'storeengine/order/payment_status_changed' );
107 $index = ( $start_index * 30 ) + 1;
108 $orders_count = get_transient( 'storeengine_csv_orders_' . $filename . '_count' );
109
110 foreach ( $orders as $order_data ) {
111 if ( ! isset( $order_data['order_key'] ) ) {
112 continue;
113 }
114 $order_key = $order_data['order_key'];
115 $has_order = Helper::get_order_by_key( $order_key );
116 if ( ! is_wp_error( $has_order ) ) {
117 continue;
118 }
119 $order = new Order();
120 $order->set_order_key( $order_key );
121 $order->set_status( $order_data['order_status'] );
122 $order->set_currency( $order_data['order_currency'] );
123 $order->set_total( $order_data['order_total'] );
124 $order->set_cart_tax( $order_data['order_tax'] );
125 $order->set_order_email( $order_data['customer_email'] );
126 $order->set_created_via( 'store-csv-import' );
127
128 $user = get_user_by( 'email', $order_data['customer_email'] );
129 if ( $user ) {
130 $order->set_customer_id( $user->ID );
131 }
132
133 $order->set_date_created_gmt( empty( $order_data['date_created_gmt'] ) ? current_time( 'timestamp' ) : $order_data['date_created_gmt'] );
134 if ( ! empty( $order_data['date_updated_gmt'] ) ) {
135 $order->set_date_updated_gmt( $order_data['date_updated_gmt'] );
136 }
137 if ( ! empty( $order_data['date_placed_gmt'] ) ) {
138 $order->set_order_placed_date_gmt( $order_data['date_placed_gmt'] );
139 $order->set_order_placed_date( get_date_from_gmt( $order_data['date_placed_gmt'] ) );
140 }
141 if ( ! empty( $order_data['order_paid_date_gmt'] ) ) {
142 $order->set_date_paid_gmt( $order_data['order_paid_date_gmt'] );
143 }
144
145 $order->set_payment_method( $order_data['payment_method'] );
146 $order->set_payment_method_title( $order_data['payment_method_title'] );
147 if ( isset( $order_data['transaction_id'] ) ) {
148 $order->set_transaction_id( $order_data['transaction_id'] );
149 }
150 if ( isset( $order_data['ip_address'] ) ) {
151 $order->set_ip_address( $order_data['ip_address'] );
152 }
153 if ( isset( $order_data['user_agent'] ) ) {
154 $order->set_user_agent( $order_data['user_agent'] );
155 }
156 if ( isset( $order_data['customer_note'] ) ) {
157 $order->set_customer_note( $order_data['customer_note'] );
158 }
159 if ( isset( $order_data['cart_hash'] ) ) {
160 $order->set_cart_hash( $order_data['cart_hash'] );
161 }
162
163 if ( ! empty( $order_data['meta_data'] ) ) {
164 $meta_data = explode( '|', $order_data['meta_data'] );
165 foreach ( $meta_data as $meta_datum ) {
166 $meta_datum = explode( ':', $meta_datum );
167 if ( 2 !== count( $meta_datum ) ) {
168 continue;
169 }
170 $order->update_meta_data( $meta_datum[0], $meta_datum[1] );
171 }
172 }
173
174 $product_ids = [];
175 if ( ! empty( $order_data['order_items'] ) && is_array( $order_data['order_items'] ) ) {
176 foreach ( $order_data['order_items'] as $order_item_data ) {
177 $product_slug = trim( $order_item_data['product_slug'] );
178 $posts = get_posts( [
179 'name' => $product_slug,
180 'post_type' => 'storeengine_product',
181 'fields' => 'ids',
182 'post_status' => 'publish',
183 'posts_per_page' => 1,
184 ] );
185 $has_product = ! empty( $posts );
186 $product_obj = false;
187 if ( $has_product ) {
188 $product_obj = Helper::get_product( $posts[0] );
189 }
190
191 $order_product_item = new Order\OrderItemProduct();
192 if ( $product_obj ) {
193 $product_ids[ $product_slug ] = $product_obj->get_id();
194 $order_product_item->set_product_id( $product_obj->get_id() );
195 $price_id = false;
196 $price_obj = null;
197 foreach ( $product_obj->get_prices() as $price ) {
198 if ( (float) $order_item_data['price'] === $price->get_price() && $order_item_data['price_name'] === $price->get_name() && $order_item_data['price_type'] === $price->get_type() && (
199 'onetime' === $order_item_data['price_type'] ||
200 ( 'subscription' === $order_item_data['price_type']
201 && $order_item_data['payment_duration'] === $price->get_payment_duration() && $order_item_data['payment_duration_type'] === $price->get_payment_duration_type() )
202 ) ) {
203 $price_id = $price->get_id();
204 $price_obj = $price;
205 break;
206 }
207 }
208 if ( $price_id ) {
209 $order_product_item->set_price_id( $price_id );
210 if ( 'subscription' !== $price_obj->get_type() && 'completed' === $order_data['order_status'] ) {
211 try {
212 $integrations = Helper::get_integrations_by_price_id( $price_obj->get_id() );
213 foreach ( $integrations as $integration ) {
214 AbstractIntegration::get_integration( $integration->get_provider() )->run_integration( $order_product_item, $order );
215 }
216 } catch ( StoreEngineException $e ) {
217 Helper::log_error( $e );
218 }
219 }
220 }
221 }
222
223 $meta_data = explode( '|', $order_item_data['meta_data'] );
224 unset( $order_item_data['meta_data'] );
225 foreach ( $meta_data as $meta_datum ) {
226 $meta_datum = explode( ':', $meta_datum );
227 if ( 2 !== count( $meta_datum ) ) {
228 continue;
229 }
230 $order_product_item->update_meta_data( $meta_datum[0], $meta_datum[1] );
231 }
232
233 foreach ( $order_item_data as $key => $value ) {
234 if ( method_exists( $order_product_item, "set_$key" ) ) {
235 $order_product_item->{"set_$key"}( $value );
236 }
237 }
238
239 $order->add_item( $order_product_item );
240 }
241 }
242
243 if ( ! empty( $order_data['billing_address'] ) && is_array( $order_data['billing_address'] ) ) {
244 foreach ( $order_data['billing_address'] as $billing_address_data ) {
245 foreach ( $billing_address_data as $key => $value ) {
246 if ( method_exists( $order, "set_$key" ) ) {
247 $order->{"set_$key"}( $value );
248 }
249 }
250 }
251 }
252
253 if ( ! empty( $order_data['shipping_address'] ) && is_array( $order_data['shipping_address'] ) ) {
254 foreach ( $order_data['shipping_address'] as $shipping_address_data ) {
255 foreach ( $shipping_address_data as $key => $value ) {
256 if ( method_exists( $order, "set_$key" ) ) {
257 $order->{"set_$key"}( $value );
258 }
259 }
260 }
261 }
262
263 if ( ! empty( $order_data['coupons'] ) && is_array( $order_data['coupons'] ) ) {
264 foreach ( $order_data['coupons'] as $coupon_data ) {
265 if ( ! isset( $coupon_data['discount'], $coupon_data['code'], $coupon_data['discount_tax'] ) ) {
266 continue;
267 }
268 $coupon = new Order\OrderItemCoupon();
269 $coupon->set_code( $coupon_data['code'] );
270 $coupon->set_discount( $coupon_data['discount'] );
271 $coupon->set_discount_tax( $coupon_data['discount_tax'] );
272 $order->add_item( $coupon );
273 }
274 }
275
276 if ( ! empty( $order_data['taxes'] ) && is_array( $order_data['taxes'] ) ) {
277 foreach ( $order_data['taxes'] as $tax_data ) {
278 if ( ! isset( $tax_data['name'], $tax_data['label'], $tax_data['tax_total'], $tax_data['rate_percent'], $tax_data['shipping_tax_total'] ) ) {
279 continue;
280 }
281
282 $tax = new Order\OrderItemTax();
283 foreach ( $tax_data as $key => $value ) {
284 if ( method_exists( $tax, "set_$key" ) ) {
285 $tax->{"set_$key"}( $value );
286 }
287 }
288 $order->add_item( $tax );
289 }
290 }
291
292 if ( ! empty( $order_data['shipping'] ) && is_array( $order_data['shipping'] ) ) {
293 foreach ( $order_data['shipping'] as $shipping_data ) {
294 $shipping = new Order\OrderItemShipping();
295 foreach ( $shipping_data as $key => $value ) {
296 if ( method_exists( $shipping, "set_$key" ) ) {
297 $shipping->{"set_$key"}( $value );
298 }
299 }
300 $order->add_item( $shipping );
301 }
302 }
303
304 if ( ! empty( $order_data['fees'] ) && is_array( $order_data['fees'] ) ) {
305 foreach ( $order_data['fees'] as $fee_data ) {
306 $fee = new Order\OrderItemFee();
307 foreach ( $fee_data as $key => $value ) {
308 if ( method_exists( $fee, "set_$key" ) ) {
309 $fee->{"set_$key"}( $value );
310 }
311 }
312 $order->add_item( $fee );
313 }
314 }
315
316 $order->save();
317 \StoreEngine\Schedules\Order::set_product_lookup_schedule( $order );
318
319 if ( ! empty( $order_data['refunds'] ) && is_array( $order_data['refunds'] ) ) {
320 foreach ( $order_data['refunds'] as $refund_data ) {
321 $refund = new Refund();
322 $refund->set_parent_order_id( $order->get_id() );
323 foreach ( $refund_data as $key => $value ) {
324 if ( method_exists( $refund, "set_$key" ) ) {
325 $refund->{"set_$key"}( $value );
326 }
327 }
328 $refund->save();
329 }
330 }
331
332 if ( ! empty( $order_data['downloads'] ) && is_array( $order_data['downloads'] ) && $order->get_customer_id() ) {
333 foreach ( $order_data['downloads'] as $download_data ) {
334 $product_slug = trim( $download_data['product_slug'] );
335 if ( ! isset( $product_ids[ $product_slug ] ) ) {
336 continue;
337 }
338
339 $download = new DownloadPermission();
340 $download->set_user_id( $order->get_customer_id() );
341 $download->set_order_id( $order->get_id() );
342 $download->set_product_id( $product_ids[ $product_slug ] );
343 $download->set_download_id( $download_data['download_id'] );
344 $download->set_access_granted( empty( $download_data['access_granted'] ) ? current_time( 'mysql' ) : $download_data['access_granted'] );
345 $download->save();
346 }
347 }
348
349 $stream->emitEvent( [
350 'type' => 'progress',
351 'percentage' => round( ( $index / $orders_count ) * 100 ),
352 ] );
353 $index ++;
354 }
355
356 delete_transient( 'storeengine_csv_orders_' . $filename . '_' . $start_index );
357 wp_cache_flush();
358
359 $stream->emitEvent( [
360 'type' => 'completed',
361 ], true );
362 }
363
364 public static function import_chunk_subscriptions( string $filename, int $start_index, EventStreamServer $stream ) {
365 $filename = Helper::get_filename_without_extension( $filename );
366 $subscriptions = get_transient( 'storeengine_csv_subscriptions_' . $filename . '_' . $start_index );
367 if ( ! $subscriptions ) {
368 $stream->emitEvent( [
369 'type' => 'error',
370 'message' => __( 'Unable to retrieve chunked subscriptions.', 'storeengine' ),
371 ], true );
372 }
373
374 $subscriptions_count = get_transient( 'storeengine_csv_subscriptions_' . $filename . '_count' );
375 $index = ( $start_index * 30 ) + 1;
376 foreach ( $subscriptions as $subscription_key => $subscription_data ) {
377 try {
378 $has_subscription = ( new Subscription() )->get_by_key( $subscription_key );
379 } catch ( StoreEngineException $e ) {
380 $has_subscription = false;
381 }
382 if ( $has_subscription ) {
383 continue;
384 }
385 $subscription = new Subscription();
386 $subscription->set_order_key( $subscription_key );
387 $subscription->set_status( $subscription_data['subscription_status'] );
388 $subscription->set_currency( $subscription_data['subscription_currency'] );
389 $subscription->set_total( $subscription_data['subscription_total'] );
390 $subscription->set_cart_tax( $subscription_data['subscription_tax'] );
391 $subscription->set_order_email( $subscription_data['customer_email'] );
392 $subscription->set_created_via( 'store-csv-import' );
393
394 $user = get_user_by( 'email', $subscription_data['customer_email'] );
395 if ( $user ) {
396 $subscription->set_customer_id( $user->ID );
397 }
398
399 $subscription->set_date_created_gmt( empty( $subscription_data['date_created_gmt'] ) ? current_time( 'timestamp' ) : $subscription_data['date_created_gmt'] );
400 if ( ! empty( $subscription_data['date_updated_gmt'] ) ) {
401 $subscription->set_date_updated_gmt( $subscription_data['date_updated_gmt'] );
402 }
403 if ( ! empty( $subscription_data['order_paid_date_gmt'] ) ) {
404 $subscription->set_date_paid_gmt( $subscription_data['order_paid_date_gmt'] );
405 }
406
407 $subscription->set_payment_method( $subscription_data['payment_method'] );
408 $subscription->set_payment_method_title( $subscription_data['payment_method_title'] );
409 if ( isset( $subscription_data['ip_address'] ) ) {
410 $subscription->set_ip_address( $subscription_data['ip_address'] );
411 }
412 if ( isset( $subscription_data['user_agent'] ) ) {
413 $subscription->set_user_agent( $subscription_data['user_agent'] );
414 }
415 if ( isset( $subscription_data['customer_note'] ) ) {
416 $subscription->set_customer_note( $subscription_data['customer_note'] );
417 }
418 if ( isset( $subscription_data['cart_hash'] ) ) {
419 $subscription->set_cart_hash( $subscription_data['cart_hash'] );
420 }
421 $subscription->set_start_date( $subscription_data['start_date'] );
422 $subscription->set_trial( Formatting::string_to_bool( $subscription_data['has_trial'] ) );
423 $subscription->set_trial_days( $subscription_data['trial_days'] );
424 $subscription->set_trial_end_date( $subscription_data['trial_end_date'] );
425 $subscription->set_next_payment_date( $subscription_data['next_payment_date'] );
426
427 if ( ! empty( $subscription_data['meta_data'] ) ) {
428 $meta_data = explode( '|', $subscription_data['meta_data'] );
429 foreach ( $meta_data as $meta_datum ) {
430 $meta_datum = explode( ':', $meta_datum );
431 if ( 2 !== count( $meta_datum ) ) {
432 continue;
433 }
434 $subscription->update_meta_data( $meta_datum[0], $meta_datum[1] );
435 }
436 }
437
438 $parent_order = Helper::get_order_by_key( $subscription_data['parent_order_key'] );
439 if ( ! is_wp_error( $parent_order ) ) {
440 $subscription->set_parent_order_id( $parent_order->get_id() );
441 }
442
443 $product_ids = [];
444 if ( ! empty( $subscription_data['order_items'] ) && is_array( $subscription_data['order_items'] ) ) {
445 foreach ( $subscription_data['order_items'] as $order_item_data ) {
446 $product_slug = trim( $order_item_data['product_slug'] );
447 $posts = get_posts( [
448 'name' => $product_slug,
449 'post_type' => 'storeengine_product',
450 'fields' => 'ids',
451 'post_status' => 'publish',
452 'posts_per_page' => 1,
453 ] );
454 $has_product = ! empty( $posts );
455 $product_obj = false;
456 if ( $has_product ) {
457 $product_obj = Helper::get_product( $posts[0] );
458 }
459
460 $order_product_item = new Order\OrderItemProduct();
461 if ( $product_obj ) {
462 $product_ids[ $product_slug ] = $product_obj->get_id();
463 $order_product_item->set_product_id( $product_obj->get_id() );
464 $price_id = false;
465 foreach ( $product_obj->get_prices() as $price ) {
466 if ( (float) $order_item_data['price'] === $price->get_price() && $order_item_data['price_name'] === $price->get_name() && $order_item_data['price_type'] === $price->get_type() && $order_item_data['payment_duration'] === $price->get_payment_duration() && $order_item_data['payment_duration_type'] === $price->get_payment_duration_type() ) {
467 $price_id = $price->get_id();
468 break;
469 }
470 }
471 if ( $price_id ) {
472 $order_product_item->set_price_id( $price_id );
473 }
474 }
475
476 $meta_data = explode( '|', $order_item_data['meta_data'] );
477 unset( $order_item_data['meta_data'] );
478 foreach ( $meta_data as $meta_datum ) {
479 $meta_datum = explode( ':', $meta_datum );
480 if ( 2 !== count( $meta_datum ) ) {
481 continue;
482 }
483 $order_product_item->update_meta_data( $meta_datum[0], $meta_datum[1] );
484 }
485
486 foreach ( $order_item_data as $key => $value ) {
487 if ( method_exists( $order_product_item, "set_$key" ) ) {
488 $order_product_item->{"set_$key"}( $value );
489 }
490 }
491
492 $subscription->add_item( $order_product_item );
493 }
494 }
495
496 if ( ! empty( $subscription_data['billing_address'] ) && is_array( $subscription_data['billing_address'] ) ) {
497 foreach ( $subscription_data['billing_address'] as $billing_address_data ) {
498 foreach ( $billing_address_data as $key => $value ) {
499 if ( method_exists( $subscription, "set_$key" ) ) {
500 $subscription->{"set_$key"}( $value );
501 }
502 }
503 }
504 }
505
506 if ( ! empty( $subscription_data['shipping_address'] ) && is_array( $subscription_data['shipping_address'] ) ) {
507 foreach ( $subscription_data['shipping_address'] as $shipping_address_data ) {
508 foreach ( $shipping_address_data as $key => $value ) {
509 if ( method_exists( $subscription, "set_$key" ) ) {
510 $subscription->{"set_$key"}( $value );
511 }
512 }
513 }
514 }
515
516 if ( ! empty( $subscription_data['coupons'] ) && is_array( $subscription_data['coupons'] ) ) {
517 foreach ( $subscription_data['coupons'] as $coupon_data ) {
518 if ( ! isset( $coupon_data['discount'], $coupon_data['code'], $coupon_data['discount_tax'] ) ) {
519 continue;
520 }
521 $coupon = new Order\OrderItemCoupon();
522 $coupon->set_code( $coupon_data['code'] );
523 $coupon->set_discount( $coupon_data['discount'] );
524 $coupon->set_discount_tax( $coupon_data['discount_tax'] );
525 $subscription->add_item( $coupon );
526 }
527 }
528
529 if ( ! empty( $subscription_data['taxes'] ) && is_array( $subscription_data['taxes'] ) ) {
530 foreach ( $subscription_data['taxes'] as $tax_data ) {
531 if ( ! isset( $tax_data['name'], $tax_data['label'], $tax_data['tax_total'], $tax_data['rate_percent'], $tax_data['shipping_tax_total'] ) ) {
532 continue;
533 }
534
535 $tax = new Order\OrderItemTax();
536 foreach ( $tax_data as $key => $value ) {
537 if ( method_exists( $tax, "set_$key" ) ) {
538 $tax->{"set_$key"}( $value );
539 }
540 }
541 $subscription->add_item( $tax );
542 }
543 }
544
545 if ( ! empty( $subscription_data['shipping'] ) && is_array( $subscription_data['shipping'] ) ) {
546 foreach ( $subscription_data['shipping'] as $shipping_data ) {
547 $shipping = new Order\OrderItemShipping();
548 foreach ( $shipping_data as $key => $value ) {
549 if ( method_exists( $shipping, "set_$key" ) ) {
550 $shipping->{"set_$key"}( $value );
551 }
552 }
553 $subscription->add_item( $shipping );
554 }
555 }
556
557 if ( ! empty( $subscription_data['fees'] ) && is_array( $subscription_data['fees'] ) ) {
558 foreach ( $subscription_data['fees'] as $fee_data ) {
559 $fee = new Order\OrderItemFee();
560 foreach ( $fee_data as $key => $value ) {
561 if ( method_exists( $fee, "set_$key" ) ) {
562 $fee->{"set_$key"}( $value );
563 }
564 }
565 $subscription->add_item( $fee );
566 }
567 }
568
569 $subscription->save();
570
571 if ( ! empty( $subscription_data['child_order_keys'] ) ) {
572 $child_order_keys = explode( ',', $subscription_data['child_order_keys'] );
573 foreach ( $child_order_keys as $child_order_key ) {
574 $order = Helper::get_order_by_key( $child_order_key );
575 if ( ! is_wp_error( $order ) ) {
576 $order->add_meta_data( '_subscription_id', $subscription->get_id() );
577 $order->add_meta_data( '_subscription_renewal', $subscription->get_id() );
578 $order->save();
579 }
580 }
581 }
582
583 foreach ( $subscription->get_items() as $subscription_item ) {
584 /** @var Order\OrderItemProduct $subscription_item */
585 try {
586 $integrations = Helper::get_integrations_by_price_id( $subscription_item->get_price_id() );
587 foreach ( $integrations as $integration ) {
588 AbstractIntegration::get_integration( $integration->get_provider() )->handle_subscription_status_changed( $subscription, $subscription->get_status() );
589 }
590 } catch ( StoreEngineException $e ) {
591 Helper::log_error( $e );
592 }
593 }
594
595 $stream->emitEvent( [
596 'type' => 'progress',
597 'percentage' => round( ( $index / $subscriptions_count ) * 100 ),
598 ] );
599 $index ++;
600 }
601
602 delete_transient( 'storeengine_csv_subscriptions_' . $filename . '_' . $start_index );
603 wp_cache_flush();
604
605 $stream->emitEvent( [
606 'type' => 'completed',
607 ], true );
608 }
609
610 public static function store_chunk_data( string $type, string $filename, array $data ): array {
611 $expire = 60 * 60 * 4;
612 $chunked_data = array_chunk( $data, 30, true );
613 $filename = Helper::get_filename_without_extension( $filename );
614 set_transient( "storeengine_csv_{$type}_" . $filename . '_count', count( $data ), $expire );
615 foreach ( $chunked_data as $index => $chunk ) {
616 set_transient( "storeengine_csv_{$type}_" . $filename . '_' . $index, $chunk, $expire );
617 }
618
619 return $chunked_data;
620 }
621
622 public static function generate_unique_username( $first_name, $last_name ): string {
623 // Build base username (first + last, lowercase, sanitized)
624 $base = sanitize_user( strtolower( $first_name . '.' . $last_name ), true );
625 $user = $base;
626 $suffix = 1;
627
628 // Ensure uniqueness
629 while ( username_exists( $user ) ) {
630 $user = $base . $suffix;
631 $suffix ++;
632 }
633
634 return $user;
635 }
636
637 public static function validate_data_type( string $type = null ) {
638 if ( ! $type ) {
639 return new \WP_Error( 'invalid_type', esc_html__( 'Type is required.', 'storeengine' ) );
640 }
641
642 if ( ! in_array( $type, [ 'products', 'orders', 'customers', 'access_groups', 'subscriptions' ], true ) ) {
643 return new \WP_Error( 'type-not-supported', esc_html__( 'Invalid type!', 'storeengine' ) );
644 }
645
646 if ( 'access_groups' === $type && ! Helper::get_addon_active_status( 'membership' ) ) {
647 return new \WP_Error( 'membership-addon-not-active', esc_html__( 'Please active Membership addon to export Access groups.', 'storeengine' ) );
648 }
649
650 if ( 'subscriptions' === $type && ! Helper::get_addon_active_status( 'subscription' ) ) {
651 return new \WP_Error( 'subscription-addon-not-active', esc_html__( 'Please active Subscription addon to export Subscriptions.', 'storeengine' ) );
652 }
653
654 return true;
655 }
656 }
657