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 +171 -51 1.7.92.7.0 View file →
@@ -21,10 +21,25 @@
21 21 * @since 1.1.0
22 22 */
23 23 class Local_Hooks {
24 24 /**
25 - * Array of added products to cart.
25 + * Checkout widget settings.
26 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 + *
27 42 * @since 1.7.9
28 43 * @var array
29 44 */
30 45 public static $in_cart = [];
@@ -29,8 +44,16 @@
29 44 */
30 45 public static $in_cart = [];
31 46
32 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 + /**
33 56 * Create instance of class without construct.
34 57 *
35 58 * @since 1.1.0
36 59 * @return object
@@ -116,8 +139,11 @@
116 139 add_action( 'sellkit_checkout_required_hidden_fields', [ $this, 'add_trigger_field_for_upsell_steps' ] );
117 140
118 141 // Add upsell templates at the end of page.
119 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' ] );
120 146 }
121 147
122 148 /**
123 149 * Opens a wrapper around widget checkout form.
@@ -320,9 +346,9 @@
320 346 $class = '\Sellkit\Elementor\Modules\Checkout\Fields\\' . ucfirst( $class );
321 347 $class = new $class();
322 348 $field = '';
323 349
324 - $class->final_html_structure( $field, $details, $key );
350 + $class->final_html_structure( $field, $details, $key, $checkout->get_value( $key ) );
325 351 }
326 352 }
327 353
328 354 /**
@@ -334,12 +360,13 @@
334 360 */
335 361 public function customize_billing_field( $default_fields ) {
336 362 $widget_billing_fields = $this->settings['billing_list'];
337 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() );
338 365
339 366 // Unset default fields.
340 367 foreach ( $default_fields as $key => $field ) {
341 - 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 ) {
342 369 unset( $default_fields[ $key ] );
343 370 }
344 371 }
345 372
@@ -408,9 +435,9 @@
408 435 $class = '\Sellkit\Elementor\Modules\Checkout\Fields\\' . ucfirst( $class );
409 436 $class = new $class();
410 437 $field = '';
411 438
412 - $field = $class->final_html_structure( $field, $details, $key );
439 + $field = $class->final_html_structure( $field, $details, $key, $checkout->get_value( $key ) );
413 440 }
414 441 }
415 442
416 443 /**
@@ -501,9 +528,9 @@
501 528 ?>
502 529 <section class="sellkit-checkout-widget-express-checkout sellkit-checkout-express-checkout-step-1">
503 530 <fieldset class="express-box sellkit-checkout-widget-divider">
504 531 <legend class="sellkit-express-checkout-legend heading">
505 - <?php echo __( 'Express Checkout', 'sellkit' ); ?>
532 + <?php echo esc_html__( 'Express Checkout', 'sellkit' ); ?>
506 533 </legend>
507 534 <div class="express-methods">
508 535 <?php do_action( 'sellkit-checkout-widget-express-methods' ); ?>
509 536 </div>
@@ -510,15 +537,15 @@
510 537 </fieldset>
511 538 </section>
512 539 <section class="sellkit-checkout-widget-express-checkout sellkit-checkout-express-checkout-step-2">
513 540 <fieldset id="sellkit-checkout-or-divider" class="divider-box sellkit-checkout-widget-divider">
514 - <legend class="heading"><?php echo __( 'OR', 'sellkit' ); ?></legend>
541 + <legend class="heading"><?php echo esc_html__( 'OR', 'sellkit' ); ?></legend>
515 542 </fieldset>
516 543 </section>
517 544 <?php
518 545 $express = ob_get_clean();
519 546 $express = apply_filters( 'sellkit-checkout-widget-express-checkout', $express );
520 - echo $express;
547 + echo wp_kses_post( $express );
521 548 }
522 549
523 550 /**
524 551 * Apply custom Messages.
@@ -538,9 +565,9 @@
538 565 add_action( 'sellkit_core/widgets/checkout/custom_message/create_website_account', function() {
539 566 $site = get_bloginfo( 'name' );
540 567 $text = $this->settings['create_website_account'];
541 568
542 - echo str_replace( '{{website}}', $site, $text );
569 + echo wp_kses_post( str_replace( '{{website}}', $site, $text ) );
543 570 } );
544 571
545 572 add_filter( 'sellkit_core/widgets/checkout/custom_message/secure_transaction_text', function() {
546 573 return $this->settings['secure_transaction_text'];
@@ -741,14 +768,14 @@
741 768 }
742 769 ?>
743 770 <?php if ( array_key_exists( 'coupon_field_type', $settings ) && 'collapsible' === $settings['coupon_field_type'] ) : ?>
744 771 <span id="copoun_toggle" class="copoun_toggle sellkit-coupon-toggle sellkit-checkout-widget-links">
745 - <?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' ); ?>
746 773 </span>
747 774 <?php $class .= ' sellkit-checkout-collapsible'; ?>
748 775 <?php Helper::instance()->editor_mode_extra_js(); ?>
749 776 <?php endif; ?>
750 - <div class="sellkit-custom-coupon-form <?php echo $class; ?>">
777 + <div class="sellkit-custom-coupon-form <?php echo esc_attr( $class ); ?>">
751 778 <p class="jx-form-row-first">
752 779 <input class="jx-coupon" type="text" placeholder="<?php esc_attr_e( 'Enter Promo code', 'sellkit' ); ?>" />
753 780 </p>
754 781
@@ -841,10 +868,17 @@
841 868 $_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
842 869 $default = $_product->get_id();
843 870 $default_q = $cart_item['quantity'];
844 871 $unique_id = 'bundle-unique-id-' . $default;
872 + $checked = '';
845 873
846 - self::$in_cart[ array_key_last( $products ) ] = $cart_item_key;
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 + }
847 881 ?>
848 882 <tr class="sellkit-checkout-bundled-products-item">
849 883 <td class="sellkit-checkout-bundled-title">
850 884 <input
@@ -852,12 +886,12 @@
852 886 value="<?php echo esc_attr( $_product->get_id() ); ?>"
853 887 name="sellkit-checkout-bundle-item"
854 888 class="sellkit-checkout-bundle-item"
855 889 id="<?php echo esc_attr( $unique_id ); ?>"
856 - <?php echo ( array_key_last( $products ) === $cart_item_key ) ? 'checked' : ''; ?>
890 + <?php echo esc_html( $checked ); ?>
857 891 >
858 892 <label for="<?php echo esc_attr( $unique_id ); ?>">
859 - <?php echo $_product->get_name(); ?>
893 + <?php echo esc_html( $_product->get_name() ); ?>
860 894 </label>
861 895 </td>
862 896 <td class="sellkit-checkout-bundled-quantity">
863 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" >
@@ -862,9 +896,9 @@
862 896 <td class="sellkit-checkout-bundled-quantity">
863 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" >
864 898 </td>
865 899 <td class="sellkit-checkout-bundled-price">
866 - <?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 ) ); ?>
867 901 </td>
868 902 <tr>
869 903 <?php if ( array_key_last( $products ) !== $cart_item_key ) : ?>
870 904 <tr>
@@ -881,41 +915,71 @@
881 915 <?php
882 916 $bundle_html = ob_get_clean();
883 917
884 918 add_action( 'sellkit-bundled-products-position', function() use ( $bundle_html ) {
885 - 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 );
886 966 } );
887 967
888 - global $wp_query;
968 + if ( wp_doing_ajax() ) {
969 + return;
970 + }
889 971
890 - $query = $wp_query->query_vars;
891 - $reset_cart = 'true';
972 + if ( 'radio' === $fields_type && null !== $default ) {
973 + WC()->cart->empty_cart();
974 + WC()->cart->add_to_cart( $default, $default_q );
975 + }
892 976
893 - if ( isset( $query['funnel_reset_cart'] ) && array_key_exists( 'funnel_reset_cart', $query ) ) {
894 - $reset_cart = $query['funnel_reset_cart'];
977 + if ( ! WC()->cart->needs_shipping() ) {
978 + wp_add_inline_script( 'sellkit-initialize-widgets', 'var sellkitCheckoutShipping = true', 'before' );
895 979 }
896 980
897 - if ( ! wp_doing_ajax() ) {
898 - if ( 'true' === $reset_cart ) {
899 - WC()->cart->empty_cart();
900 - }
901 -
902 - if ( null !== $default ) {
903 - if ( ! array_key_exists( $default, self::$in_cart ) && 'true' !== $reset_cart ) {
904 - WC()->cart->add_to_cart( $default, $default_q );
905 - }
906 -
907 - if ( 'true' === $reset_cart ) {
908 - WC()->cart->add_to_cart( $default, $default_q );
909 - }
910 -
911 - if ( ! WC()->cart->needs_shipping() ) {
912 - wp_add_inline_script( 'sellkit-initialize-widgets', 'var sellkitCheckoutShipping = true', 'before' );
913 - }
914 - }
915 -
916 - Global_Hooks::make_changes_after_cart_item_edit( get_the_id() );
917 - }
981 + Global_Hooks::make_changes_after_cart_item_edit( get_the_id() );
918 982 }
919 983
920 984 /**
921 985 * Trigger to activate order bumb or not for this checkout.
@@ -937,8 +1001,12 @@
937 1001 * @since 1.1.0
938 1002 * @return void
939 1003 */
940 1004 private static function order_bump_frontend_manager() {
1005 + if ( self::$is_bumps_applied ) {
1006 + return;
1007 + }
1008 +
941 1009 global $wp_query;
942 1010 $query = $wp_query->query_vars;
943 1011
944 1012 if ( ! array_key_exists( 'bump_data', $query ) ) {
@@ -958,8 +1026,10 @@
958 1026 add_action( $design['sellkit_funnels_bump_position'], function() use ( $design, $products ) {
959 1027 self::bump_html( $design, $products );
960 1028 }, 5 );
961 1029 }
1030 +
1031 + self::$is_bumps_applied = true;
962 1032 }
963 1033
964 1034 /**
965 1035 * Order bump html.
@@ -969,9 +1039,9 @@
969 1039 * @since 1.1.0
970 1040 * @return void
971 1041 */
972 1042 public static function bump_html( $design, $products ) {
973 - $list = $products['list'];
1043 + $list = empty( $products['list'] ) ? [] : $products['list'];
974 1044 $ids = [];
975 1045
976 1046 foreach ( $list as $id => $details ) {
977 1047 $ids[] = $id;
@@ -983,9 +1053,9 @@
983 1053 $ids_string = implode( '|', $ids );
984 1054 $product = wc_get_product( $ids_string );
985 1055 $qty = ( empty( $qty ) ) ? 1 : $qty;
986 1056
987 - if ( empty( $product ) || ! $product->get_id() ) {
1057 + if ( empty( $product ) || ! $product->get_id() || ! $product->is_in_stock() ) {
988 1058 return;
989 1059 }
990 1060
991 1061 $unique_id = 'bump-title-' . $ids_string;
@@ -996,8 +1066,10 @@
996 1066 'sellkit-checkout-after-order-summary' === current_action()
997 1067 ) {
998 1068 $class = 'sellkit-bump-review-order';
999 1069 }
1070 +
1071 + $checked = empty( WC()->cart->find_product_in_cart( WC()->cart->generate_cart_id( $product->get_id() ) ) ) ? false : true;
1000 1072 ?>
1001 1073 <div class="sellkit-checkout-step-bump-wrapper <?php echo esc_attr( $class ); ?>" >
1002 1074 <div class="sellkit-checkout-bump-order-header">
1003 1075 <div class="sellkit-bump-order-left-header">
@@ -1008,8 +1080,9 @@
1008 1080 class="sellkit-checkout-bump-order-products"
1009 1081 data-qty="<?php echo esc_attr( $qty ); ?>"
1010 1082 name="sellkit_bump_data_<?php echo esc_attr( $ids_string ); ?>"
1011 1083 id="<?php echo esc_html( $unique_id ); ?>"
1084 + <?php echo ( true === $checked ) ? 'checked="true"' : ''; ?>
1012 1085 >
1013 1086 <label
1014 1087 for="<?php echo esc_attr( $unique_id ); ?>"
1015 1088 class="sellkit-checkout-order-bump-title"
@@ -1030,18 +1103,18 @@
1030 1103 <del aria-hidden="true">
1031 1104 <span class="woocommerce-Price-amount amount">
1032 1105 <bdi>
1033 1106 <span class="woocommerce-Price-currencySymbol">
1034 - <?php echo wc_price( $main_price ); ?>
1107 + <?php echo wp_kses_post( wc_price( $main_price ) ); ?>
1035 1108 </span>
1036 1109 </bdi>
1037 1110 </span>
1038 1111 </del>
1039 - <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>
1040 1113 <?php
1041 1114 } else {
1042 1115 ?>
1043 - <bdi><?php echo wc_price( $main_price ); ?></bdi>
1116 + <bdi><?php echo wp_kses_post( wc_price( $main_price ) ); ?></bdi>
1044 1117 <?php
1045 1118 }
1046 1119 ?>
1047 1120 </span>
@@ -1050,14 +1123,14 @@
1050 1123 <div class="sellkit-checkout-bump-order-body" >
1051 1124 <div class="sellkit-bump-order-left-body">
1052 1125 <?php $image = wp_get_attachment_image_src( $product->get_image_id() ); ?>
1053 1126 <?php if ( 'true' === $design['sellkit_funnels_bump_product_image'] && ! empty( $image[0] ) ) : ?>
1054 - <img src="<?php echo esc_attr( $image[0] ); ?>" >
1127 + <img src="<?php echo esc_url( $image[0] ); ?>" >
1055 1128 <?php endif; ?>
1056 1129 </div>
1057 1130 <div class="sellkit-bump-order-right-body">
1058 1131 <div class="sellkit-bump-order-description">
1059 - <?php echo $design['sellkit_content']; ?>
1132 + <?php echo wp_kses_post( $design['sellkit_content'] ); ?>
1060 1133 </div>
1061 1134 </div>
1062 1135 </div>
1063 1136 </div>
@@ -1113,8 +1186,20 @@
1113 1186
1114 1187 $popups = [ 'downsell', 'upsell' ];
1115 1188
1116 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 +
1117 1202 $step['type'] = (array) $step['type'];
1118 1203
1119 1204 if ( in_array( $step['type']['key'], $popups, true ) ) {
1120 1205 $include_upsell = true;
@@ -1169,15 +1254,50 @@
1169 1254 }
1170 1255
1171 1256 foreach ( $upsell_data as $data ) {
1172 1257 $id = 'sellkit_funnel_upsell_popup_' . $i;
1173 - $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.
1174 1259 ?>
1175 1260 <div class="<?php echo esc_attr( $class ); ?>" id="<?php echo esc_attr( $id ); ?>">
1176 - <?php echo Elementor::instance()->frontend->get_builder_content_for_display( $data['page_id'] ); ?>
1177 - <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. ?>" >
1178 1263 </div>
1179 1264 <?php
1180 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
1181 1301 }
1182 1302 }
1183 1303 }