PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 1.2.3
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v1.2.3
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 1.8.1 All 42 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.2.3, at includes/elementor/modules/checkout/classes/global-hooks.php

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