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 +270 -27 1.7.92.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
@@ -907,8 +951,9 @@
907 951 * @param int $checkout_id_ajax checkout id.
908 952 * @param string $source source of products, bump or default products to be checked.
909 953 * @param array $upsell_data upsell product data coming from popup.
910 954 * @since 1.2.8
955 + * @SuppressWarnings(PHPMD.CyclomaticComplexity)
911 956 */
912 957 public static function apply_discounted_prices( $cart = [], $checkout_id_ajax = null, $source = 'default', $upsell_data = [] ) {
913 958 $checkout_id = get_queried_object_id();
914 959
@@ -930,9 +975,9 @@
930 975
931 976 if (
932 977 'default' === $source &&
933 978 array_key_exists( 'data', $step_data ) &&
934 - array_key_exists( 'list', $step_data['data']['products'] )
979 + ( ! empty( $step_data['data']['products'] ) && array_key_exists( 'list', $step_data['data']['products'] ) )
935 980 ) {
936 981 $products = $step_data['data']['products']['list'];
937 982 }
938 983
@@ -943,9 +988,14 @@
943 988 if ( ! array_key_exists( 'products', $bump['data'] ) ) {
944 989 continue;
945 990 }
946 991
947 - $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 +
948 998 $products[ $key ] = $bump['data']['products']['list'][ $key ];
949 999 }
950 1000 }
951 1001
@@ -968,12 +1018,16 @@
968 1018 }
969 1019
970 1020 foreach ( $products as $product_id => $product_details ) {
971 1021 if ( $item_id === $product_id ) {
972 - $discount_type = $product_details['discountType'];
973 - $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'] : '';
974 1024
975 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 + }
976 1030 }
977 1031 }
978 1032
979 1033 if ( false !== $price ) {
@@ -979,9 +1033,9 @@
979 1033 if ( false !== $price ) {
980 1034 $details['data']->set_price( $price );
981 1035 }
982 1036
983 - $final_price += $details['data']->get_price( $price ) * $details['quantity'];
1037 + $final_price += $details['data']->get_price() * $details['quantity'];
984 1038 }
985 1039
986 1040 self::modify_products_price_before_woo_apply_discounts( $final_price );
987 1041 }
@@ -1114,8 +1168,9 @@
1114 1168 /**
1115 1169 * Recalculate checkout and cart prices.
1116 1170 *
1117 1171 * @since 1.2.8
1172 + * @SuppressWarnings(PHPMD.CyclomaticComplexity)
1118 1173 */
1119 1174 public function before_cart_calculate() {
1120 1175 // More than twice isn't necessary. this is called multiple times by WooCommerce.
1121 1176 if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 && wp_doing_ajax() ) {
@@ -1137,11 +1192,13 @@
1137 1192 // Catch id after pressing place order button. none of above methods worked.
1138 1193 if ( empty( $checkout_id ) ) {
1139 1194 $data = filter_input( INPUT_POST, 'post_data', FILTER_DEFAULT );
1140 1195
1141 - parse_str( $data, $data );
1196 + if ( ! empty( $data ) ) {
1197 + parse_str( $data, $data );
1198 + }
1142 1199
1143 - if ( array_key_exists( 'sellkit_current_page_id', $data ) ) {
1200 + if ( is_array( $data ) && array_key_exists( 'sellkit_current_page_id', $data ) ) {
1144 1201 $checkout_id = $data['sellkit_current_page_id'];
1145 1202 }
1146 1203 }
1147 1204 }
@@ -1156,8 +1213,43 @@
1156 1213 // Apply funnel prices.
1157 1214 self::apply_discounted_prices( wc()->cart, $checkout_id );
1158 1215 self::apply_discounted_prices( wc()->cart, $checkout_id, 'bumps' );
1159 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 +
1160 1252 // We should re apply coupons after each price changes. to make sure everything is correct.
1161 1253 $optimization_data = ! empty( $funnel_data['data']['optimization'] ) ? $funnel_data['data']['optimization'] : '';
1162 1254
1163 1255 if ( Checkout::apply_coupon_validation( $optimization_data ) ) {
@@ -1163,8 +1255,11 @@
1163 1255 if ( Checkout::apply_coupon_validation( $optimization_data ) ) {
1164 1256 WC()->cart->remove_coupons();
1165 1257
1166 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 + }
1167 1262 wc()->cart->add_discount( get_the_title( $auto_apply_coupon['value'] ) );
1168 1263 }
1169 1264
1170 1265 wc_clear_notices();
@@ -1185,15 +1280,21 @@
1185 1280
1186 1281 $funnel->next_step_data['type'] = (array) $funnel->next_step_data['type'];
1187 1282
1188 1283 if ( 'decision' === $funnel->next_step_data['type']['key'] ) {
1189 - $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 );
1190 1288 return;
1191 1289 }
1192 1290
1193 1291 if ( in_array( $funnel->next_step_data['type']['key'], $popups, true ) ) {
1292 +
1293 + $next_step = $this->is_set_upsell_product( $next_step );
1294 +
1194 1295 wp_send_json_success( [
1195 - '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.
1196 1297 'next_type' => $next_step['type']['key'],
1197 1298 ] );
1198 1299 }
1199 1300 }
@@ -1198,14 +1299,51 @@
1198 1299 }
1199 1300 }
1200 1301
1201 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 + /**
1202 1334 * Gets step id before the decision step and return result.
1203 1335 *
1204 1336 * @param int $step_id id of the step before decision step.
1337 + * @param int $funnel_id id of the funnel.
1205 1338 * @since 1.6.2
1206 1339 */
1207 - 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 +
1208 1346 $funnel = new Sellkit_Funnel( $step_id );
1209 1347 $conditions = ! empty( $funnel->current_step_data['data']['conditions'] ) ? $funnel->current_step_data['data']['conditions'] : [];
1210 1348 $is_valid = sellkit_conditions_validation( $conditions );
1211 1349 $next_step = $funnel->next_no_step_data;
@@ -1213,23 +1351,51 @@
1213 1351 if ( $is_valid ) {
1214 1352 $next_step = $funnel->next_step_data;
1215 1353 }
1216 1354
1355 + $next_step = $this->is_set_upsell_product( $next_step );
1217 1356 $next_step['type'] = (array) $next_step['type'];
1218 1357
1219 1358 if ( 'decision' === $next_step['type']['key'] ) {
1220 - $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.
1221 1360
1222 1361 return;
1223 1362 }
1224 1363
1225 1364 wp_send_json_success( [
1226 - '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.
1227 1366 'next_type' => $next_step['type']['key'],
1228 1367 ] );
1229 1368 }
1230 1369
1231 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 + /**
1232 1398 * Perform upsell popup accept button.
1233 1399 *
1234 1400 * @since 1.6.2
1235 1401 */
@@ -1258,9 +1424,9 @@
1258 1424 array_key_exists( 'products', $upsell_data['data'] ) &&
1259 1425 ! empty( $upsell_data['data']['products']['list'] )
1260 1426 ) {
1261 1427 $product_id = array_key_first( $upsell_data['data']['products']['list'] );
1262 - $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;
1263 1429 }
1264 1430
1265 1431 if ( empty( $qty ) ) {
1266 1432 $qty = 1;
@@ -1265,23 +1431,46 @@
1265 1431 if ( empty( $qty ) ) {
1266 1432 $qty = 1;
1267 1433 }
1268 1434
1269 - WC()->cart->add_to_cart( $product_id, $qty );
1270 - // Take care of cart and applied discounts.
1271 - self::apply_discounted_prices( WC()->cart, $checkout_id, 'upsell', $upsell_data );
1272 - 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 +
1273 1445 // Response.
1274 1446 $funnel = new Sellkit_Funnel( $upsell_id );
1275 1447 $next_step = $funnel->next_step_data;
1276 - $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;
1277 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 +
1278 1466 // Step with empty data, will be redirected to thankyou page.
1279 - if ( empty( $next_step ) ) {
1467 + if ( empty( $next_step ) || empty( $next_step['type'] ) ) {
1280 1468 wp_send_json_success(
1281 1469 [
1282 1470 'next_id' => $funnel->end_node_step_data['page_id'],
1283 1471 'next_type' => $funnel->end_node_step_data['type']['key'],
1472 + 'upsell_prices' => wp_json_encode( self::$sellkit_upsell_products ),
1284 1473 ]
1285 1474 );
1286 1475 }
1287 1476
@@ -1290,10 +1479,11 @@
1290 1479 return;
1291 1480 }
1292 1481
1293 1482 $response = [
1294 - '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.
1295 1484 'next_type' => $next_step['type']['key'],
1485 + 'upsell_prices' => wp_json_encode( self::$sellkit_upsell_products ),
1296 1486 ];
1297 1487
1298 1488 wp_send_json_success( $response );
1299 1489 }
@@ -1309,14 +1499,18 @@
1309 1499 if ( empty( $upsell_id ) ) {
1310 1500 wp_send_json_error( esc_html__( 'Empty Upsell ID.', 'sellkit' ) );
1311 1501 }
1312 1502
1313 - $funnel = new Sellkit_Funnel( $upsell_id );
1314 - $next_step = $funnel->next_no_step_data;
1315 - $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 );
1316 1506
1507 + if ( $next_step ) {
1508 + $next_step['type'] = (array) $next_step['type'];
1509 + }
1510 +
1317 1511 // Step with empty data, will be redirected to thankyou page.
1318 - if ( empty( $next_step ) ) {
1512 + if ( empty( $next_step ) || empty( $next_step['type'] ) ) {
1319 1513 wp_send_json_success(
1320 1514 [
1321 1515 'next_id' => $funnel->end_node_step_data['page_id'],
1322 1516 'next_type' => $funnel->end_node_step_data['type']['key'],
@@ -1329,11 +1523,60 @@
1329 1523 return;
1330 1524 }
1331 1525
1332 1526 $response = [
1333 - '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.
1334 1528 'next_type' => $next_step['type']['key'],
1335 1529 ];
1336 1530
1337 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 + }
1338 1581 }
1339 1582 }