PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 1.1.0
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v1.1.0
2.7.0 2.6.0 trunk 1.1.0 1.1.4 1.2.1 1.2.2 1.2.3 1.2.5 1.2.9 1.3.1 1.3.2 1.5.0 1.5.1 1.5.4 1.5.7 1.5.8 1.5.9 1.6.2 1.6.5 1.6.8 1.7.2 1.7.4 1.7.5 1.7.9 All 43 releases
sellkit / includes / elementor / modules / checkout / classes / global-hooks.php

global-hooks.php in SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster 1.1.0, at includes/elementor/modules/checkout/classes/global-hooks.php

748 lines 21.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Sellkit\Elementor\Modules\Checkout\Classes;
4
5 defined( 'ABSPATH' ) || exit;
6
7 use Sellkit\Elementor\Modules\Checkout\Classes\Local_Hooks;
8 use Elementor\Plugin as Elementor;
9
10 /**
11 * Global hooks.
12 *
13 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
14 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
15 * @since 1.1.0
16 */
17 class Global_Hooks {
18 /**
19 * Create instance of class without construct.
20 *
21 * @since 1.1.0
22 * @return object
23 */
24 public static function instance() {
25 $class = new \ReflectionClass( __CLASS__ );
26 return $class->newInstanceWithoutConstructor();
27 }
28
29 /**
30 * Class construct.
31 * required actions that affects woocommerce global checkout shortcode / page.
32 *
33 * @since 1.1.0
34 */
35 public function __construct() {
36 // Create empty shortcode to simulate our widget page as checkout page.
37 add_shortcode( 'sellkit_checkout_widget_simulated', function() {
38 return '';
39 } );
40
41 add_action( 'wp_ajax_sellkit_checkout_ajax_handler', [ $this, 'ajax_handler' ] );
42 add_action( 'wp_ajax_nopriv_sellkit_checkout_ajax_handler', [ $this, 'ajax_handler' ] );
43
44 // Add shipping total to review order by custom hook.
45 add_action( 'sellkit-checkout-widget-display-shipping-price', [ $this, 'add_shipping_total_to_review_order' ] );
46
47 // Modify checkout order-review item.
48 add_action( 'sellkit-one-page-checkout-custom-order-item', [ $this, 'modify_checkout_order_item' ], 1, 4 );
49
50 // Modify sent data before processing & validate order.
51 add_filter( 'woocommerce_checkout_posted_data', [ $this, 'modify_order_data_before_validate' ], 10, 1 );
52
53 // Validate user defined fields.
54 add_action( 'woocommerce_checkout_process', [ $this, 'validate_user_defined_fields' ] );
55
56 // Save user defined fields.
57 add_action( 'woocommerce_checkout_update_order_meta', [ $this, 'save_user_defined_fields' ] );
58
59 // Add custom shipping field to email.
60 add_filter( 'woocommerce_order_get_formatted_shipping_address', [ $this, 'attach_user_shipping_fields_to_order_email' ], 10, 3 );
61
62 // Add custom billing field to email.
63 add_filter( 'woocommerce_order_get_formatted_billing_address', [ $this, 'attach_user_billing_fields_to_order_email' ], 10, 3 );
64
65 // Filter checkout ajax fragment.
66 add_filter( 'woocommerce_update_order_review_fragments', [ $this, 'checkout_fragment' ] );
67
68 // Simulate checkout page for our widget.
69 add_action( 'wp', [ $this, 'simulate_our_widget_page_as_checkout' ] );
70
71 // Fix shipping method price change on ajax.
72 // Manage bump order discounts.
73 add_action( 'woocommerce_checkout_update_order_review', [ $this, 'sellkit_custom_shipping_state' ], 10, 1 );
74 }
75
76 /**
77 * Handle ajax calls.
78 *
79 * @since 1.1.0
80 * @return void
81 */
82 public function ajax_handler() {
83 check_ajax_referer( 'sellkit_elementor', 'nonce' );
84
85 $sub_action = filter_input( INPUT_POST, 'sub_action', FILTER_SANITIZE_STRING );
86
87 if ( method_exists( $this, $sub_action ) ) {
88 call_user_func( [ $this, $sub_action ] );
89 return;
90 }
91
92 wp_send_json_error();
93 }
94
95 /**
96 * Modify checkout ajax response HTML.
97 *
98 * @param array $response woocommerce checkout page ajax response.
99 * @return array
100 * @since 1.1.0
101 */
102 public function checkout_fragment( $response ) {
103 // Get posted data and identify if it's been sent by jupiter widget or not.
104 $checkout_form_data = filter_input( INPUT_POST, 'post_data', FILTER_SANITIZE_STRING );
105 $checkout_form_data = explode( '&', $checkout_form_data );
106 $posted_data = [];
107
108 foreach ( $checkout_form_data as $input ) {
109 $item = explode( '=', urldecode( $input ) );
110
111 $posted_data[ $item[0] ] = $item[1];
112 }
113
114 // Identify if it's been sent by jupiter checkout widget or not.
115 if ( ! array_key_exists( 'form_id', $posted_data ) && ! array_key_exists( 'post_id', $posted_data ) ) {
116 // Default woocommerce checkout.
117 return $response;
118 }
119
120 // Current checkout created by sellkit checkout widget: so apply what we needs.
121 add_filter( 'wc_get_template', function( $located, $template_name ) {
122 $our_path = sellkit()->plugin_dir() . 'includes/elementor/modules/checkout/templates/';
123 $files = [
124 'review-order.php',
125 'payment-method.php',
126 'payment.php',
127 'form-checkout.php',
128 'cart-item-data.php',
129 'cart-shipping.php',
130 ];
131 $template = str_replace( 'checkout/', '', $template_name );
132 $template = str_replace( 'cart/', '', $template );
133
134 if ( in_array( $template, $files, true ) ) {
135 $located = $our_path . $template;
136 }
137
138 return $located;
139 }, 10, 2 );
140
141 // Inject widget custom coupon form by custom hook.
142 $widget_settings = Helper::instance()->retrieve_checkout_widget_settings( $posted_data['post_id'], $posted_data['form_id'] );
143
144 Local_Hooks::enable_disable_sections( $widget_settings, $posted_data );
145
146 // Order review fragment.
147 ob_start();
148 woocommerce_order_review();
149 $order_review = ob_get_clean();
150
151 // Payment fragment.
152 ob_start();
153 woocommerce_checkout_payment();
154 $payment = ob_get_clean();
155
156 // Shipping method fragment.
157 ob_start();
158 echo '<section class="sellkit-one-page-shipping-methods">';
159 wc_cart_totals_shipping_html();
160 echo '</section>';
161 $shipping_method = ob_get_clean();
162
163 $response['.woocommerce-checkout-review-order-table'] = $order_review;
164 $response['.woocommerce-checkout-payment'] = $payment;
165 $response['.sellkit-one-page-shipping-methods'] = '';
166
167 if ( ! array_key_exists( 'show_shipping_method', $widget_settings ) ) {
168 $response['.sellkit-one-page-shipping-methods'] = $shipping_method;
169 }
170
171 return $response;
172 }
173
174 /**
175 * Apply coupon code using ajax.
176 *
177 * @return void
178 * @since 1.1.0
179 */
180 public function apply_coupon() {
181 $code = filter_input( INPUT_POST, 'code', FILTER_SANITIZE_STRING );
182
183 if ( empty( $code ) ) {
184 wp_send_json_error();
185 }
186
187 $result = WC()->cart->add_discount( $code );
188 wp_send_json_success( $result );
189 }
190
191 /**
192 * Update cart item quantity in checkout page by ajax.
193 *
194 * @return void
195 * @since 1.1.0
196 */
197 public function change_cart_item_qty() {
198 $qty = filter_input( INPUT_POST, 'qty', FILTER_SANITIZE_NUMBER_INT );
199 $id = filter_input( INPUT_POST, 'id', FILTER_SANITIZE_STRING );
200 $action = filter_input( INPUT_POST, 'mode', FILTER_SANITIZE_STRING );
201
202 if ( 'add' === $action ) {
203 WC()->cart->add_to_cart( $id, $qty );
204 return;
205 }
206
207 if ( 'remove' === $action ) {
208 $product_cart_id = WC()->cart->generate_cart_id( $id );
209 $cart_item_key = WC()->cart->find_product_in_cart( $product_cart_id );
210
211 if ( $cart_item_key ) {
212 WC()->cart->remove_cart_item( $cart_item_key );
213 }
214
215 return;
216 }
217
218 ( $qty > 0 ) ? WC()->cart->set_quantity( $id, $qty ) : WC()->cart->remove_cart_item( $id );
219
220 wp_send_json_success();
221 }
222
223 /**
224 * Place shipping price based on design to checkout order-review.
225 *
226 * @return void
227 * @since 1.1.0
228 */
229 public function add_shipping_total_to_review_order() {
230 ?>
231 <tr class="sellkit-shipping-total">
232 <th><?php echo __( 'Shipping', 'sellkit' ); ?></th>
233 <td><?php echo wc_price( WC()->cart->get_shipping_total() ); ?></td>
234 </tr>
235 <?php
236 }
237
238 /**
239 * Modify checkout review-order based on design.
240 *
241 * @return void
242 * @param string $row html string of cart row.
243 * @param object $product product object.
244 * @param array $cart_item cart item information.
245 * @param string $cart_item_key cart item unique key.
246 * @since 1.1.0
247 */
248 public function modify_checkout_order_item( $row, $product, $cart_item, $cart_item_key ) {
249 $cart_items = WC()->cart->get_cart();
250
251 //phpcs:disable
252 ob_start();
253 ?>
254 <div style="display: inline-block" class="sellkit-checkout-widget-item-image">
255 <?php echo $product->get_image(); ?>
256 </div>
257 <?php
258 $img_html = ob_get_clean();
259 $img_html = apply_filters( 'sellkit/includes/elementor/modules/checkout/product-image', $img_html, $product, $cart_item_key );
260
261 ob_start();
262
263 $extra_class = '';
264 if ( $cart_items[ $cart_item_key ] === end( $cart_items ) ) {
265 $extra_class = ' last-cart-item';
266 }
267 ?>
268 <tr class="<?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ) . $extra_class; ?>">
269
270 <td class="product-name sellkit-one-page-checkout-product-name">
271 <?php
272 echo $img_html;
273
274 $fix_style = '';
275
276 if ( '' === $img_html ) {
277 $fix_style = 'margin-left: 0px;';
278 }
279 ?>
280
281 <div class="name-price" style="<?php echo esc_attr( $fix_style ); ?>">
282 <span style="display:inline-block">
283 <?php echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', $product->get_name(), $cart_item, $cart_item_key ) ) . '&nbsp;'; ?>
284 </span>
285 <span class="sellkit-checkout-variations">
286 <?php echo wc_get_formatted_cart_item_data( $cart_item ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
287 </span>
288 <?php echo apply_filters( 'sellkit-checkout-widget-disable-quantity', '<input type="number" data-id="' . esc_attr( $cart_item_key ) . '" value="' . esc_attr( $cart_item['quantity'] ) . '" class="sellkit-one-page-checkout-product-qty" >', $cart_item['quantity'] ); ?>
289 <?php do_action( 'sellkit-checkout-editor-mode-quantity', $cart_item['quantity'] ); ?>
290 </div>
291 </td>
292 <td class="product-total sellkit-one-page-checkout-product-price">
293 <?php echo apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $product, $cart_item['quantity'] ), $cart_item, $cart_item_key ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
294 </td>
295 </tr>
296 <?php
297 $cart_item = ob_get_clean();
298
299 echo apply_filters( 'sellkit-checkout-cart-item' , $cart_item );
300 //phpcs:enable
301 }
302
303 /**
304 * Modify fields after pressing place order button.
305 * we hooked here because some removed fields still get checked and have not removed by previous hooks.
306 *
307 * @param array $data checkout form data.
308 * @return array $data data of woocommerce checkout form.
309 * @since 1.1.0
310 */
311 public function modify_order_data_before_validate( $data ) {
312 $post_id = filter_input( INPUT_POST, 'post_id', FILTER_SANITIZE_NUMBER_INT );
313 $form_id = filter_input( INPUT_POST, 'form_id', FILTER_SANITIZE_STRING );
314
315 if ( empty( $post_id ) && empty( $form_id ) ) {
316 return $data;
317 }
318
319 $settings = Helper::instance()->retrieve_checkout_widget_settings( $post_id, $form_id );
320
321 if ( empty( $settings ) ) {
322 return $data;
323 }
324
325 $widget_shipping_field = Helper::instance()->get_user_defined_fields_slug( $settings['shipping_list'], 'shipping_list_field' );
326 $widget_billing_field = Helper::instance()->get_user_defined_fields_slug( $settings['billing_list'], 'billing_list_field' );
327
328 $default_shipping_fields = Helper::instance()->shipping_fields();
329 $default_billing_fields = Helper::instance()->billing_fields();
330
331 // Unset removed shipping fields.
332 foreach ( $default_shipping_fields as $field => $details ) {
333 if ( ! in_array( $field, $widget_shipping_field, true ) ) {
334 unset( $data[ $field ] );
335 }
336 }
337
338 // Unset removed billing fields.
339 foreach ( $default_billing_fields as $field => $details ) {
340 if ( ! in_array( $field, $widget_billing_field, true ) && 'billing_email' !== $field ) {
341 unset( $data[ $field ] );
342 }
343 }
344
345 return $data;
346 }
347
348 /**
349 * Login user by ajax.
350 * sign user in by using form included in widget.
351 *
352 * @return void
353 * @since 1.1.0
354 */
355 public function auth_user() {
356 $email = filter_input( INPUT_POST, 'email', FILTER_SANITIZE_EMAIL );
357 $pass = filter_input( INPUT_POST, 'pass', FILTER_SANITIZE_STRING );
358 $verify = filter_var( $email, FILTER_VALIDATE_EMAIL );
359
360 if ( ! $verify || empty( $email ) || empty( $pass ) ) {
361 wp_send_json_error( __( 'Email or password field is not valid.', 'sellkit' ) );
362 }
363
364 $result = wp_authenticate( $email, $pass );
365
366 if ( is_wp_error( $result ) ) {
367 wp_send_json_error( $result->get_error_message() );
368 }
369
370 wp_clear_auth_cookie();
371 wp_set_current_user( $result->ID );
372 wp_set_auth_cookie( $result->ID );
373
374 wp_send_json_success( $result );
375 }
376
377 /**
378 * Get widget settings in ajax calls using form and post id.
379 *
380 * @return void
381 * @since 1.1.0
382 */
383 private function widget_settings() {
384 $form_id = filter_input( INPUT_POST, 'form_id', FILTER_SANITIZE_STRING );
385 $post_id = filter_input( INPUT_POST, 'post_id', FILTER_SANITIZE_NUMBER_INT );
386
387 if ( empty( $form_id ) && empty( $post_id ) ) {
388 return;
389 }
390
391 $widget_settings = Helper::instance()->retrieve_checkout_widget_settings( $post_id, $form_id );
392
393 return $widget_settings;
394 }
395
396 /**
397 * Validate user defined custom value.
398 *
399 * @return void
400 * @since 1.1.0
401 */
402 public function validate_user_defined_fields() {
403 $widget_settings = $this->widget_settings();
404
405 if ( empty( $widget_settings ) ) {
406 return;
407 }
408
409 $widget_shipping_fields = $widget_settings['shipping_list'];
410 $widget_billing_fields = $widget_settings['billing_list'];
411
412 Helper::instance()->validate_user_defined_fields( $widget_shipping_fields, $widget_billing_fields );
413 Helper::instance()->make_sure_to_convert_required_field_to_optional( $widget_shipping_fields, $widget_billing_fields );
414 }
415
416 /**
417 * Save user defined custom fields value to database.
418 *
419 * @param int $order_id id of woocommerce order.
420 * @return void
421 * @since 1.1.0
422 */
423 public function save_user_defined_fields( $order_id ) {
424 $widget_settings = $this->widget_settings();
425
426 if ( empty( $widget_settings ) ) {
427 return;
428 }
429
430 $widget_shipping_fields = $widget_settings['shipping_list'];
431 $widget_billing_fields = $widget_settings['billing_list'];
432
433 Helper::instance()->save_user_defined_fields( $widget_shipping_fields, $widget_billing_fields, $order_id );
434 }
435
436 /**
437 * Attach user defined shipping field values to order emails.
438 *
439 * @param string $address address.
440 * @param string $raw_address raw address.
441 * @param object $order woocommerce order object.
442 * @return string
443 * @since 1.1.0
444 */
445 public function attach_user_shipping_fields_to_order_email( $address, $raw_address, $order ) {
446 $order_id = $order->get_id();
447 $custom_fields = get_post_meta( $order_id, 'sellkit_checkout_widget_custom_field_of_order', true );
448
449 if ( empty( $custom_fields ) || ! is_array( $custom_fields ) ) {
450 return $address;
451 }
452
453 foreach ( $custom_fields as $field ) {
454 if ( 'yes' !== $field['show_in_email'] ) {
455 continue;
456 }
457
458 $key = $field['key_name'];
459 $value = get_post_meta( $order_id, $key, true );
460
461 if ( strpos( $key, 'shipping' ) !== false ) {
462 $address .= '<br>' . $value;
463 }
464 }
465
466 return $address;
467 }
468
469 /**
470 * Attach user defined billing field values to order emails.
471 *
472 * @param string $address address.
473 * @param string $raw_address raw address.
474 * @param object $order woocommerce order object.
475 * @return string
476 * @since 1.1.0
477 */
478 public function attach_user_billing_fields_to_order_email( $address, $raw_address, $order ) {
479 $order_id = $order->get_id();
480 $custom_fields = get_post_meta( $order_id, 'sellkit_checkout_widget_custom_field_of_order', true );
481
482 if ( empty( $custom_fields ) || ! is_array( $custom_fields ) ) {
483 return $address;
484 }
485
486 foreach ( $custom_fields as $field ) {
487 if ( 'yes' !== $field['show_in_email'] ) {
488 continue;
489 }
490
491 $key = $field['key_name'];
492 $value = get_post_meta( $order_id, $key, true );
493
494 if ( strpos( $key, 'billing' ) !== false ) {
495 $address .= '<br>' . $value;
496 }
497 }
498
499 return $address;
500 }
501
502 /**
503 * Place custom coupon form in checkout order-review based design.
504 * We have used same form in Local_Hooks. but this one is for ajax response.
505 *
506 * @see sellkit_Core\Raven\Modules\Checkout\Classes\Local_Hooks::coupon_form.
507 * @param array $settings widget settings.
508 * @return void
509 * @since 1.1.0
510 */
511 public function coupon_form( $settings ) {
512 if ( array_key_exists( 'show_coupon_field', $settings ) ) {
513 return;
514 }
515
516 echo '<tr class="coupon-form border-none"><td colspan="2">';
517 Local_Hooks::form( $settings );
518 echo '</td></tr>';
519
520 do_action( 'sellkit-checkout-after-coupon-form-ajax' );
521 }
522
523 /**
524 * Look for an email if exists or not.
525 * Is used for login process.
526 *
527 * @return void
528 * @since 1.1.0
529 */
530 public function search_for_email() {
531 $email = filter_input( INPUT_POST, 'email', FILTER_SANITIZE_EMAIL );
532 $valid = filter_var( $email, FILTER_VALIDATE_EMAIL );
533
534 if ( ! $valid || empty( $email ) ) {
535 wp_send_json_error();
536 }
537
538 $check = email_exists( $email );
539
540 if ( false === $check ) {
541 wp_send_json_error();
542 }
543
544 wp_send_json_success();
545 }
546
547 /**
548 * Look for an username if exists or not.
549 * Is used for register process.
550 *
551 * @return void
552 * @since 1.1.0
553 */
554 public function search_for_username() {
555 $username = filter_input( INPUT_POST, 'user', FILTER_SANITIZE_EMAIL );
556
557 if ( empty( $username ) ) {
558 wp_send_json_error();
559 }
560
561 $username = sanitize_user( $username );
562 $check = username_exists( $username );
563
564 if ( false !== $check ) {
565 wp_send_json_error();
566 }
567
568 wp_send_json_success();
569 }
570
571 /**
572 * Validate postcode via ajax.
573 *
574 * @since 1.1.0
575 * @return void
576 */
577 public function validate_postcode() {
578 $country = filter_input( INPUT_POST, 'country_code', FILTER_SANITIZE_STRING );
579 $postcode = filter_input( INPUT_POST, 'post_code', FILTER_SANITIZE_STRING );
580 $parent = filter_input( INPUT_POST, 'parent', FILTER_DEFAULT );
581
582 $postcode = wc_format_postcode( $postcode, $country );
583 $valid = \WC_Validation::is_postcode( $postcode, $country );
584
585 if ( ! $valid ) {
586 wp_send_json_error( $parent );
587 }
588
589 wp_send_json_success( $parent );
590 }
591
592 /**
593 * Validate phone number via ajax.
594 *
595 * @since 1.1.0
596 * @return void
597 */
598 public function validate_phone_number() {
599 $phone = filter_input( INPUT_POST, 'phone_number', FILTER_SANITIZE_STRING );
600 $parent = filter_input( INPUT_POST, 'parent', FILTER_DEFAULT );
601
602 $valid = \WC_Validation::is_phone( $phone );
603
604 if ( ! $valid ) {
605 wp_send_json_error( $parent );
606 }
607
608 wp_send_json_success( $parent );
609 }
610
611 /**
612 * Simulate checkout page where our widget is present. using empty shortcode [sellkit_checkout_widget_simulated].
613 *
614 * @since 1.1.0
615 * @return void
616 */
617 public function simulate_our_widget_page_as_checkout() {
618 $page_id = get_the_ID();
619 $content = get_post_field( 'post_content', $page_id );
620
621 if ( false === strpos( $content, 'woocommerce_checkout' ) ) {
622 return;
623 }
624
625 add_filter( 'woocommerce_is_checkout', function() {
626 return true;
627 } );
628
629 if ( false === strpos( $content, 'sellkit_checkout_widget_simulated' ) ) {
630 return;
631 }
632
633 add_filter( 'theme_mod_jupiterx_jupiterx_checkout_cart_elements', function() {
634 return [];
635 }, 10 );
636 }
637
638 /**
639 * Integrate user country with our widget.
640 *
641 * @since 1.1.0
642 * @return void
643 */
644 public function set_customer_details_ajax() {
645 $country = filter_input( INPUT_POST, 'country', FILTER_SANITIZE_STRING );
646 $state = filter_input( INPUT_POST, 'state', FILTER_SANITIZE_STRING );
647 $shipping_country = filter_input( INPUT_POST, 'shipping_country', FILTER_SANITIZE_STRING );
648 $shipping_state = filter_input( INPUT_POST, 'shipping_state', FILTER_SANITIZE_STRING );
649
650 if ( ! empty( $country ) ) {
651 setcookie( 'sellkit-checkout-billing-cc', $country, time() + ( 86400 * 3 ), '/' );
652 setcookie( 'sellkit-checkout-billing-state', $state, time() + ( 86400 * 3 ), '/' );
653 }
654
655 if ( ! empty( $shipping_country ) ) {
656 setcookie( 'sellkit-checkout-shipping-cc', $shipping_country, time() + ( 86400 * 3 ), '/' );
657 setcookie( 'sellkit-checkout-shipping-state', $shipping_state, time() + ( 86400 * 3 ), '/' );
658 }
659
660 wp_send_json_success();
661 }
662
663 /**
664 * State lookup using postcode and country.
665 *
666 * @since 1.1.0
667 * @return void
668 */
669 public function sellkit_state_lookup_by_postcode() {
670 $country = filter_input( INPUT_POST, 'country_value', FILTER_SANITIZE_STRING );
671 $postcode = filter_input( INPUT_POST, 'postcode_value', FILTER_SANITIZE_STRING );
672 $api = 'https://api.zippopotam.us/' . $country . '/' . $postcode;
673
674 if ( empty( $country ) || empty( $postcode ) ) {
675 wp_send_json_error( esc_html__( 'Not valid inputs', 'sellkit' ) );
676 }
677
678 $response = wp_remote_get( $api );
679
680 if ( is_wp_error( $response ) || ! is_array( $response ) ) {
681 wp_send_json_error( esc_html__( 'Server error.', 'sellkit' ) );
682 }
683
684 if ( '{}' === $response['body'] ) {
685 wp_send_json_error( esc_html__( 'Selected country or postcode is not supported.', 'sellkit' ) );
686 }
687
688 wp_send_json_success( $response );
689 }
690
691 /**
692 * Modify cart contents using bundled products.
693 *
694 * @since 1.1.0
695 * @return void
696 */
697 public function sellkit_checkout_modify_cart_by_bundle_products() {
698 $qty = filter_input( INPUT_POST, 'qty', FILTER_SANITIZE_NUMBER_INT );
699 $id = filter_input( INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT );
700 $type = filter_input( INPUT_POST, 'type', FILTER_SANITIZE_STRING );
701
702 WC()->cart->empty_cart();
703
704 if ( 'radio' === $type ) {
705 WC()->cart->add_to_cart( $id, $qty );
706 }
707
708 wp_send_json_success();
709 }
710
711 /**
712 * Fix shipping method price on checkout ajax state change.
713 *
714 * @param string $data checkout form data.
715 * @since 1.1.0
716 * @return void
717 */
718 public function sellkit_custom_shipping_state( $data ) {
719 $data = explode( '&', $data );
720 $clear = [];
721
722 foreach ( $data as $key => $input ) {
723 $input = explode( '=', $input );
724 $clear[ $input[0] ] = $input[1];
725 }
726
727 if ( ! array_key_exists( 'form_id', $clear ) ) {
728 return;
729 }
730
731 if ( array_key_exists( 'shipping_state', $clear ) ) {
732 $_POST['s_state'] = $clear['shipping_state'];
733 }
734
735 if ( array_key_exists( 'billing_state', $clear ) ) {
736 $_POST['state'] = $clear['billing_state'];
737 }
738
739 Local_Hooks::order_bump( $clear );
740
741 if ( array_key_exists( 'sellkit-bundle-products', $clear ) ) {
742 $option = $clear['sellkit-bundle-products'];
743
744 Local_Hooks::bundle_product_action( $option );
745 }
746 }
747 }
748