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/global-hooks.php +294 -30 1.7.42.7.0 View file →
@@ -4,8 +4,10 @@
4 4
5 5 defined( 'ABSPATH' ) || exit;
6 6
7 7 use Sellkit\Elementor\Modules\Checkout\Classes\{ Local_Hooks, Helper };
8 +use Sellkit\Funnel\Analytics\Data_Updater;
9 +use Sellkit\Funnel\Contacts\Base_Contacts;
8 10 use Sellkit\Funnel\Steps\Checkout;
9 11 use Sellkit_Funnel;
10 12
11 13 /**
@@ -14,12 +16,27 @@
14 16 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
15 17 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
16 18 * @SuppressWarnings(PHPMD.TooManyMethods)
17 19 * @SuppressWarnings(PHPMD.NPathComplexity)
20 + * @SuppressWarnings(PHPMD.ExcessiveClassLength)
18 21 * @since 1.1.0
19 22 */
20 23 class Global_Hooks {
21 24 /**
25 + * Helper id during checkout process.
26 + *
27 + * @var int
28 + */
29 + private $helper_id = 0;
30 +
31 + /**
32 + * List of upsell product with price
33 + *
34 + * @var array
35 + */
36 + private static $sellkit_upsell_products;
37 +
38 + /**
22 39 * Create instance of class without construct.
23 40 *
24 41 * @since 1.1.0
25 42 * @return object
@@ -58,8 +75,12 @@
58 75
59 76 // Save user defined fields.
60 77 add_action( 'woocommerce_checkout_update_order_meta', [ $this, 'save_user_defined_fields' ] );
61 78
79 + // Display user defined fields in order edit page.
80 + add_action( 'woocommerce_admin_order_data_after_billing_address', [ $this, 'add_item_to_order_details' ], 10, 1 );
81 + add_action( 'woocommerce_admin_order_data_after_shipping_address', [ $this, 'add_item_to_order_details' ], 10, 1 );
82 +
62 83 // Add custom shipping field to email.
63 84 add_filter( 'woocommerce_order_get_formatted_shipping_address', [ $this, 'attach_user_shipping_fields_to_order_email' ], 10, 3 );
64 85
65 86 // Add custom billing field to email.
@@ -79,8 +100,20 @@
79 100 add_filter( 'sellkit-shipping-methods-choosen-method', [ $this, 'sellkit_default_shipping_method' ], 10, 1 );
80 101
81 102 // Modify discounted products.
82 103 add_action( 'woocommerce_before_calculate_totals', [ $this, 'before_cart_calculate' ], 999 );
104 +
105 + // Allow viewing of Checkout page in the Editor with an empty cart.
106 + $action = isset( $_REQUEST['action'] ) ? filter_var( $_REQUEST['action'], FILTER_SANITIZE_FULL_SPECIAL_CHARS ) : ''; // phpcs:ignore
107 + $elementor_preview = isset( $_REQUEST['elementor-preview'] ) ? filter_var( $_REQUEST['elementor-preview'], FILTER_SANITIZE_FULL_SPECIAL_CHARS ) : ''; // phpcs:ignore
108 +
109 + if (
110 + ( 'elementor' === $action && is_admin() ) // Elementor Editor.
111 + || 'elementor_ajax' === $action // Elementor Editor Preview - Ajax Render Widget.
112 + || ! empty( $elementor_preview ) // Elementor Editor Preview.
113 + ) {
114 + add_filter( 'woocommerce_checkout_redirect_empty_cart', '__return_false', 5 );
115 + }
83 116 }
84 117
85 118 /**
86 119 * Handle ajax calls.
@@ -246,8 +279,16 @@
246 279 if ( empty( $optimization_data ) ) {
247 280 return;
248 281 }
249 282
283 + $auto_apply_coupon_cookie_value = null;
284 +
285 + if ( isset( $_COOKIE['sellkit_rejected_coupon'] ) ) {
286 + // Get the value of the cookie.
287 + $auto_apply_coupon_cookie_value = sanitize_text_field( wp_unslash( $_COOKIE['sellkit_rejected_coupon'] ) );
288 + $auto_apply_coupon_cookie_value = explode( ',', $auto_apply_coupon_cookie_value );
289 + }
290 +
250 291 // Help to apply funnel discount prices and coupons when changing product quantity.
251 292 self::apply_discounted_prices( wc()->cart, $funnel_id );
252 293 self::apply_discounted_prices( wc()->cart, $funnel_id, 'bumps' );
253 294
@@ -254,8 +295,11 @@
254 295 if ( Checkout::apply_coupon_validation( $optimization_data ) ) {
255 296 WC()->cart->remove_coupons();
256 297
257 298 foreach ( $optimization_data['auto_apply_coupons'] as $auto_apply_coupon ) {
299 + if ( ! empty( $auto_apply_coupon_cookie_value ) && in_array( $auto_apply_coupon['label'], $auto_apply_coupon_cookie_value, true ) ) {
300 + continue;
301 + }
258 302 wc()->cart->add_discount( get_the_title( $auto_apply_coupon['value'] ) );
259 303 }
260 304
261 305 wc_clear_notices();
@@ -270,9 +314,9 @@
270 314 */
271 315 public function add_shipping_total_to_review_order() {
272 316 ?>
273 317 <tr class="sellkit-shipping-total">
274 - <th><?php echo __( 'Shipping', 'sellkit' ); ?></th>
318 + <th><?php echo esc_html__( 'Shipping', 'sellkit' ); ?></th>
275 319 <td>
276 320 <?php
277 321 $price = WC()->cart->get_shipping_total();
278 322
@@ -279,9 +323,9 @@
279 323 if ( WC()->cart->display_prices_including_tax() ) {
280 324 $price = WC()->cart->get_shipping_total() + WC()->cart->shipping_tax_total;
281 325 }
282 326
283 - echo wc_price( $price );
327 + echo wp_kses_post( wc_price( $price ) );
284 328 ?>
285 329 </td>
286 330 </tr>
287 331 <?php
@@ -806,8 +850,9 @@
806 850 * Modify cart contents using bundled products.
807 851 *
808 852 * @since 1.1.0
809 853 * @return void
854 + * @SuppressWarnings(PHPMD.CyclomaticComplexity)
810 855 */
811 856 public function sellkit_checkout_modify_cart_by_bundle_products() {
812 857 $qty = filter_input( INPUT_POST, 'qty', FILTER_SANITIZE_NUMBER_INT );
813 858 $id = filter_input( INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT );
@@ -827,11 +872,31 @@
827 872 wp_send_json_success();
828 873 }
829 874
830 875 if ( 'radio' === $type ) {
831 - $step_data = get_post_meta( $checkout_id, 'step_data', true );
832 - $products = $step_data['data']['products']['list'];
833 - $selected = $products[ $id ];
876 + $step_data = get_post_meta( $checkout_id, 'step_data', true );
877 + $products = $step_data['data']['products']['list'];
878 + $reset_cart = isset( $step_data['data']['products']['reset_cart'] ) ? $step_data['data']['products']['reset_cart'] : 'true';
879 +
880 + if ( 'true' === $reset_cart ) {
881 + foreach ( WC()->cart->get_cart() as $item ) {
882 + if ( empty( $item['product_id'] ) ) {
883 + continue;
884 + }
885 +
886 + if ( array_key_exists( $item['product_id'], $products ) ) {
887 + continue;
888 + }
889 +
890 + $products[ $item['product_id'] ] = [
891 + 'quantity' => $item['quantity'],
892 + 'discount' => '',
893 + 'discountType' => 'fixed',
894 + ];
895 + }
896 + }
897 +
898 + $selected = ! empty( $products[ $id ] ) ? $products[ $id ] : [];
834 899 $real_quantity = ( empty( $selected['quantity'] ) ) ? 1 : $selected['quantity'];
835 900
836 901 if ( (int) $real_quantity !== (int) $qty ) {
837 902 wp_send_json_error( esc_html__( 'Oh do not be tricky.', 'sellkit' ) );
@@ -886,8 +951,9 @@
886 951 * @param int $checkout_id_ajax checkout id.
887 952 * @param string $source source of products, bump or default products to be checked.
888 953 * @param array $upsell_data upsell product data coming from popup.
889 954 * @since 1.2.8
955 + * @SuppressWarnings(PHPMD.CyclomaticComplexity)
890 956 */
891 957 public static function apply_discounted_prices( $cart = [], $checkout_id_ajax = null, $source = 'default', $upsell_data = [] ) {
892 958 $checkout_id = get_queried_object_id();
893 959
@@ -909,9 +975,9 @@
909 975
910 976 if (
911 977 'default' === $source &&
912 978 array_key_exists( 'data', $step_data ) &&
913 - array_key_exists( 'list', $step_data['data']['products'] )
979 + ( ! empty( $step_data['data']['products'] ) && array_key_exists( 'list', $step_data['data']['products'] ) )
914 980 ) {
915 981 $products = $step_data['data']['products']['list'];
916 982 }
917 983
@@ -922,9 +988,14 @@
922 988 if ( ! array_key_exists( 'products', $bump['data'] ) ) {
923 989 continue;
924 990 }
925 991
926 - $key = array_key_first( $bump['data']['products']['list'] );
992 + $key = ! empty( $bump['data']['products']['list'] ) ? array_key_first( $bump['data']['products']['list'] ) : null;
993 +
994 + if ( empty( $key ) ) {
995 + continue;
996 + }
997 +
927 998 $products[ $key ] = $bump['data']['products']['list'][ $key ];
928 999 }
929 1000 }
930 1001
@@ -947,12 +1018,16 @@
947 1018 }
948 1019
949 1020 foreach ( $products as $product_id => $product_details ) {
950 1021 if ( $item_id === $product_id ) {
951 - $discount_type = $product_details['discountType'];
952 - $discount_value = $product_details['discount'];
1022 + $discount_type = isset( $product_details['discountType'] ) ? $product_details['discountType'] : '';
1023 + $discount_value = isset( $product_details['discount'] ) ? $product_details['discount'] : '';
953 1024
954 1025 $price = Helper::calculate_discount( $item_id, $discount_type, $discount_value );
1026 +
1027 + if ( 'upsell' === $source ) {
1028 + self::$sellkit_upsell_products[ $product_id ] = $price;
1029 + }
955 1030 }
956 1031 }
957 1032
958 1033 if ( false !== $price ) {
@@ -958,9 +1033,9 @@
958 1033 if ( false !== $price ) {
959 1034 $details['data']->set_price( $price );
960 1035 }
961 1036
962 - $final_price += $details['data']->get_price( $price ) * $details['quantity'];
1037 + $final_price += $details['data']->get_price() * $details['quantity'];
963 1038 }
964 1039
965 1040 self::modify_products_price_before_woo_apply_discounts( $final_price );
966 1041 }
@@ -1093,8 +1168,9 @@
1093 1168 /**
1094 1169 * Recalculate checkout and cart prices.
1095 1170 *
1096 1171 * @since 1.2.8
1172 + * @SuppressWarnings(PHPMD.CyclomaticComplexity)
1097 1173 */
1098 1174 public function before_cart_calculate() {
1099 1175 // More than twice isn't necessary. this is called multiple times by WooCommerce.
1100 1176 if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 && wp_doing_ajax() ) {
@@ -1116,11 +1192,13 @@
1116 1192 // Catch id after pressing place order button. none of above methods worked.
1117 1193 if ( empty( $checkout_id ) ) {
1118 1194 $data = filter_input( INPUT_POST, 'post_data', FILTER_DEFAULT );
1119 1195
1120 - parse_str( $data, $data );
1196 + if ( ! empty( $data ) ) {
1197 + parse_str( $data, $data );
1198 + }
1121 1199
1122 - if ( array_key_exists( 'sellkit_current_page_id', $data ) ) {
1200 + if ( is_array( $data ) && array_key_exists( 'sellkit_current_page_id', $data ) ) {
1123 1201 $checkout_id = $data['sellkit_current_page_id'];
1124 1202 }
1125 1203 }
1126 1204 }
@@ -1135,8 +1213,43 @@
1135 1213 // Apply funnel prices.
1136 1214 self::apply_discounted_prices( wc()->cart, $checkout_id );
1137 1215 self::apply_discounted_prices( wc()->cart, $checkout_id, 'bumps' );
1138 1216
1217 + // Apply upsell discount.
1218 + $sellkit_upsell_prices = null;
1219 + if ( isset( $_POST['woocommerce-process-checkout-nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['woocommerce-process-checkout-nonce'] ) ), 'woocommerce-process_checkout' ) ) {
1220 + $sellkit_upsell_prices = isset( $_POST['sellkit_product_prices'] ) ? sanitize_textarea_field( wp_unslash( $_POST['sellkit_product_prices'] ) ) : null;
1221 + }
1222 + $upsell_product_ids;
1223 +
1224 + if ( isset( $sellkit_upsell_prices ) && ! empty( $sellkit_upsell_prices ) ) {
1225 + $sellkit_upsell_prices = json_decode( $sellkit_upsell_prices, true );
1226 + $upsell_product_ids = array_keys( $sellkit_upsell_prices );
1227 + }
1228 +
1229 + if ( isset( $upsell_product_ids ) ) {
1230 + foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
1231 + $product = $cart_item['data'];
1232 + $product_name = $product->get_name();
1233 + $product_id = $product->get_id();
1234 +
1235 + if ( in_array( $product_id, $upsell_product_ids, true ) ) {
1236 + $upsell_price = $sellkit_upsell_prices[ $product_id ];
1237 + $product->set_price( $upsell_price );
1238 + }
1239 +
1240 + $price = $product->get_price();
1241 + }
1242 + }
1243 +
1244 + $auto_apply_coupon_cookie_value = null;
1245 +
1246 + if ( isset( $_COOKIE['sellkit_rejected_coupon'] ) ) {
1247 + // Get the value of the cookie.
1248 + $auto_apply_coupon_cookie_value = sanitize_text_field( wp_unslash( $_COOKIE['sellkit_rejected_coupon'] ) );
1249 + $auto_apply_coupon_cookie_value = explode( ',', $auto_apply_coupon_cookie_value );
1250 + }
1251 +
1139 1252 // We should re apply coupons after each price changes. to make sure everything is correct.
1140 1253 $optimization_data = ! empty( $funnel_data['data']['optimization'] ) ? $funnel_data['data']['optimization'] : '';
1141 1254
1142 1255 if ( Checkout::apply_coupon_validation( $optimization_data ) ) {
@@ -1142,8 +1255,11 @@
1142 1255 if ( Checkout::apply_coupon_validation( $optimization_data ) ) {
1143 1256 WC()->cart->remove_coupons();
1144 1257
1145 1258 foreach ( $optimization_data['auto_apply_coupons'] as $auto_apply_coupon ) {
1259 + if ( ! empty( $auto_apply_coupon_cookie_value ) && in_array( $auto_apply_coupon['label'], $auto_apply_coupon_cookie_value, true ) ) {
1260 + continue;
1261 + }
1146 1262 wc()->cart->add_discount( get_the_title( $auto_apply_coupon['value'] ) );
1147 1263 }
1148 1264
1149 1265 wc_clear_notices();
@@ -1164,15 +1280,21 @@
1164 1280
1165 1281 $funnel->next_step_data['type'] = (array) $funnel->next_step_data['type'];
1166 1282
1167 1283 if ( 'decision' === $funnel->next_step_data['type']['key'] ) {
1168 - $this->take_care_of_decision_step( $funnel->next_step_data['page_id'] );
1284 + $page_id = isset( $funnel->next_step_data['page_id'] ) ? apply_filters( 'wpml_object_id', $funnel->next_step_data['page_id'], 'sellkit_step', true ) : 0; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API.
1285 +
1286 + $this->helper_id = $step;
1287 + $this->take_care_of_decision_step( $page_id, $funnel->funnel_id );
1169 1288 return;
1170 1289 }
1171 1290
1172 1291 if ( in_array( $funnel->next_step_data['type']['key'], $popups, true ) ) {
1292 +
1293 + $next_step = $this->is_set_upsell_product( $next_step );
1294 +
1173 1295 wp_send_json_success( [
1174 - 'next_id' => $next_step['page_id'],
1296 + 'next_id' => apply_filters( 'wpml_object_id', $next_step['page_id'], 'sellkit_step', true ), // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API.
1175 1297 'next_type' => $next_step['type']['key'],
1176 1298 ] );
1177 1299 }
1178 1300 }
@@ -1177,14 +1299,51 @@
1177 1299 }
1178 1300 }
1179 1301
1180 1302 /**
1303 + * Check the upsell or downsell have product or not, ignore upsell/downsell step if product doesn't set.
1304 + *
1305 + * @param array $next_step Next step data.
1306 + * @since 2.6.0
1307 + */
1308 + private function is_set_upsell_product( $next_step ) {
1309 + if ( isset( $next_step['type']['key'] ) && ! in_array( $next_step['type']['key'], [ 'upsell', 'downsell' ], true ) ) {
1310 + return $next_step;
1311 + }
1312 +
1313 + $products = isset( $next_step['data'] ) ? $next_step['data']['products'] : [];
1314 + $list = isset( $products['list'] ) ? $products['list'] : [];
1315 +
1316 + if ( empty( $list ) ) {
1317 + $funnel = isset( $next_step['page_id'] ) ? new Sellkit_Funnel( $next_step['page_id'] ) : null;
1318 + $next_step = ! empty( $funnel ) ? $funnel->next_no_step_data : [];
1319 +
1320 + if ( empty( $next_step ) && ! empty( $funnel ) ) {
1321 + return $funnel->end_node_step_data;
1322 + }
1323 +
1324 + if ( isset( $next_step['type']['key'] ) && in_array( $next_step['type']['key'], [ 'upsell', 'downsell' ], true ) ) {
1325 +
1326 + $next_step = $this->is_set_upsell_product( $next_step );
1327 + }
1328 + }
1329 +
1330 + return $next_step;
1331 + }
1332 +
1333 + /**
1181 1334 * Gets step id before the decision step and return result.
1182 1335 *
1183 1336 * @param int $step_id id of the step before decision step.
1337 + * @param int $funnel_id id of the funnel.
1184 1338 * @since 1.6.2
1185 1339 */
1186 - private function take_care_of_decision_step( $step_id ) {
1340 + private function take_care_of_decision_step( $step_id, $funnel_id = null ) {
1341 + // Failed decision step due to no page id should be checked a little different.
1342 + if ( empty( $step_id ) && ! empty( $funnel_id ) ) {
1343 + $this->check_decision_step_with_no_page_id();
1344 + }
1345 +
1187 1346 $funnel = new Sellkit_Funnel( $step_id );
1188 1347 $conditions = ! empty( $funnel->current_step_data['data']['conditions'] ) ? $funnel->current_step_data['data']['conditions'] : [];
1189 1348 $is_valid = sellkit_conditions_validation( $conditions );
1190 1349 $next_step = $funnel->next_no_step_data;
@@ -1192,23 +1351,51 @@
1192 1351 if ( $is_valid ) {
1193 1352 $next_step = $funnel->next_step_data;
1194 1353 }
1195 1354
1355 + $next_step = $this->is_set_upsell_product( $next_step );
1196 1356 $next_step['type'] = (array) $next_step['type'];
1197 1357
1198 1358 if ( 'decision' === $next_step['type']['key'] ) {
1199 - $this->take_care_of_decision_step( $next_step['page_id'] );
1359 + $this->take_care_of_decision_step( apply_filters( 'wpml_object_id', $next_step['page_id'], 'sellkit_step', true ) ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API.
1200 1360
1201 1361 return;
1202 1362 }
1203 1363
1204 1364 wp_send_json_success( [
1205 - 'next_id' => $next_step['page_id'],
1365 + 'next_id' => apply_filters( 'wpml_object_id', $next_step['page_id'], 'sellkit_step', true ), // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API.
1206 1366 'next_type' => $next_step['type']['key'],
1207 1367 ] );
1208 1368 }
1209 1369
1210 1370 /**
1371 + * Decision next step directly using funnel data.
1372 + *
1373 + * @since 1.8.6
1374 + */
1375 + private function check_decision_step_with_no_page_id() {
1376 + $funnel = new Sellkit_Funnel( $this->helper_id );
1377 + $decicion_data = $funnel->next_step_data;
1378 + $conditions = $decicion_data['data']['conditions'];
1379 + $funnel_data = get_post_meta( $funnel->funnel_id, 'nodes', true );
1380 + $next_no = 'none' !== $decicion_data['targets'][1]['nodeId'] ? $funnel_data[ $decicion_data['targets'][1]['nodeId'] ] : $funnel->end_node_step_data;
1381 + $next_yes = 'none' !== $decicion_data['targets'][0]['nodeId'] ? $funnel_data[ $decicion_data['targets'][0]['nodeId'] ] : $funnel->end_node_step_data;
1382 + $is_valid = sellkit_conditions_validation( $conditions );
1383 + $next_step = $next_no;
1384 +
1385 + if ( $is_valid ) {
1386 + $next_step = $next_yes;
1387 + }
1388 +
1389 + $next_step = $this->is_set_upsell_product( $next_step );
1390 +
1391 + wp_send_json_success( [
1392 + 'next_id' => apply_filters( 'wpml_object_id', $next_step['page_id'], 'sellkit_step', true ), // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API.
1393 + 'next_type' => $next_step['type']['key'],
1394 + ] );
1395 + }
1396 +
1397 + /**
1211 1398 * Perform upsell popup accept button.
1212 1399 *
1213 1400 * @since 1.6.2
1214 1401 */
@@ -1237,9 +1424,9 @@
1237 1424 array_key_exists( 'products', $upsell_data['data'] ) &&
1238 1425 ! empty( $upsell_data['data']['products']['list'] )
1239 1426 ) {
1240 1427 $product_id = array_key_first( $upsell_data['data']['products']['list'] );
1241 - $qty = $upsell_data['data']['products']['list'][ $product_id ]['quantity'];
1428 + $qty = ! empty( $upsell_data['data']['products']['list'][ $product_id ] ) ? $upsell_data['data']['products']['list'][ $product_id ]['quantity'] : 0;
1242 1429 }
1243 1430
1244 1431 if ( empty( $qty ) ) {
1245 1432 $qty = 1;
@@ -1244,23 +1431,46 @@
1244 1431 if ( empty( $qty ) ) {
1245 1432 $qty = 1;
1246 1433 }
1247 1434
1248 - WC()->cart->add_to_cart( $product_id, $qty );
1249 - // Take care of cart and applied discounts.
1250 - self::apply_discounted_prices( WC()->cart, $checkout_id, 'upsell', $upsell_data );
1251 - self::make_changes_after_cart_item_edit( $checkout_id );
1435 + $added_product_hash = '';
1436 +
1437 + if ( ! in_array( $product_id, array_column( WC()->cart->get_cart(), 'product_id' ), true ) ) {
1438 + $added_product_hash = WC()->cart->add_to_cart( $product_id, $qty );
1439 +
1440 + // Take care of cart and applied discounts.
1441 + self::apply_discounted_prices( WC()->cart, $checkout_id, 'upsell', $upsell_data );
1442 + self::make_changes_after_cart_item_edit( $checkout_id );
1443 + }
1444 +
1252 1445 // Response.
1253 1446 $funnel = new Sellkit_Funnel( $upsell_id );
1254 1447 $next_step = $funnel->next_step_data;
1255 - $next_step['type'] = (array) $next_step['type'];
1448 + $next_step = $this->is_set_upsell_product( $next_step );
1449 + $next_step['type'] = ! empty( $next_step['type'] ) ? (array) $next_step['type'] : null;
1256 1450
1451 + if ( 'upsell' === $funnel->current_step_data['type']['key'] && isset( WC()->cart->cart_contents[ $added_product_hash ] ) ) {
1452 + $analytics_updater = new Data_Updater();
1453 + $total = empty( WC()->cart->cart_contents[ $added_product_hash ]['line_total'] ) ? 0 : WC()->cart->cart_contents[ $added_product_hash ]['line_total'];
1454 +
1455 + $analytics_updater->set_funnel_id( $funnel->funnel_id );
1456 + $analytics_updater->add_new_upsell_revenue_log( $total );
1457 + }
1458 +
1459 + $contact_data = [
1460 + 'key' => $funnel->current_step_data['type']['key'],
1461 + 'page_id' => $funnel->current_step_data['page_id'],
1462 + ];
1463 +
1464 + Base_Contacts::step_is_passed( $contact_data );
1465 +
1257 1466 // Step with empty data, will be redirected to thankyou page.
1258 - if ( empty( $next_step ) ) {
1467 + if ( empty( $next_step ) || empty( $next_step['type'] ) ) {
1259 1468 wp_send_json_success(
1260 1469 [
1261 1470 'next_id' => $funnel->end_node_step_data['page_id'],
1262 1471 'next_type' => $funnel->end_node_step_data['type']['key'],
1472 + 'upsell_prices' => wp_json_encode( self::$sellkit_upsell_products ),
1263 1473 ]
1264 1474 );
1265 1475 }
1266 1476
@@ -1269,10 +1479,11 @@
1269 1479 return;
1270 1480 }
1271 1481
1272 1482 $response = [
1273 - 'next_id' => $next_step['page_id'],
1483 + 'next_id' => apply_filters( 'wpml_object_id', $next_step['page_id'], 'sellkit_step', true ), // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API.
1274 1484 'next_type' => $next_step['type']['key'],
1485 + 'upsell_prices' => wp_json_encode( self::$sellkit_upsell_products ),
1275 1486 ];
1276 1487
1277 1488 wp_send_json_success( $response );
1278 1489 }
@@ -1288,14 +1499,18 @@
1288 1499 if ( empty( $upsell_id ) ) {
1289 1500 wp_send_json_error( esc_html__( 'Empty Upsell ID.', 'sellkit' ) );
1290 1501 }
1291 1502
1292 - $funnel = new Sellkit_Funnel( $upsell_id );
1293 - $next_step = $funnel->next_no_step_data;
1294 - $next_step['type'] = (array) $next_step['type'];
1503 + $funnel = new Sellkit_Funnel( $upsell_id );
1504 + $next_step = $funnel->next_no_step_data;
1505 + $next_step = $this->is_set_upsell_product( $next_step );
1295 1506
1507 + if ( $next_step ) {
1508 + $next_step['type'] = (array) $next_step['type'];
1509 + }
1510 +
1296 1511 // Step with empty data, will be redirected to thankyou page.
1297 - if ( empty( $next_step ) ) {
1512 + if ( empty( $next_step ) || empty( $next_step['type'] ) ) {
1298 1513 wp_send_json_success(
1299 1514 [
1300 1515 'next_id' => $funnel->end_node_step_data['page_id'],
1301 1516 'next_type' => $funnel->end_node_step_data['type']['key'],
@@ -1308,11 +1523,60 @@
1308 1523 return;
1309 1524 }
1310 1525
1311 1526 $response = [
1312 - 'next_id' => $next_step['page_id'],
1527 + 'next_id' => apply_filters( 'wpml_object_id', $next_step['page_id'], 'sellkit_step', true ), // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API.
1313 1528 'next_type' => $next_step['type']['key'],
1314 1529 ];
1315 1530
1316 1531 wp_send_json_success( $response );
1532 + }
1533 +
1534 + /**
1535 + * Add new item to the WooCommerce order details on the edit page.
1536 + *
1537 + * @param object $order woocommerce order object.
1538 + * @since 1.8.9
1539 + */
1540 + public function add_item_to_order_details( $order ) {
1541 + $order_id = $order->get_id();
1542 + $custom_fields = get_post_meta( $order_id, 'sellkit_checkout_widget_custom_field_of_order', true );
1543 + $current_action = current_action();
1544 +
1545 + if ( empty( $custom_fields ) || ! is_array( $custom_fields ) ) {
1546 + return;
1547 + }
1548 +
1549 + foreach ( $custom_fields as $field ) {
1550 + $key_name = $field['key_name'];
1551 + $label = $field['label'];
1552 +
1553 + // For old users data.
1554 + if ( empty( $label ) ) {
1555 + $label = $key_name;
1556 + $label = str_replace( '_', ' ', $label );
1557 + $label = str_replace( '-', ' ', $label );
1558 + $label = ucwords( $label );
1559 + }
1560 +
1561 + if (
1562 + 'woocommerce_admin_order_data_after_shipping_address' === $current_action &&
1563 + 'shipping' === substr( $key_name, 0, 8 )
1564 + ) {
1565 + ?>
1566 + <h3><?php echo esc_html( $label ); ?></h3>
1567 + <div><?php echo esc_html( get_post_meta( $order_id, $key_name, true ) ); ?></div>
1568 + <?php
1569 + }
1570 +
1571 + if (
1572 + 'woocommerce_admin_order_data_after_billing_address' === $current_action &&
1573 + 'billing' === substr( $key_name, 0, 7 )
1574 + ) {
1575 + ?>
1576 + <h3><?php echo esc_html( $label ); ?></h3>
1577 + <div><?php echo esc_html( get_post_meta( $order_id, $key_name, true ) ); ?></div>
1578 + <?php
1579 + }
1580 + }
1317 1581 }
1318 1582 }