PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 2.7.0
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v2.7.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
← All changes | includes/elementor/modules/checkout/classes/local-hooks.php +334 -54 1.5.02.7.0 View file →
@@ -5,8 +5,10 @@
5 5 defined( 'ABSPATH' ) || exit;
6 6
7 7 use Sellkit\Elementor\Modules\Checkout\Classes\{ Helper, Global_Hooks };
8 8 use Elementor\Plugin as Elementor;
9 +use Sellkit_Funnel;
10 +use Sellkit\Global_Checkout\Checkout;
9 11
10 12 /**
11 13 * Local hooks.
12 14 * Applies before widget.
@@ -14,12 +16,44 @@
14 16 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
15 17 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
16 18 * @SuppressWarnings(PHPMD.TooManyMethods)
17 19 * @SuppressWarnings(PHPMD.NPathComplexity)
20 + * @SuppressWarnings(PHPMD.CyclomaticComplexity)
18 21 * @since 1.1.0
19 22 */
20 23 class Local_Hooks {
21 24 /**
25 + * Checkout widget settings.
26 + *
27 + * @since 1.8.6
28 + * @var array
29 + */
30 + public $settings;
31 +
32 + /**
33 + * Checkout widget.
34 + *
35 + * @since 1.8.6
36 + * @var object
37 + */
38 + public $widget;
39 +
40 + /** Array of added products to cart.
41 + *
42 + * @since 1.7.9
43 + * @var array
44 + */
45 + public static $in_cart = [];
46 +
47 + /**
48 + * Checks if bumps applied.
49 + *
50 + * @since 1.8.1
51 + * @var bool
52 + */
53 + public static $is_bumps_applied = false;
54 +
55 + /**
22 56 * Create instance of class without construct.
23 57 *
24 58 * @since 1.1.0
25 59 * @return object
@@ -49,11 +83,8 @@
49 83 * @return void
50 84 * @since 1.1.0
51 85 */
52 86 private function actions() {
53 - // Empty cart notice.
54 - add_action( 'woocommerce_before_checkout_form_cart_notices', [ $this, 'empty_cart_notice' ] );
55 -
56 87 // sellkit wrapper for checkout widget.
57 88 add_action( 'woocommerce_before_checkout_form', [ $this, 'open_multistep_wrap' ] );
58 89 add_action( 'woocommerce_after_checkout_form', [ $this, 'close_multistep_wrap' ], 999 );
59 90
@@ -102,27 +133,17 @@
102 133 add_action( 'woocommerce_before_checkout_form', [ $this, 'order_bump' ] );
103 134
104 135 // Bundle products.
105 136 $this->bundled_products();
106 - }
107 137
108 - /**
109 - * Add custom notice if cart is empty.
110 - *
111 - * @return void
112 - * @since 1.1.0
113 - */
114 - public function empty_cart_notice() {
115 - global $woocommerce;
116 - $count = $woocommerce->cart->get_cart_contents_count();
138 + // Trigger for upsell steps popup.
139 + add_action( 'sellkit_checkout_required_hidden_fields', [ $this, 'add_trigger_field_for_upsell_steps' ] );
117 140
118 - if ( 0 === $count ) {
119 - /* translators: %s: Empty cart message. */
120 - echo sprintf(
121 - '<div class="elementor-alert elementor-alert-info">%s</div>',
122 - $this->settings['empty_cart']
123 - );
124 - }
141 + // Add upsell templates at the end of page.
142 + add_action( 'wp_footer', [ $this, 'sellkit_funnel_display_upsell_as_popup' ] );
143 +
144 + // Add order notes to checkout form to desired location.
145 + add_action( 'sellkit_checkout_after_term_and_condition', [ $this, 'order_notes' ] );
125 146 }
126 147
127 148 /**
128 149 * Opens a wrapper around widget checkout form.
@@ -325,9 +346,9 @@
325 346 $class = '\Sellkit\Elementor\Modules\Checkout\Fields\\' . ucfirst( $class );
326 347 $class = new $class();
327 348 $field = '';
328 349
329 - $class->final_html_structure( $field, $details, $key );
350 + $class->final_html_structure( $field, $details, $key, $checkout->get_value( $key ) );
330 351 }
331 352 }
332 353
333 354 /**
@@ -339,12 +360,13 @@
339 360 */
340 361 public function customize_billing_field( $default_fields ) {
341 362 $widget_billing_fields = $this->settings['billing_list'];
342 363 $widget_field_slug = Helper::instance()->get_user_defined_fields_slug( $widget_billing_fields, 'billing_list_field' );
364 + $core_billing_fields = array_keys( Helper::instance()->billing_fields() );
343 365
344 366 // Unset default fields.
345 367 foreach ( $default_fields as $key => $field ) {
346 - if ( ! in_array( $key, $widget_field_slug, true ) && 'billing_email' !== $field ) {
368 + if ( in_array( $key, $core_billing_fields, true ) && ! in_array( $key, $widget_field_slug, true ) && 'billing_email' !== $key ) {
347 369 unset( $default_fields[ $key ] );
348 370 }
349 371 }
350 372
@@ -413,9 +435,9 @@
413 435 $class = '\Sellkit\Elementor\Modules\Checkout\Fields\\' . ucfirst( $class );
414 436 $class = new $class();
415 437 $field = '';
416 438
417 - $field = $class->final_html_structure( $field, $details, $key );
439 + $field = $class->final_html_structure( $field, $details, $key, $checkout->get_value( $key ) );
418 440 }
419 441 }
420 442
421 443 /**
@@ -446,9 +468,9 @@
446 468 }
447 469 }
448 470
449 471 foreach ( $widget_shipping_fields as $data ) {
450 - $slug = $data['shipping_list_field'];
472 + $slug = isset( $data['shipping_list_field'] ) ? $data['shipping_list_field'] : '';
451 473
452 474 if ( 'yes' !== $data['shipping_list_required'] && array_key_exists( $slug, $default_fields['shipping'] ) ) {
453 475 $default_fields['shipping'][ $slug ]['required'] = false;
454 476 unset( $default_fields['shipping'][ $slug ]['required'] );
@@ -506,9 +528,9 @@
506 528 ?>
507 529 <section class="sellkit-checkout-widget-express-checkout sellkit-checkout-express-checkout-step-1">
508 530 <fieldset class="express-box sellkit-checkout-widget-divider">
509 531 <legend class="sellkit-express-checkout-legend heading">
510 - <?php echo __( 'Express Checkout', 'sellkit' ); ?>
532 + <?php echo esc_html__( 'Express Checkout', 'sellkit' ); ?>
511 533 </legend>
512 534 <div class="express-methods">
513 535 <?php do_action( 'sellkit-checkout-widget-express-methods' ); ?>
514 536 </div>
@@ -515,15 +537,15 @@
515 537 </fieldset>
516 538 </section>
517 539 <section class="sellkit-checkout-widget-express-checkout sellkit-checkout-express-checkout-step-2">
518 540 <fieldset id="sellkit-checkout-or-divider" class="divider-box sellkit-checkout-widget-divider">
519 - <legend class="heading"><?php echo __( 'OR', 'sellkit' ); ?></legend>
541 + <legend class="heading"><?php echo esc_html__( 'OR', 'sellkit' ); ?></legend>
520 542 </fieldset>
521 543 </section>
522 544 <?php
523 545 $express = ob_get_clean();
524 546 $express = apply_filters( 'sellkit-checkout-widget-express-checkout', $express );
525 - echo $express;
547 + echo wp_kses_post( $express );
526 548 }
527 549
528 550 /**
529 551 * Apply custom Messages.
@@ -543,9 +565,9 @@
543 565 add_action( 'sellkit_core/widgets/checkout/custom_message/create_website_account', function() {
544 566 $site = get_bloginfo( 'name' );
545 567 $text = $this->settings['create_website_account'];
546 568
547 - echo str_replace( '{{website}}', $site, $text );
569 + echo wp_kses_post( str_replace( '{{website}}', $site, $text ) );
548 570 } );
549 571
550 572 add_filter( 'sellkit_core/widgets/checkout/custom_message/secure_transaction_text', function() {
551 573 return $this->settings['secure_transaction_text'];
@@ -581,8 +603,23 @@
581 603 add_action( 'sellkit-checkout-widget-custom-coupon-form', function() use ( $settings ) {
582 604 Global_Hooks::instance()->coupon_form( $settings );
583 605 } );
584 606
607 + // Improve UI issue in the editor for the order summary input.
608 + add_filter( 'woocommerce_cart_item_class', function( $default ) use ( $settings, $posted_data ) {
609 + $default = str_replace( 'product-title-one-row', '', $default );
610 +
611 + if (
612 + ! array_key_exists( 'show_cart_edit', $settings ) ||
613 + array_key_exists( 'bundle-products-force', $posted_data ) ||
614 + empty( $settings['show_cart_edit'] )
615 + ) {
616 + $default .= ' product-title-one-row';
617 + }
618 +
619 + return $default;
620 + } );
621 +
585 622 return;
586 623 }
587 624
588 625 if ( wp_doing_ajax() ) {
@@ -604,9 +641,13 @@
604 641 } );
605 642
606 643 // Disable order item quantity input.
607 644 if ( array_key_exists( 'show_cart_edit', $settings ) || array_key_exists( 'bundle-products-force', $posted_data ) ) {
608 - add_action( 'sellkit-checkout-widget-disable-quantity', [ Helper::instance(), 'checkout_order_hidden_quantity' ], 10, 2 );
645 + add_filter( 'sellkit-checkout-widget-disable-quantity', [ Helper::instance(), 'checkout_order_hidden_quantity' ], 10, 2 );
646 +
647 + add_filter( 'woocommerce_cart_item_class', function( $default ) {
648 + return $default . ' product-title-one-row';
649 + } );
609 650 }
610 651
611 652 add_filter( 'woocommerce_shipping_package_name', function() {
612 653 return '<h4 id="shipping_header_title" class="shipping-method-header heading">' . esc_html__( 'Shipping Methods', 'sellkit' ) . '</h4>';
@@ -653,9 +694,9 @@
653 694 }, 10 );
654 695
655 696 // Disable order item quantity input.
656 697 if ( array_key_exists( 'show_cart_edit', $settings ) ) {
657 - add_action( 'sellkit-checkout-widget-disable-quantity', [ Helper::instance(), 'checkout_order_hidden_quantity' ], 10, 2 );
698 + add_filter( 'sellkit-checkout-widget-disable-quantity', [ Helper::instance(), 'checkout_order_hidden_quantity' ], 10, 2 );
658 699
659 700 add_filter( 'sellkit/includes/elementor/modules/checkout/quanity/class', function( $classes ) {
660 701 return $classes .= ' sellkit-checkout-widget-d-block';
661 702 } );
@@ -660,8 +701,14 @@
660 701 return $classes .= ' sellkit-checkout-widget-d-block';
661 702 } );
662 703 }
663 704
705 + if ( array_key_exists( 'show_cart_edit', $settings ) || array_key_exists( 'bundle-products-force', $posted_data ) ) {
706 + add_filter( 'woocommerce_cart_item_class', function( $default ) {
707 + return $default . ' product-title-one-row';
708 + } );
709 + }
710 +
664 711 add_filter( 'sellkit-checkout-place-order-btn-text', function( $place_order_btn ) {
665 712 if ( ! empty( $settings['place_order_btn_txt'] ) ) {
666 713 return $settings['place_order_btn_txt'];
667 714 }
@@ -721,14 +768,14 @@
721 768 }
722 769 ?>
723 770 <?php if ( array_key_exists( 'coupon_field_type', $settings ) && 'collapsible' === $settings['coupon_field_type'] ) : ?>
724 771 <span id="copoun_toggle" class="copoun_toggle sellkit-coupon-toggle sellkit-checkout-widget-links">
725 - <?php echo __( 'Have a coupon? Click here to enter your code', 'sellkit' ); ?>
772 + <?php echo esc_html__( 'Have a coupon? Click here to enter your code', 'sellkit' ); ?>
726 773 </span>
727 774 <?php $class .= ' sellkit-checkout-collapsible'; ?>
728 775 <?php Helper::instance()->editor_mode_extra_js(); ?>
729 776 <?php endif; ?>
730 - <div class="sellkit-custom-coupon-form <?php echo $class; ?>">
777 + <div class="sellkit-custom-coupon-form <?php echo esc_attr( $class ); ?>">
731 778 <p class="jx-form-row-first">
732 779 <input class="jx-coupon" type="text" placeholder="<?php esc_attr_e( 'Enter Promo code', 'sellkit' ); ?>" />
733 780 </p>
734 781
@@ -780,9 +827,9 @@
780 827 * @since 1.1.0
781 828 * return void
782 829 */
783 830 public static function bundle_product_action( $option ) {
784 - add_action( 'sellkit-checkout-widget-disable-quantity', [ Helper::instance(), 'checkout_order_hidden_quantity' ], 10, 2 );
831 + add_filter( 'sellkit-checkout-widget-disable-quantity', [ Helper::instance(), 'checkout_order_hidden_quantity' ], 10, 2 );
785 832
786 833 if ( 'force-products' === $option || Elementor::$instance->editor->is_edit_mode() ) {
787 834 return;
788 835 }
@@ -813,12 +860,25 @@
813 860 </thead>
814 861 <tbody>
815 862 <?php foreach ( $products as $cart_item_key => $cart_item ) : ?>
816 863 <?php
864 + if ( in_array( $cart_item_key, self::$in_cart, true ) ) {
865 + continue;
866 + }
867 +
817 868 $_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
818 869 $default = $_product->get_id();
819 870 $default_q = $cart_item['quantity'];
820 871 $unique_id = 'bundle-unique-id-' . $default;
872 + $checked = '';
873 +
874 + if ( 'checkbox' === $fields_type ) {
875 + $checked = 'checked';
876 + }
877 +
878 + if ( 'radio' === $fields_type && array_key_last( $products ) === $cart_item_key ) {
879 + $checked = 'checked';
880 + }
821 881 ?>
822 882 <tr class="sellkit-checkout-bundled-products-item">
823 883 <td class="sellkit-checkout-bundled-title">
824 884 <input
@@ -826,12 +886,12 @@
826 886 value="<?php echo esc_attr( $_product->get_id() ); ?>"
827 887 name="sellkit-checkout-bundle-item"
828 888 class="sellkit-checkout-bundle-item"
829 889 id="<?php echo esc_attr( $unique_id ); ?>"
830 - <?php echo ( array_key_last( $products ) === $cart_item_key ) ? 'checked' : ''; ?>
890 + <?php echo esc_html( $checked ); ?>
831 891 >
832 892 <label for="<?php echo esc_attr( $unique_id ); ?>">
833 - <?php echo $_product->get_name(); ?>
893 + <?php echo esc_html( $_product->get_name() ); ?>
834 894 </label>
835 895 </td>
836 896 <td class="sellkit-checkout-bundled-quantity">
837 897 <input type="number" <?php echo esc_attr( $readonly ); ?> min="1" value="<?php echo esc_attr( $cart_item['quantity'] ); ?>" data-id="<?php echo esc_attr( $cart_item_key ); ?>" class="sellkit-checkout-single-bundle-item-quantity" >
@@ -836,9 +896,9 @@
836 896 <td class="sellkit-checkout-bundled-quantity">
837 897 <input type="number" <?php echo esc_attr( $readonly ); ?> min="1" value="<?php echo esc_attr( $cart_item['quantity'] ); ?>" data-id="<?php echo esc_attr( $cart_item_key ); ?>" class="sellkit-checkout-single-bundle-item-quantity" >
838 898 </td>
839 899 <td class="sellkit-checkout-bundled-price">
840 - <?php echo apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key ); ?>
900 + <?php echo wp_kses_post( apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key ) ); ?>
841 901 </td>
842 902 <tr>
843 903 <?php if ( array_key_last( $products ) !== $cart_item_key ) : ?>
844 904 <tr>
@@ -855,24 +915,71 @@
855 915 <?php
856 916 $bundle_html = ob_get_clean();
857 917
858 918 add_action( 'sellkit-bundled-products-position', function() use ( $bundle_html ) {
859 - echo $bundle_html;
919 + $allowed_html = [
920 + 'section' => [
921 + 'class' => true,
922 + ],
923 + 'div' => [
924 + 'class' => true,
925 + ],
926 + 'span' => [
927 + 'class' => true,
928 + ],
929 + 'table' => [
930 + 'class' => true,
931 + ],
932 + 'thead' => [
933 + 'class' => true,
934 + ],
935 + 'tr' => [
936 + 'class' => true,
937 + ],
938 + 'th' => [
939 + 'class' => true,
940 + ],
941 + 'tbody' => [
942 + 'class' => true,
943 + ],
944 + 'td' => [
945 + 'class' => true,
946 + 'colspan' => true,
947 + ],
948 + 'input' => [
949 + 'type' => true,
950 + 'value' => true,
951 + 'name' => true,
952 + 'class' => true,
953 + 'id' => true,
954 + 'checked' => true,
955 + 'readonly' => true,
956 + 'min' => true,
957 + 'data-id' => true,
958 + ],
959 + 'label' => [
960 + 'for' => true,
961 + ],
962 + 'hr' => [],
963 + ];
964 +
965 + echo wp_kses( $bundle_html, $allowed_html );
860 966 } );
861 967
862 - if ( ! wp_doing_ajax() ) {
968 + if ( wp_doing_ajax() ) {
969 + return;
970 + }
971 +
972 + if ( 'radio' === $fields_type && null !== $default ) {
863 973 WC()->cart->empty_cart();
974 + WC()->cart->add_to_cart( $default, $default_q );
975 + }
864 976
865 - if ( null !== $default ) {
866 - WC()->cart->add_to_cart( $default, $default_q );
977 + if ( ! WC()->cart->needs_shipping() ) {
978 + wp_add_inline_script( 'sellkit-initialize-widgets', 'var sellkitCheckoutShipping = true', 'before' );
979 + }
867 980
868 - if ( ! WC()->cart->needs_shipping() ) {
869 - wp_add_inline_script( 'sellkit-initialize-widgets', 'var sellkitCheckoutShipping = true', 'before' );
870 - }
871 - }
872 -
873 - Global_Hooks::make_changes_after_cart_item_edit( get_the_id() );
874 - }
981 + Global_Hooks::make_changes_after_cart_item_edit( get_the_id() );
875 982 }
876 983
877 984 /**
878 985 * Trigger to activate order bumb or not for this checkout.
@@ -894,8 +1001,12 @@
894 1001 * @since 1.1.0
895 1002 * @return void
896 1003 */
897 1004 private static function order_bump_frontend_manager() {
1005 + if ( self::$is_bumps_applied ) {
1006 + return;
1007 + }
1008 +
898 1009 global $wp_query;
899 1010 $query = $wp_query->query_vars;
900 1011
901 1012 if ( ! array_key_exists( 'bump_data', $query ) ) {
@@ -915,8 +1026,10 @@
915 1026 add_action( $design['sellkit_funnels_bump_position'], function() use ( $design, $products ) {
916 1027 self::bump_html( $design, $products );
917 1028 }, 5 );
918 1029 }
1030 +
1031 + self::$is_bumps_applied = true;
919 1032 }
920 1033
921 1034 /**
922 1035 * Order bump html.
@@ -926,9 +1039,9 @@
926 1039 * @since 1.1.0
927 1040 * @return void
928 1041 */
929 1042 public static function bump_html( $design, $products ) {
930 - $list = $products['list'];
1043 + $list = empty( $products['list'] ) ? [] : $products['list'];
931 1044 $ids = [];
932 1045
933 1046 foreach ( $list as $id => $details ) {
934 1047 $ids[] = $id;
@@ -940,9 +1053,9 @@
940 1053 $ids_string = implode( '|', $ids );
941 1054 $product = wc_get_product( $ids_string );
942 1055 $qty = ( empty( $qty ) ) ? 1 : $qty;
943 1056
944 - if ( empty( $product ) || ! $product->get_id() ) {
1057 + if ( empty( $product ) || ! $product->get_id() || ! $product->is_in_stock() ) {
945 1058 return;
946 1059 }
947 1060
948 1061 $unique_id = 'bump-title-' . $ids_string;
@@ -953,8 +1066,10 @@
953 1066 'sellkit-checkout-after-order-summary' === current_action()
954 1067 ) {
955 1068 $class = 'sellkit-bump-review-order';
956 1069 }
1070 +
1071 + $checked = empty( WC()->cart->find_product_in_cart( WC()->cart->generate_cart_id( $product->get_id() ) ) ) ? false : true;
957 1072 ?>
958 1073 <div class="sellkit-checkout-step-bump-wrapper <?php echo esc_attr( $class ); ?>" >
959 1074 <div class="sellkit-checkout-bump-order-header">
960 1075 <div class="sellkit-bump-order-left-header">
@@ -965,8 +1080,9 @@
965 1080 class="sellkit-checkout-bump-order-products"
966 1081 data-qty="<?php echo esc_attr( $qty ); ?>"
967 1082 name="sellkit_bump_data_<?php echo esc_attr( $ids_string ); ?>"
968 1083 id="<?php echo esc_html( $unique_id ); ?>"
1084 + <?php echo ( true === $checked ) ? 'checked="true"' : ''; ?>
969 1085 >
970 1086 <label
971 1087 for="<?php echo esc_attr( $unique_id ); ?>"
972 1088 class="sellkit-checkout-order-bump-title"
@@ -987,18 +1103,18 @@
987 1103 <del aria-hidden="true">
988 1104 <span class="woocommerce-Price-amount amount">
989 1105 <bdi>
990 1106 <span class="woocommerce-Price-currencySymbol">
991 - <?php echo wc_price( $main_price ); ?>
1107 + <?php echo wp_kses_post( wc_price( $main_price ) ); ?>
992 1108 </span>
993 1109 </bdi>
994 1110 </span>
995 1111 </del>
996 - <bdi class="bump-price-bolded"><?php echo wc_price( $discounted_price ); ?></bdi>
1112 + <bdi class="bump-price-bolded"><?php echo wp_kses_post( wc_price( $discounted_price ) ); ?></bdi>
997 1113 <?php
998 1114 } else {
999 1115 ?>
1000 - <bdi><?php echo wc_price( $main_price ); ?></bdi>
1116 + <bdi><?php echo wp_kses_post( wc_price( $main_price ) ); ?></bdi>
1001 1117 <?php
1002 1118 }
1003 1119 ?>
1004 1120 </span>
@@ -1007,17 +1123,181 @@
1007 1123 <div class="sellkit-checkout-bump-order-body" >
1008 1124 <div class="sellkit-bump-order-left-body">
1009 1125 <?php $image = wp_get_attachment_image_src( $product->get_image_id() ); ?>
1010 1126 <?php if ( 'true' === $design['sellkit_funnels_bump_product_image'] && ! empty( $image[0] ) ) : ?>
1011 - <img src="<?php echo esc_attr( $image[0] ); ?>" >
1127 + <img src="<?php echo esc_url( $image[0] ); ?>" >
1012 1128 <?php endif; ?>
1013 1129 </div>
1014 1130 <div class="sellkit-bump-order-right-body">
1015 1131 <div class="sellkit-bump-order-description">
1016 - <?php echo $design['sellkit_content']; ?>
1132 + <?php echo wp_kses_post( $design['sellkit_content'] ); ?>
1017 1133 </div>
1018 1134 </div>
1019 1135 </div>
1020 1136 </div>
1021 1137 <?php
1138 + }
1139 +
1140 + /**
1141 + * Checks if funnel includes upsell step.
1142 + *
1143 + * @param string $goal customize return value.
1144 + * @param int $ajax_id upsell id through ajax.
1145 + * @since 1.6.2
1146 + */
1147 + public static function is_funnel_includes_upsell( $goal = 'is_upsell', $ajax_id = null ) {
1148 + $id = get_queried_object_id();
1149 +
1150 + if ( wp_doing_ajax() ) {
1151 + $id = $ajax_id;
1152 + }
1153 +
1154 + $step_data = get_post_meta( $id, 'step_data', true );
1155 + $include_upsell = false;
1156 + $upsell_steps = [];
1157 + $upsell_ids = [];
1158 + $global_checkout_id = get_option( Checkout::SELLKIT_GLOBAL_CHECKOUT_OPTION, 0 );
1159 +
1160 + // We are in default WooCommerce checkout page.
1161 + if ( empty( $step_data ) && $global_checkout_id > 0 && 'publish' === get_post_status( $global_checkout_id ) ) {
1162 + $steps = get_post_meta( $global_checkout_id, 'nodes', true );
1163 + $checkout_id = 0;
1164 +
1165 + foreach ( $steps as $step ) {
1166 + $step['type'] = (array) $step['type'];
1167 +
1168 + if ( 'checkout' === $step['type']['key'] ) {
1169 + $checkout_id = $step['page_id'];
1170 + }
1171 + }
1172 +
1173 + $step_data = get_post_meta( $checkout_id, 'step_data', true );
1174 + }
1175 +
1176 + if ( empty( $step_data ) ) {
1177 + return $include_upsell;
1178 + }
1179 +
1180 + $funnel_id = intval( $step_data['funnel_id'] );
1181 + $funnel_data = get_post_meta( $funnel_id, 'nodes', true );
1182 +
1183 + if ( empty( $funnel_data ) ) {
1184 + return $include_upsell;
1185 + }
1186 +
1187 + $popups = [ 'downsell', 'upsell' ];
1188 +
1189 + foreach ( $funnel_data as $step ) {
1190 + if ( isset( $step['data'] ) && isset( $step['data']['products'] ) && isset( $step['data']['products']['list'] ) ) {
1191 + $product_id = array_keys( $step['data']['products']['list'] )[0] ?? 0;
1192 +
1193 + if ( $product_id ) {
1194 + $product = wc_get_product( $product_id );
1195 +
1196 + if ( $product && ! $product->is_in_stock() ) {
1197 + return $include_upsell;
1198 + }
1199 + }
1200 + }
1201 +
1202 + $step['type'] = (array) $step['type'];
1203 +
1204 + if ( in_array( $step['type']['key'], $popups, true ) ) {
1205 + $include_upsell = true;
1206 + $upsell_steps[] = $step;
1207 + $upsell_ids[] = $step['page_id'];
1208 + }
1209 + }
1210 +
1211 + if ( 'get_ids' === $goal ) {
1212 + return $upsell_ids;
1213 + }
1214 +
1215 + // Send data to the filter that keeps steps data to prepare popup.
1216 + add_filter( 'sellkit_upsell_steps_popup_information', function( $default ) use ( $upsell_steps ) {
1217 + if ( ! empty( $upsell_steps ) ) {
1218 + return $upsell_steps;
1219 + }
1220 +
1221 + return $default;
1222 + } );
1223 +
1224 + return $include_upsell;
1225 + }
1226 +
1227 + /**
1228 + * Add an extra hidden field to checkout form if funnel includes upsell step.
1229 + *
1230 + * @since 1.6.2
1231 + */
1232 + public function add_trigger_field_for_upsell_steps() {
1233 + $include_upsell = self::is_funnel_includes_upsell();
1234 +
1235 + if ( false === $include_upsell ) {
1236 + return;
1237 + }
1238 +
1239 + echo '<input type="hidden" id="sellkit_funnel_has_upsell" value="upsell" >';
1240 + echo '<input type="hidden" id="sellkit_funnel_popup_step_id" value="0" >';
1241 + }
1242 +
1243 + /**
1244 + * Display sellkit upsell steps as popup.
1245 + *
1246 + * @since 1.6.2
1247 + */
1248 + public function sellkit_funnel_display_upsell_as_popup() {
1249 + $upsell_data = apply_filters( 'sellkit_upsell_steps_popup_information', [] );
1250 + $i = 1;
1251 +
1252 + if ( empty( $upsell_data ) ) {
1253 + return;
1254 + }
1255 +
1256 + foreach ( $upsell_data as $data ) {
1257 + $id = 'sellkit_funnel_upsell_popup_' . $i;
1258 + $class = 'sellkit_funnel_upsell_popup sellkit_funnel_upsell_popup_' . apply_filters( 'wpml_object_id', $data['page_id'], 'sellkit_step', true ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API.
1259 + ?>
1260 + <div class="<?php echo esc_attr( $class ); ?>" id="<?php echo esc_attr( $id ); ?>">
1261 + <?php echo wp_kses_post( Elementor::instance()->frontend->get_builder_content_for_display( apply_filters( 'wpml_object_id', $data['page_id'], 'sellkit_step', true ) ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API. ?>
1262 + <input type="hidden" class="identify" value="<?php echo esc_attr( apply_filters( 'wpml_object_id', $data['page_id'], 'sellkit_step', true ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API. ?>" >
1263 + </div>
1264 + <?php
1265 + $i++;
1266 + }
1267 + }
1268 +
1269 + /**
1270 + * Display checkout order notes field.
1271 + *
1272 + * @since 1.8.9
1273 + */
1274 + public function order_notes() {
1275 + // Get woocommerce order notes field.
1276 + $notes = WC()->checkout()->get_checkout_fields( 'order' );
1277 +
1278 + // print notes field.
1279 + foreach ( $notes as $key => $field ) {
1280 + ?>
1281 + <div class="sellkit-checkout-order-fields sellkit-widget-checkout-fields">
1282 + <?php
1283 + if ( 'order_comments' === $key ) {
1284 + ?>
1285 + <div class="sellkit-checkout-order-notes">
1286 + <div class="sellkit-order-note-field-wrapper">
1287 + <input id="sellkit-add-notes-to-order-box" type="checkbox">
1288 + <label for="sellkit-add-notes-to-order-box">
1289 + <?php echo esc_html__( 'Add a note to your order', 'sellkit' ); ?>
1290 + </label>
1291 + </div>
1292 + <?php
1293 + woocommerce_form_field( $key, $field, WC()->checkout()->get_value( $key ) );
1294 + ?>
1295 + </div>
1296 + <?php
1297 + }
1298 + ?>
1299 + </div>
1300 + <?php
1301 + }
1022 1302 }
1023 1303 }