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 +208 -37 1.6.82.7.0 View file →
@@ -6,8 +6,9 @@
6 6
7 7 use Sellkit\Elementor\Modules\Checkout\Classes\{ Helper, Global_Hooks };
8 8 use Elementor\Plugin as Elementor;
9 9 use Sellkit_Funnel;
10 +use Sellkit\Global_Checkout\Checkout;
10 11
11 12 /**
12 13 * Local hooks.
13 14 * Applies before widget.
@@ -20,8 +21,39 @@
20 21 * @since 1.1.0
21 22 */
22 23 class Local_Hooks {
23 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 + /**
24 56 * Create instance of class without construct.
25 57 *
26 58 * @since 1.1.0
27 59 * @return object
@@ -107,8 +139,11 @@
107 139 add_action( 'sellkit_checkout_required_hidden_fields', [ $this, 'add_trigger_field_for_upsell_steps' ] );
108 140
109 141 // Add upsell templates at the end of page.
110 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' ] );
111 146 }
112 147
113 148 /**
114 149 * Opens a wrapper around widget checkout form.
@@ -311,9 +346,9 @@
311 346 $class = '\Sellkit\Elementor\Modules\Checkout\Fields\\' . ucfirst( $class );
312 347 $class = new $class();
313 348 $field = '';
314 349
315 - $class->final_html_structure( $field, $details, $key );
350 + $class->final_html_structure( $field, $details, $key, $checkout->get_value( $key ) );
316 351 }
317 352 }
318 353
319 354 /**
@@ -325,12 +360,13 @@
325 360 */
326 361 public function customize_billing_field( $default_fields ) {
327 362 $widget_billing_fields = $this->settings['billing_list'];
328 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() );
329 365
330 366 // Unset default fields.
331 367 foreach ( $default_fields as $key => $field ) {
332 - 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 ) {
333 369 unset( $default_fields[ $key ] );
334 370 }
335 371 }
336 372
@@ -399,9 +435,9 @@
399 435 $class = '\Sellkit\Elementor\Modules\Checkout\Fields\\' . ucfirst( $class );
400 436 $class = new $class();
401 437 $field = '';
402 438
403 - $field = $class->final_html_structure( $field, $details, $key );
439 + $field = $class->final_html_structure( $field, $details, $key, $checkout->get_value( $key ) );
404 440 }
405 441 }
406 442
407 443 /**
@@ -492,9 +528,9 @@
492 528 ?>
493 529 <section class="sellkit-checkout-widget-express-checkout sellkit-checkout-express-checkout-step-1">
494 530 <fieldset class="express-box sellkit-checkout-widget-divider">
495 531 <legend class="sellkit-express-checkout-legend heading">
496 - <?php echo __( 'Express Checkout', 'sellkit' ); ?>
532 + <?php echo esc_html__( 'Express Checkout', 'sellkit' ); ?>
497 533 </legend>
498 534 <div class="express-methods">
499 535 <?php do_action( 'sellkit-checkout-widget-express-methods' ); ?>
500 536 </div>
@@ -501,15 +537,15 @@
501 537 </fieldset>
502 538 </section>
503 539 <section class="sellkit-checkout-widget-express-checkout sellkit-checkout-express-checkout-step-2">
504 540 <fieldset id="sellkit-checkout-or-divider" class="divider-box sellkit-checkout-widget-divider">
505 - <legend class="heading"><?php echo __( 'OR', 'sellkit' ); ?></legend>
541 + <legend class="heading"><?php echo esc_html__( 'OR', 'sellkit' ); ?></legend>
506 542 </fieldset>
507 543 </section>
508 544 <?php
509 545 $express = ob_get_clean();
510 546 $express = apply_filters( 'sellkit-checkout-widget-express-checkout', $express );
511 - echo $express;
547 + echo wp_kses_post( $express );
512 548 }
513 549
514 550 /**
515 551 * Apply custom Messages.
@@ -529,9 +565,9 @@
529 565 add_action( 'sellkit_core/widgets/checkout/custom_message/create_website_account', function() {
530 566 $site = get_bloginfo( 'name' );
531 567 $text = $this->settings['create_website_account'];
532 568
533 - echo str_replace( '{{website}}', $site, $text );
569 + echo wp_kses_post( str_replace( '{{website}}', $site, $text ) );
534 570 } );
535 571
536 572 add_filter( 'sellkit_core/widgets/checkout/custom_message/secure_transaction_text', function() {
537 573 return $this->settings['secure_transaction_text'];
@@ -732,14 +768,14 @@
732 768 }
733 769 ?>
734 770 <?php if ( array_key_exists( 'coupon_field_type', $settings ) && 'collapsible' === $settings['coupon_field_type'] ) : ?>
735 771 <span id="copoun_toggle" class="copoun_toggle sellkit-coupon-toggle sellkit-checkout-widget-links">
736 - <?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' ); ?>
737 773 </span>
738 774 <?php $class .= ' sellkit-checkout-collapsible'; ?>
739 775 <?php Helper::instance()->editor_mode_extra_js(); ?>
740 776 <?php endif; ?>
741 - <div class="sellkit-custom-coupon-form <?php echo $class; ?>">
777 + <div class="sellkit-custom-coupon-form <?php echo esc_attr( $class ); ?>">
742 778 <p class="jx-form-row-first">
743 779 <input class="jx-coupon" type="text" placeholder="<?php esc_attr_e( 'Enter Promo code', 'sellkit' ); ?>" />
744 780 </p>
745 781
@@ -824,12 +860,25 @@
824 860 </thead>
825 861 <tbody>
826 862 <?php foreach ( $products as $cart_item_key => $cart_item ) : ?>
827 863 <?php
864 + if ( in_array( $cart_item_key, self::$in_cart, true ) ) {
865 + continue;
866 + }
867 +
828 868 $_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
829 869 $default = $_product->get_id();
830 870 $default_q = $cart_item['quantity'];
831 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 + }
832 881 ?>
833 882 <tr class="sellkit-checkout-bundled-products-item">
834 883 <td class="sellkit-checkout-bundled-title">
835 884 <input
@@ -837,12 +886,12 @@
837 886 value="<?php echo esc_attr( $_product->get_id() ); ?>"
838 887 name="sellkit-checkout-bundle-item"
839 888 class="sellkit-checkout-bundle-item"
840 889 id="<?php echo esc_attr( $unique_id ); ?>"
841 - <?php echo ( array_key_last( $products ) === $cart_item_key ) ? 'checked' : ''; ?>
890 + <?php echo esc_html( $checked ); ?>
842 891 >
843 892 <label for="<?php echo esc_attr( $unique_id ); ?>">
844 - <?php echo $_product->get_name(); ?>
893 + <?php echo esc_html( $_product->get_name() ); ?>
845 894 </label>
846 895 </td>
847 896 <td class="sellkit-checkout-bundled-quantity">
848 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" >
@@ -847,9 +896,9 @@
847 896 <td class="sellkit-checkout-bundled-quantity">
848 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" >
849 898 </td>
850 899 <td class="sellkit-checkout-bundled-price">
851 - <?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 ) ); ?>
852 901 </td>
853 902 <tr>
854 903 <?php if ( array_key_last( $products ) !== $cart_item_key ) : ?>
855 904 <tr>
@@ -866,24 +915,71 @@
866 915 <?php
867 916 $bundle_html = ob_get_clean();
868 917
869 918 add_action( 'sellkit-bundled-products-position', function() use ( $bundle_html ) {
870 - 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 );
871 966 } );
872 967
873 - if ( ! wp_doing_ajax() ) {
968 + if ( wp_doing_ajax() ) {
969 + return;
970 + }
971 +
972 + if ( 'radio' === $fields_type && null !== $default ) {
874 973 WC()->cart->empty_cart();
974 + WC()->cart->add_to_cart( $default, $default_q );
975 + }
875 976
876 - if ( null !== $default ) {
877 - 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 + }
878 980
879 - if ( ! WC()->cart->needs_shipping() ) {
880 - wp_add_inline_script( 'sellkit-initialize-widgets', 'var sellkitCheckoutShipping = true', 'before' );
881 - }
882 - }
883 -
884 - Global_Hooks::make_changes_after_cart_item_edit( get_the_id() );
885 - }
981 + Global_Hooks::make_changes_after_cart_item_edit( get_the_id() );
886 982 }
887 983
888 984 /**
889 985 * Trigger to activate order bumb or not for this checkout.
@@ -905,8 +1001,12 @@
905 1001 * @since 1.1.0
906 1002 * @return void
907 1003 */
908 1004 private static function order_bump_frontend_manager() {
1005 + if ( self::$is_bumps_applied ) {
1006 + return;
1007 + }
1008 +
909 1009 global $wp_query;
910 1010 $query = $wp_query->query_vars;
911 1011
912 1012 if ( ! array_key_exists( 'bump_data', $query ) ) {
@@ -926,8 +1026,10 @@
926 1026 add_action( $design['sellkit_funnels_bump_position'], function() use ( $design, $products ) {
927 1027 self::bump_html( $design, $products );
928 1028 }, 5 );
929 1029 }
1030 +
1031 + self::$is_bumps_applied = true;
930 1032 }
931 1033
932 1034 /**
933 1035 * Order bump html.
@@ -937,9 +1039,9 @@
937 1039 * @since 1.1.0
938 1040 * @return void
939 1041 */
940 1042 public static function bump_html( $design, $products ) {
941 - $list = $products['list'];
1043 + $list = empty( $products['list'] ) ? [] : $products['list'];
942 1044 $ids = [];
943 1045
944 1046 foreach ( $list as $id => $details ) {
945 1047 $ids[] = $id;
@@ -951,9 +1053,9 @@
951 1053 $ids_string = implode( '|', $ids );
952 1054 $product = wc_get_product( $ids_string );
953 1055 $qty = ( empty( $qty ) ) ? 1 : $qty;
954 1056
955 - if ( empty( $product ) || ! $product->get_id() ) {
1057 + if ( empty( $product ) || ! $product->get_id() || ! $product->is_in_stock() ) {
956 1058 return;
957 1059 }
958 1060
959 1061 $unique_id = 'bump-title-' . $ids_string;
@@ -964,8 +1066,10 @@
964 1066 'sellkit-checkout-after-order-summary' === current_action()
965 1067 ) {
966 1068 $class = 'sellkit-bump-review-order';
967 1069 }
1070 +
1071 + $checked = empty( WC()->cart->find_product_in_cart( WC()->cart->generate_cart_id( $product->get_id() ) ) ) ? false : true;
968 1072 ?>
969 1073 <div class="sellkit-checkout-step-bump-wrapper <?php echo esc_attr( $class ); ?>" >
970 1074 <div class="sellkit-checkout-bump-order-header">
971 1075 <div class="sellkit-bump-order-left-header">
@@ -976,8 +1080,9 @@
976 1080 class="sellkit-checkout-bump-order-products"
977 1081 data-qty="<?php echo esc_attr( $qty ); ?>"
978 1082 name="sellkit_bump_data_<?php echo esc_attr( $ids_string ); ?>"
979 1083 id="<?php echo esc_html( $unique_id ); ?>"
1084 + <?php echo ( true === $checked ) ? 'checked="true"' : ''; ?>
980 1085 >
981 1086 <label
982 1087 for="<?php echo esc_attr( $unique_id ); ?>"
983 1088 class="sellkit-checkout-order-bump-title"
@@ -998,18 +1103,18 @@
998 1103 <del aria-hidden="true">
999 1104 <span class="woocommerce-Price-amount amount">
1000 1105 <bdi>
1001 1106 <span class="woocommerce-Price-currencySymbol">
1002 - <?php echo wc_price( $main_price ); ?>
1107 + <?php echo wp_kses_post( wc_price( $main_price ) ); ?>
1003 1108 </span>
1004 1109 </bdi>
1005 1110 </span>
1006 1111 </del>
1007 - <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>
1008 1113 <?php
1009 1114 } else {
1010 1115 ?>
1011 - <bdi><?php echo wc_price( $main_price ); ?></bdi>
1116 + <bdi><?php echo wp_kses_post( wc_price( $main_price ) ); ?></bdi>
1012 1117 <?php
1013 1118 }
1014 1119 ?>
1015 1120 </span>
@@ -1018,14 +1123,14 @@
1018 1123 <div class="sellkit-checkout-bump-order-body" >
1019 1124 <div class="sellkit-bump-order-left-body">
1020 1125 <?php $image = wp_get_attachment_image_src( $product->get_image_id() ); ?>
1021 1126 <?php if ( 'true' === $design['sellkit_funnels_bump_product_image'] && ! empty( $image[0] ) ) : ?>
1022 - <img src="<?php echo esc_attr( $image[0] ); ?>" >
1127 + <img src="<?php echo esc_url( $image[0] ); ?>" >
1023 1128 <?php endif; ?>
1024 1129 </div>
1025 1130 <div class="sellkit-bump-order-right-body">
1026 1131 <div class="sellkit-bump-order-description">
1027 - <?php echo $design['sellkit_content']; ?>
1132 + <?php echo wp_kses_post( $design['sellkit_content'] ); ?>
1028 1133 </div>
1029 1134 </div>
1030 1135 </div>
1031 1136 </div>
@@ -1045,13 +1150,30 @@
1045 1150 if ( wp_doing_ajax() ) {
1046 1151 $id = $ajax_id;
1047 1152 }
1048 1153
1049 - $step_data = get_post_meta( $id, 'step_data', true );
1050 - $include_upsell = false;
1051 - $upsell_steps = [];
1052 - $upsell_ids = [];
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 );
1053 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 +
1054 1176 if ( empty( $step_data ) ) {
1055 1177 return $include_upsell;
1056 1178 }
1057 1179
@@ -1064,8 +1186,22 @@
1064 1186
1065 1187 $popups = [ 'downsell', 'upsell' ];
1066 1188
1067 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 +
1068 1204 if ( in_array( $step['type']['key'], $popups, true ) ) {
1069 1205 $include_upsell = true;
1070 1206 $upsell_steps[] = $step;
1071 1207 $upsell_ids[] = $step['page_id'];
@@ -1118,15 +1254,50 @@
1118 1254 }
1119 1255
1120 1256 foreach ( $upsell_data as $data ) {
1121 1257 $id = 'sellkit_funnel_upsell_popup_' . $i;
1122 - $class = 'sellkit_funnel_upsell_popup sellkit_funnel_upsell_popup_' . $data['page_id'];
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.
1123 1259 ?>
1124 1260 <div class="<?php echo esc_attr( $class ); ?>" id="<?php echo esc_attr( $id ); ?>">
1125 - <?php echo Elementor::instance()->frontend->get_builder_content_for_display( $data['page_id'] ); ?>
1126 - <input type="hidden" class="identify" value="<?php echo esc_attr( $data['page_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. ?>" >
1127 1263 </div>
1128 1264 <?php
1129 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
1130 1301 }
1131 1302 }
1132 1303 }