← All changes
|
public/modules/checkout/class-wpfnl-checkout.php
+655
-56
3.12.13
→
3.13.3
View file →
| @@ -8,9 +8,8 @@ | ||
| 8 | 8 | |
| 9 | 9 | namespace WPFunnels\Modules\Frontend\Checkout; |
| 10 | 10 | |
| 11 | 11 | use Error; |
| 12 | -use WC_Session_Handler; | |
| 13 | 12 | use WPFunnels\Data_Store\Wpfnl_Steps_Store_Data; |
| 14 | 13 | use WPFunnels\Frontend\Module\Wpfnl_Frontend_Module; |
| 15 | 14 | use WPFunnels\Frontend\Wpfnl_Public; |
| 16 | 15 | use WPFunnels\Meta\Wpfnl_Default_Meta; |
| @@ -33,8 +32,22 @@ | ||
| 33 | 32 | public $funnel_id; |
| 34 | 33 | |
| 35 | 34 | public $step_id; |
| 36 | 35 | |
| 36 | + /** | |
| 37 | + * Whether the funnel hidden fields have already been printed for this request. | |
| 38 | + * | |
| 39 | + * @var bool | |
| 40 | + */ | |
| 41 | + private $checkout_metas_rendered = false; | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * Whether the additional information (order notes) block has already rendered. | |
| 45 | + * | |
| 46 | + * @var bool | |
| 47 | + */ | |
| 48 | + private $additional_fields_rendered = false; | |
| 49 | + | |
| 37 | 50 | // const CHECKOUT = ""; |
| 38 | 51 | |
| 39 | 52 | public function __construct() |
| 40 | 53 | { |
| @@ -120,9 +133,11 @@ | ||
| 120 | 133 | add_action( 'wpfunnels/after_optin_submit', array( $this, 'get_optin_data_checkout' ), 10, 4 ); |
| 121 | 134 | add_filter( 'woocommerce_checkout_fields', array($this, 'set_option_data_in_checkout_filed'),10 ); |
| 122 | 135 | add_filter( 'woocommerce_available_payment_gateways', array($this, 'conditional_payment_gateways'),10 ); |
| 123 | 136 | add_action( 'woocommerce_checkout_after_customer_details', array( $this, 'add_custom_shipping_section' ), 10 ); |
| 124 | - add_action( 'woocommerce_checkout_order_review', array( $this, 'display_custom_coupon_field' ) ); | |
| 137 | + add_action( 'wpfunnels/after_order_total', array( $this, 'display_custom_coupon_field' ), 5 ); | |
| 138 | + add_filter( 'woocommerce_update_order_review_fragments', array( $this, 'split_after_order_total_fragment' ) ); | |
| 139 | + add_filter( 'woocommerce_update_order_review_fragments', array( $this, 'wpfnl_update_checkout_fragments' ), 20 ); | |
| 125 | 140 | |
| 126 | 141 | /* Manage Express Checkout buttons visibility dynamically */ |
| 127 | 142 | add_filter( 'wc_stripe_show_payment_request_on_checkout', [$this, 'wpfnl_manage_stripe_express_checkout'], 9999, 2 ); |
| 128 | 143 | |
| @@ -155,9 +170,9 @@ | ||
| 155 | 170 | |
| 156 | 171 | if ( $checkout_id ) { |
| 157 | 172 | $express_checkout_enabled = get_post_meta( $checkout_id, '_wpfnl_express_checkout_enabled', true ); |
| 158 | 173 | if ( 'yes' !== $express_checkout_enabled ) { |
| 159 | - return false; // Hide Stripe Payment Request (Apple Pay / Google Pay) | |
| 174 | + return false; // Hide Stripe Payment Request (Apple Pay / Google Pay) | |
| 160 | 175 | } |
| 161 | 176 | } |
| 162 | 177 | |
| 163 | 178 | return $show; |
| @@ -429,8 +444,11 @@ | ||
| 429 | 444 | * Init necessary actions related Checkout step |
| 430 | 445 | */ |
| 431 | 446 | public function init_actions() { |
| 432 | 447 | add_action( 'woocommerce_after_order_notes', [$this, 'checkout_shortcode_metas']); |
| 448 | + add_action( 'woocommerce_before_order_notes', [$this, 'mark_additional_fields_rendered'], 1 ); | |
| 449 | + // add_action( 'woocommerce_checkout_after_customer_details', [$this, 'maybe_render_additional_fields'], 15 ); | |
| 450 | + add_action( 'woocommerce_checkout_after_customer_details', [$this, 'maybe_render_checkout_metas'], 20 ); | |
| 433 | 451 | $this->display_coupon_field(); |
| 434 | 452 | $this->enable_checkout_hook(); |
| 435 | 453 | |
| 436 | 454 | if ( Wpfnl_functions::check_if_this_is_step_type( 'checkout' ) ) { |
| @@ -445,12 +463,45 @@ | ||
| 445 | 463 | * @since 3.1.3 |
| 446 | 464 | */ |
| 447 | 465 | public function load_checkout_step_scripts() { |
| 448 | 466 | $this->load_google_map_api_scripts(); |
| 467 | + $this->load_tokenization_form_script(); | |
| 449 | 468 | } |
| 450 | 469 | |
| 451 | 470 | |
| 452 | 471 | /** |
| 472 | + * Load WooCommerce's saved payment method (tokenization) script on checkout steps. | |
| 473 | + * | |
| 474 | + * WooCommerce enqueues `woocommerce-tokenization-form` from inside | |
| 475 | + * WC_Payment_Gateway::payment_fields(). On a funnel checkout the payment box is often | |
| 476 | + * rendered for the first time by wc-ajax=update_order_review, where wp_enqueue_script() | |
| 477 | + * is a no-op, so the saved payment method markup arrives without the script that selects | |
| 478 | + * "Use a new payment method". Stripe's UPE script then reads the unchecked | |
| 479 | + * #wc-stripe-payment-token-new radio as "customer picked a saved card", never creates a | |
| 480 | + * PaymentMethod, and the order is placed with an empty wc-stripe-payment-method field. | |
| 481 | + * | |
| 482 | + * Enqueueing it up front on every checkout step keeps the AJAX rendered markup working. | |
| 483 | + * | |
| 484 | + * @since 3.13.2 | |
| 485 | + */ | |
| 486 | + private function load_tokenization_form_script() { | |
| 487 | + if ( ! Wpfnl_functions::is_wc_active() || ! function_exists( 'WC' ) ) { | |
| 488 | + return; | |
| 489 | + } | |
| 490 | + | |
| 491 | + $gateways = WC()->payment_gateways() ? WC()->payment_gateways()->payment_gateways() : []; | |
| 492 | + | |
| 493 | + foreach ( $gateways as $gateway ) { | |
| 494 | + if ( 'yes' === $gateway->enabled && $gateway->supports( 'tokenization' ) ) { | |
| 495 | + // Also localises wc_tokenization_form_params, which the script reads. | |
| 496 | + $gateway->tokenization_script(); | |
| 497 | + break; | |
| 498 | + } | |
| 499 | + } | |
| 500 | + } | |
| 501 | + | |
| 502 | + | |
| 503 | + /** | |
| 453 | 504 | * Load google map places script on checkout page |
| 454 | 505 | * |
| 455 | 506 | * @since 3.1.3 |
| 456 | 507 | */ |
| @@ -580,10 +631,9 @@ | ||
| 580 | 631 | $user_id = $order->get_user_id(); |
| 581 | 632 | $orders[ $checkout_id ] = $order_id; |
| 582 | 633 | WC()->session->set( 'wpfnl_orders_' . $user_id . '_' . $funnel_id, $orders ); |
| 583 | 634 | |
| 584 | - $session_handler = new WC_Session_Handler(); | |
| 585 | - WC()->session->set( 'wpfnl_order_owner', $session_handler->generate_customer_id() ); | |
| 635 | + Wpfnl_functions::mark_order_owned_by_session( $order_id ); | |
| 586 | 636 | |
| 587 | 637 | /** |
| 588 | 638 | * Fires after a funnel order is placed. |
| 589 | 639 | * |
| @@ -621,9 +671,9 @@ | ||
| 621 | 671 | |
| 622 | 672 | if(!Wpfnl_functions::is_wc_active() ){ |
| 623 | 673 | return; |
| 624 | 674 | } |
| 625 | - | |
| 675 | + | |
| 626 | 676 | $checkout_id = ''; |
| 627 | 677 | if( wp_doing_ajax() ){ |
| 628 | 678 | $checkout_id = Wpfnl_functions::get_checkout_id_from_post($_POST); |
| 629 | 679 | } |
| @@ -638,8 +688,9 @@ | ||
| 638 | 688 | || Wpfnl_functions::is_checkoutify_orderbump_clicked_from_post_data() |
| 639 | 689 | || Wpfnl_functions::is_product_option_from_post_data() |
| 640 | 690 | || Wpfnl_functions::is_variation_selected_from_post_data() |
| 641 | 691 | || Wpfnl_functions::maybe_select_quantity_from_post_data() |
| 692 | + || Wpfnl_functions::is_order_bump_already_accepted_from_cookie() | |
| 642 | 693 | // || Wpfnl_functions::is_coupon_applied_from_post_data() |
| 643 | 694 | ) { |
| 644 | 695 | return; |
| 645 | 696 | } |
| @@ -1093,11 +1144,11 @@ | ||
| 1093 | 1144 | } |
| 1094 | 1145 | if(!$checkout_id) { |
| 1095 | 1146 | return ''; |
| 1096 | 1147 | } |
| 1097 | - $checkout_layout = Wpfnl::get_instance()->meta->get_checkout_meta_value($checkout_id, 'wpfnl_checkout_layout', 'wpfnl-col-2'); | |
| 1148 | + $checkout_layout = Wpfnl_functions::get_checkout_layout($checkout_id); | |
| 1098 | 1149 | |
| 1099 | - $floating_label = Wpfnl::get_instance()->meta->get_checkout_meta_value($checkout_id, 'wpfnl_floating_label', ''); | |
| 1150 | + $floating_label = Wpfnl_functions::get_checkout_step_setting($checkout_id, 'wpfnl_floating_label', ''); | |
| 1100 | 1151 | |
| 1101 | 1152 | $output = ''; |
| 1102 | 1153 | ob_start(); |
| 1103 | 1154 | |
| @@ -1194,10 +1245,15 @@ | ||
| 1194 | 1245 | * @since 1.0.0 |
| 1195 | 1246 | */ |
| 1196 | 1247 | public function checkout_shortcode_metas() |
| 1197 | 1248 | { |
| 1249 | + if ($this->checkout_metas_rendered) { | |
| 1250 | + return; | |
| 1251 | + } | |
| 1252 | + | |
| 1198 | 1253 | if (Wpfnl_functions::check_if_this_is_step_type('checkout')) { |
| 1199 | 1254 | global $post; |
| 1255 | + $this->checkout_metas_rendered = true; | |
| 1200 | 1256 | $this->step_id = $post->ID; |
| 1201 | 1257 | $step = new Wpfnl_Steps_Store_Data(); |
| 1202 | 1258 | $step->read($this->step_id); |
| 1203 | 1259 | $this->funnel_id = $step->get_funnel_id(); |
| @@ -1209,8 +1265,94 @@ | ||
| 1209 | 1265 | } |
| 1210 | 1266 | |
| 1211 | 1267 | |
| 1212 | 1268 | /** |
| 1269 | + * Print the funnel hidden fields when the shipping section is skipped. | |
| 1270 | + * | |
| 1271 | + * The checkout layouts only run `woocommerce_checkout_shipping` when the cart | |
| 1272 | + * needs a shipping address, so a cart holding only virtual/downloadable | |
| 1273 | + * products never renders form-shipping.php and `woocommerce_after_order_notes` | |
| 1274 | + * never fires. Without the hidden fields the placed order gets no funnel meta, | |
| 1275 | + * and the customer lands on the WooCommerce order-received page instead of the | |
| 1276 | + * funnel thankyou step. | |
| 1277 | + * | |
| 1278 | + * @since 3.13.2 | |
| 1279 | + */ | |
| 1280 | + public function maybe_render_checkout_metas() | |
| 1281 | + { | |
| 1282 | + $this->checkout_shortcode_metas(); | |
| 1283 | + } | |
| 1284 | + | |
| 1285 | + | |
| 1286 | + /** | |
| 1287 | + * Record that the additional information block has rendered. | |
| 1288 | + * | |
| 1289 | + * Hooked as early as possible on `woocommerce_before_order_notes` so the | |
| 1290 | + * fallback below knows form-shipping.php already produced the section. | |
| 1291 | + * | |
| 1292 | + * @since 3.13.2 | |
| 1293 | + */ | |
| 1294 | + public function mark_additional_fields_rendered() | |
| 1295 | + { | |
| 1296 | + $this->additional_fields_rendered = true; | |
| 1297 | + } | |
| 1298 | + | |
| 1299 | + | |
| 1300 | + /** | |
| 1301 | + * Render the additional information (order notes) block. | |
| 1302 | + * | |
| 1303 | + * WooCommerce ships this block inside form-shipping.php, which the checkout | |
| 1304 | + * layouts only render when the cart needs a shipping address — so a cart of | |
| 1305 | + * virtual/downloadable products lost the order notes field along with the | |
| 1306 | + * `woocommerce_before_order_notes` / `woocommerce_after_order_notes` hooks that | |
| 1307 | + * custom checkout fields rely on, and on shippable carts the block landed above | |
| 1308 | + * the "Use same address for billing" toggle. Rendering it here, on | |
| 1309 | + * `woocommerce_checkout_after_customer_details`, puts it after both address | |
| 1310 | + * forms for every cart. | |
| 1311 | + * | |
| 1312 | + * @since 3.13.2 | |
| 1313 | + */ | |
| 1314 | + public function maybe_render_additional_fields() | |
| 1315 | + { | |
| 1316 | + if ( $this->additional_fields_rendered ) { | |
| 1317 | + return; | |
| 1318 | + } | |
| 1319 | + | |
| 1320 | + if ( ! Wpfnl_functions::check_if_this_is_step_type( 'checkout' ) ) { | |
| 1321 | + return; | |
| 1322 | + } | |
| 1323 | + | |
| 1324 | + if ( ! Wpfnl_functions::is_wc_active() || ! function_exists( 'WC' ) ) { | |
| 1325 | + return; | |
| 1326 | + } | |
| 1327 | + | |
| 1328 | + $checkout = WC()->checkout(); | |
| 1329 | + if ( ! $checkout ) { | |
| 1330 | + return; | |
| 1331 | + } | |
| 1332 | + | |
| 1333 | + $this->additional_fields_rendered = true; | |
| 1334 | + ?> | |
| 1335 | + <div class="woocommerce-additional-fields"> | |
| 1336 | + <?php do_action( 'woocommerce_before_order_notes', $checkout ); ?> | |
| 1337 | + | |
| 1338 | + <?php if ( apply_filters( 'woocommerce_enable_order_notes_field', 'yes' === get_option( 'woocommerce_enable_order_comments', 'yes' ) ) ) : ?> | |
| 1339 | + <h3><?php esc_html_e( 'Additional information', 'woocommerce' ); ?></h3> | |
| 1340 | + | |
| 1341 | + <div class="woocommerce-additional-fields__field-wrapper"> | |
| 1342 | + <?php foreach ( $checkout->get_checkout_fields( 'order' ) as $key => $field ) : ?> | |
| 1343 | + <?php woocommerce_form_field( $key, $field, $checkout->get_value( $key ) ); ?> | |
| 1344 | + <?php endforeach; ?> | |
| 1345 | + </div> | |
| 1346 | + <?php endif; ?> | |
| 1347 | + | |
| 1348 | + <?php do_action( 'woocommerce_after_order_notes', $checkout ); ?> | |
| 1349 | + </div> | |
| 1350 | + <?php | |
| 1351 | + } | |
| 1352 | + | |
| 1353 | + | |
| 1354 | + /** | |
| 1213 | 1355 | * Insert helper hidden ids |
| 1214 | 1356 | * |
| 1215 | 1357 | * @since 1.0.0 |
| 1216 | 1358 | */ |
| @@ -1336,9 +1478,9 @@ | ||
| 1336 | 1478 | * Returns the query parameter after applying the 'wpfunnels/prepare_query_param' filter. |
| 1337 | 1479 | * |
| 1338 | 1480 | * @param array $query_param |
| 1339 | 1481 | * @return array $query_param |
| 1340 | - * | |
| 1482 | + * | |
| 1341 | 1483 | * @since 3.4.13 |
| 1342 | 1484 | */ |
| 1343 | 1485 | return apply_filters( 'wpfunnels/prepare_query_param', $query_param ); |
| 1344 | 1486 | } |
| @@ -1447,8 +1589,12 @@ | ||
| 1447 | 1589 | * |
| 1448 | 1590 | * @since 1.1. |
| 1449 | 1591 | */ |
| 1450 | 1592 | public function wpfnl_order_bump_ajax() { |
| 1593 | + if ( ! check_ajax_referer( 'wpfnl', 'security', false ) ) { | |
| 1594 | + wp_send_json_error( array( 'message' => __( 'Unauthorized request', 'wpfnl' ) ), 403 ); | |
| 1595 | + } | |
| 1596 | + | |
| 1451 | 1597 | $step_id = filter_input( INPUT_POST, 'step_id', FILTER_VALIDATE_INT ); |
| 1452 | 1598 | $product_id = filter_input( INPUT_POST, 'product', FILTER_VALIDATE_INT ); |
| 1453 | 1599 | $variation_id = filter_input( INPUT_POST, 'variation_id', FILTER_VALIDATE_INT ); |
| 1454 | 1600 | $checker = filter_input( INPUT_POST, 'checker', FILTER_SANITIZE_SPECIAL_CHARS ); |
| @@ -1459,17 +1605,33 @@ | ||
| 1459 | 1605 | $funnel_id = Wpfnl_functions::get_funnel_id_from_step( $step_id ); |
| 1460 | 1606 | $type = get_post_meta( $funnel_id, '_wpfnl_funnel_type', true ); |
| 1461 | 1607 | $type = !$type ? 'wc' : $type; |
| 1462 | 1608 | |
| 1463 | - // Validate quantity - must be a positive integer | |
| 1464 | - $quantity = absint( $quantity ); | |
| 1465 | - if ( $quantity < 1 ) { | |
| 1466 | - $quantity = 1; | |
| 1609 | + // The bump's discount is pinned to the product it was configured for, and | |
| 1610 | + // the quantity is the merchant's. Otherwise any step's offer could be | |
| 1611 | + // borrowed and applied to any product. | |
| 1612 | + if ( 'lms' !== $type ) { | |
| 1613 | + $bump = Wpfnl_functions::resolve_order_bump_item( $step_id, $key, $product_id, $variation_id ); | |
| 1614 | + | |
| 1615 | + if ( is_wp_error( $bump ) ) { | |
| 1616 | + wp_send_json_error( array( 'message' => $bump->get_error_message() ), 400 ); | |
| 1617 | + } | |
| 1618 | + | |
| 1619 | + $product_id = $bump['product_id']; | |
| 1620 | + $variation_id = $bump['variation_id']; | |
| 1621 | + $quantity = $bump['quantity']; | |
| 1622 | + $cart_product_id = $bump['cart_product_id']; | |
| 1623 | + } else { | |
| 1624 | + // Validate quantity - must be a positive integer | |
| 1625 | + $quantity = absint( $quantity ); | |
| 1626 | + if ( $quantity < 1 ) { | |
| 1627 | + $quantity = 1; | |
| 1628 | + } | |
| 1629 | + | |
| 1630 | + // If variation_id exists, use it as product_id for cart functions. | |
| 1631 | + $cart_product_id = $variation_id ? $variation_id : $product_id; | |
| 1467 | 1632 | } |
| 1468 | 1633 | |
| 1469 | - // If variation_id exists, use it as product_id for cart functions. | |
| 1470 | - $cart_product_id = $variation_id ? $variation_id : $product_id; | |
| 1471 | - | |
| 1472 | 1634 | $class_object = Wpfnl_Public_Type_Factory::build( $type ); |
| 1473 | 1635 | if( $class_object ) { |
| 1474 | 1636 | $data = $class_object->wpfnl_order_bump_trigger( $step_id, $cart_product_id, $quantity, $key, $user_id, $funnel_id, $checker ); |
| 1475 | 1637 | if( $type === 'lms' ) { |
| @@ -1694,8 +1856,11 @@ | ||
| 1694 | 1856 | public function add_custom_shipping_section() { |
| 1695 | 1857 | if ( ! $this->is_modern_checkout_layout() || ! apply_filters( 'wpfunnels_should_render_custom_shipping', true ) ) { |
| 1696 | 1858 | return; |
| 1697 | 1859 | } |
| 1860 | + if ( ! Wpfnl_functions::is_wc_active() || ! function_exists( 'WC' ) || ! WC()->cart || ! WC()->cart->needs_shipping() ) { | |
| 1861 | + return; | |
| 1862 | + } | |
| 1698 | 1863 | ob_start(); |
| 1699 | 1864 | echo '<div class="wpfnl-customer-shipping">'; |
| 1700 | 1865 | $this->wpfnl_cart_totals_shipping_html(); |
| 1701 | 1866 | echo '</div>'; |
| @@ -1703,8 +1868,465 @@ | ||
| 1703 | 1868 | } |
| 1704 | 1869 | |
| 1705 | 1870 | |
| 1706 | 1871 | /** |
| 1872 | + * Give the `wpfunnels/after_order_total` block its own order-review fragment. | |
| 1873 | + * | |
| 1874 | + * WooCommerce's update_order_review AJAX returns the entire review-order template | |
| 1875 | + * under the `.woocommerce-checkout-review-order-table` key, and checkout.js runs | |
| 1876 | + * `$( key ).replaceWith( value )`. That selector matches only the <table>, so the | |
| 1877 | + * coupon field, order bumps and testimonials that our template appends after it | |
| 1878 | + * were injected again on every refresh while the previous copies remained as | |
| 1879 | + * siblings — one extra copy per AJAX call. | |
| 1880 | + * | |
| 1881 | + * Split the buffer at the wrapper emitted by review-order.php so each key matches | |
| 1882 | + * the outermost node of its own value, which makes both replacements idempotent. | |
| 1883 | + * | |
| 1884 | + * If the wrapper is missing — a theme or plugin overriding review-order.php with | |
| 1885 | + * its own copy — leave the fragments untouched and keep the previous behaviour. | |
| 1886 | + * | |
| 1887 | + * @param array $fragments Fragments keyed by CSS selector. | |
| 1888 | + * | |
| 1889 | + * @return array | |
| 1890 | + * @since 3.13.2 | |
| 1891 | + */ | |
| 1892 | + public function split_after_order_total_fragment( $fragments ) { | |
| 1893 | + $table_key = '.woocommerce-checkout-review-order-table'; | |
| 1894 | + | |
| 1895 | + if ( ! is_array( $fragments ) || empty( $fragments[ $table_key ] ) || ! is_string( $fragments[ $table_key ] ) ) { | |
| 1896 | + return $fragments; | |
| 1897 | + } | |
| 1898 | + | |
| 1899 | + $wrapper = '<div class="wpfnl-after-order-total">'; | |
| 1900 | + // The wrapper is the last thing review-order.php prints; search from the end so | |
| 1901 | + // markup echoed by a hooked callback can never be mistaken for it. | |
| 1902 | + $position = strrpos( $fragments[ $table_key ], $wrapper ); | |
| 1903 | + | |
| 1904 | + if ( false === $position ) { | |
| 1905 | + return $fragments; | |
| 1906 | + } | |
| 1907 | + | |
| 1908 | + $fragments['.wpfnl-after-order-total'] = substr( $fragments[ $table_key ], $position ); | |
| 1909 | + $fragments[ $table_key ] = substr( $fragments[ $table_key ], 0, $position ); | |
| 1910 | + | |
| 1911 | + return $fragments; | |
| 1912 | + } | |
| 1913 | + | |
| 1914 | + | |
| 1915 | + /** | |
| 1916 | + * Update checkout fragments for customer details and multistep navigation | |
| 1917 | + * when cart items (or order bumps) change during update_order_review AJAX. | |
| 1918 | + * | |
| 1919 | + * @param array $fragments | |
| 1920 | + * @return array | |
| 1921 | + */ | |
| 1922 | + public function wpfnl_update_checkout_fragments( $fragments ) { | |
| 1923 | + if ( ! Wpfnl_functions::is_wc_active() || ! function_exists( 'WC' ) || ! WC()->cart || ! WC()->checkout() ) { | |
| 1924 | + return $fragments; | |
| 1925 | + } | |
| 1926 | + | |
| 1927 | + // These fragments re-render WPFunnels' own checkout markup. A theme or page | |
| 1928 | + // builder that ships its own form-checkout.php lays the region out differently | |
| 1929 | + // and can park the order notes block -- and anything hooked to | |
| 1930 | + // `woocommerce_after_order_notes`, such as a relocated payment box -- inside | |
| 1931 | + // #customer_details. Replacing that node with our markup deletes it on the first | |
| 1932 | + // update_order_review, so only rebuild what we rendered ourselves. | |
| 1933 | + if ( ! $this->is_wpfnl_checkout_template_request() ) { | |
| 1934 | + return $fragments; | |
| 1935 | + } | |
| 1936 | + | |
| 1937 | + $checkout_id = Wpfnl_functions::get_checkout_id_from_post( $_POST ); | |
| 1938 | + if ( ! $checkout_id && ! empty( $_POST['wpfnl_step_id'] ) ) { | |
| 1939 | + $checkout_id = absint( $_POST['wpfnl_step_id'] ); | |
| 1940 | + } | |
| 1941 | + if ( ! $checkout_id && ! empty( $_POST['step_id'] ) ) { | |
| 1942 | + $checkout_id = absint( $_POST['step_id'] ); | |
| 1943 | + } | |
| 1944 | + if ( ! $checkout_id && ! empty( $_POST['post_data'] ) ) { | |
| 1945 | + $post_data = array(); | |
| 1946 | + wp_parse_str( wp_unslash( $_POST['post_data'] ), $post_data ); | |
| 1947 | + if ( ! empty( $post_data['wpfnl_step_id'] ) ) { | |
| 1948 | + $checkout_id = absint( $post_data['wpfnl_step_id'] ); | |
| 1949 | + } elseif ( ! empty( $post_data['_wpfunnels_checkout_id'] ) ) { | |
| 1950 | + $checkout_id = absint( $post_data['_wpfunnels_checkout_id'] ); | |
| 1951 | + } | |
| 1952 | + } | |
| 1953 | + | |
| 1954 | + if ( ! $checkout_id ) { | |
| 1955 | + return $fragments; | |
| 1956 | + } | |
| 1957 | + | |
| 1958 | + // Re-initialize actions for billing and shipping form rendering | |
| 1959 | + add_filter( 'woocommerce_locate_template', array( new Wpfnl_Public(), 'wpfunnels_woocommerce_locate_template' ), 20, 3 ); | |
| 1960 | + remove_all_actions( 'woocommerce_checkout_billing' ); | |
| 1961 | + remove_all_actions( 'woocommerce_checkout_shipping' ); | |
| 1962 | + add_action( 'woocommerce_checkout_billing', array( WC()->checkout(), 'checkout_form_billing' ) ); | |
| 1963 | + add_action( 'woocommerce_checkout_shipping', array( WC()->checkout(), 'checkout_form_shipping' ) ); | |
| 1964 | + | |
| 1965 | + $checkout_layout = get_post_meta( $checkout_id, '_wpfnl_checkout_layout', true ); | |
| 1966 | + if ( empty( $checkout_layout ) && isset( $_SESSION['checkout_layout'] ) ) { | |
| 1967 | + $checkout_layout = $_SESSION['checkout_layout']; | |
| 1968 | + } | |
| 1969 | + | |
| 1970 | + // Each fragment below re-fires the checkout form hooks, so the one-shot | |
| 1971 | + // guard in checkout_shortcode_metas() has to be cleared before every render. | |
| 1972 | + // Without this only the first fragment carries _wpfunnels_funnel_id and the | |
| 1973 | + // placed order loses its funnel, so the buyer never reaches the offer step. | |
| 1974 | + $this->checkout_metas_rendered = false; | |
| 1975 | + | |
| 1976 | + // 1. Render #customer_details for default, express, 2-step, modern-one-column | |
| 1977 | + if ( 'wpfnl-modern-one-column' === $checkout_layout ) { | |
| 1978 | + ob_start(); | |
| 1979 | + ?> | |
| 1980 | + <div class="col2-set" id="customer_details"> | |
| 1981 | + <?php do_action( 'wpfunnels/before_customer_details' ); ?> | |
| 1982 | + <?php if ( WC()->cart && WC()->cart->needs_shipping_address() ) : ?> | |
| 1983 | + <div class="wpfnl-modern-section wpfnl-modern-section--shipping" data-section="shipping"> | |
| 1984 | + <div class="wpfnl-modern-section__content"> | |
| 1985 | + <div class="col-2" id="wpfnl_checkout_shipping"> | |
| 1986 | + <?php do_action( 'woocommerce_checkout_shipping' ); ?> | |
| 1987 | + </div> | |
| 1988 | + </div> | |
| 1989 | + </div> | |
| 1990 | + <?php endif; ?> | |
| 1991 | + <div class="wpfnl-modern-section wpfnl-modern-section--billing" data-section="billing"> | |
| 1992 | + <div class="wpfnl-modern-section__content"> | |
| 1993 | + <div class="col-1" id="wpfnl_checkout_billing"> | |
| 1994 | + <?php do_action( 'woocommerce_checkout_billing' ); ?> | |
| 1995 | + </div> | |
| 1996 | + </div> | |
| 1997 | + </div> | |
| 1998 | + <?php do_action( 'wpfunnels/after_customer_details' ); ?> | |
| 1999 | + </div> | |
| 2000 | + <?php | |
| 2001 | + $fragments['#customer_details'] = ob_get_clean(); | |
| 2002 | + } else { | |
| 2003 | + ob_start(); | |
| 2004 | + ?> | |
| 2005 | + <div class="col2-set" id="customer_details"> | |
| 2006 | + <?php do_action( 'wpfunnels/before_customer_details' ); ?> | |
| 2007 | + | |
| 2008 | + <?php | |
| 2009 | + /* | |
| 2010 | + * The classic layouts render the contact card as the first child of | |
| 2011 | + * #customer_details, so this fragment has to reproduce it - replacing the node | |
| 2012 | + * without it would take the required email field off the page on the first | |
| 2013 | + * cart update. form-billing.php drops billing_email from the billing fieldset | |
| 2014 | + * unconditionally, so this stays the only copy of it. | |
| 2015 | + */ | |
| 2016 | + $checkout = WC()->checkout(); | |
| 2017 | + include WPFNL_DIR . 'public/modules/checkout/templates/parts/customer-information.php'; | |
| 2018 | + ?> | |
| 2019 | + | |
| 2020 | + <?php if ( WC()->cart && WC()->cart->needs_shipping_address() ) : ?> | |
| 2021 | + <div class="col-1" id="wpfnl_checkout_shipping"> | |
| 2022 | + <?php do_action( 'woocommerce_checkout_shipping' ); ?> | |
| 2023 | + </div> | |
| 2024 | + <div class="col-2" id="wpfnl_checkout_billing"> | |
| 2025 | + <?php do_action( 'woocommerce_checkout_billing' ); ?> | |
| 2026 | + </div> | |
| 2027 | + <?php else : ?> | |
| 2028 | + <div class="col-1" id="wpfnl_checkout_billing"> | |
| 2029 | + <?php do_action( 'woocommerce_checkout_billing' ); ?> | |
| 2030 | + </div> | |
| 2031 | + <?php endif; ?> | |
| 2032 | + <?php do_action( 'wpfunnels/after_customer_details' ); ?> | |
| 2033 | + </div> | |
| 2034 | + <?php | |
| 2035 | + $fragments['#customer_details'] = ob_get_clean(); | |
| 2036 | + } | |
| 2037 | + | |
| 2038 | + $this->checkout_metas_rendered = false; | |
| 2039 | + | |
| 2040 | + // 2. Render #wpfnl_modern_customer_details for modern 2-column and modern multistep | |
| 2041 | + ob_start(); | |
| 2042 | + ?> | |
| 2043 | + <div id="wpfnl_modern_customer_details" class="wpfnl-modern-customer-details"> | |
| 2044 | + <?php do_action( 'wpfunnels/before_customer_details' ); ?> | |
| 2045 | + <?php if ( WC()->cart && WC()->cart->needs_shipping_address() ) : ?> | |
| 2046 | + <?php do_action( 'woocommerce_checkout_shipping' ); ?> | |
| 2047 | + <?php endif; ?> | |
| 2048 | + <?php do_action( 'woocommerce_checkout_billing' ); ?> | |
| 2049 | + <?php do_action( 'wpfunnels/after_customer_details' ); ?> | |
| 2050 | + </div> | |
| 2051 | + <?php | |
| 2052 | + $fragments['#wpfnl_modern_customer_details'] = ob_get_clean(); | |
| 2053 | + | |
| 2054 | + // 3. Render .wpfnl-multistep-wizard for multistep/express/2-step layouts | |
| 2055 | + ob_start(); | |
| 2056 | + if ( 'wpfnl-2-step' === $checkout_layout ) { | |
| 2057 | + // The 2-step layout has its own wizard shape: Login (optional) / Information / Payment. | |
| 2058 | + // Information covers both shipping and billing; Payment covers the order review. | |
| 2059 | + $two_step_billing_active_cls = is_user_logged_in() || 'no' === get_option( 'woocommerce_enable_checkout_login_reminder' ) ? 'current' : ''; | |
| 2060 | + ?> | |
| 2061 | + <ul class="wpfnl-multistep-wizard"> | |
| 2062 | + <?php if ( ! is_user_logged_in() && 'yes' === get_option( 'woocommerce_enable_checkout_login_reminder' ) ) { ?> | |
| 2063 | + <li class="login current"> | |
| 2064 | + <button type="button" data-target="login"> | |
| 2065 | + <span class="step-icon"> | |
| 2066 | + <?php include WPFNL_DIR . 'public/assets/icons/icon-login.php'; ?> | |
| 2067 | + </span> | |
| 2068 | + <span class="step-title"> | |
| 2069 | + <?php esc_html_e( 'Login', 'wpfnl' ); ?> | |
| 2070 | + </span> | |
| 2071 | + </button> | |
| 2072 | + </li> | |
| 2073 | + <?php } ?> | |
| 2074 | + | |
| 2075 | + <li class="billing <?php echo esc_attr( $two_step_billing_active_cls ); ?>"> | |
| 2076 | + <button type="button" class="two-step" data-target="billing"> | |
| 2077 | + <span class="step-icon"> | |
| 2078 | + <?php include WPFNL_DIR . 'public/assets/icons/icon-billing.php'; ?> | |
| 2079 | + </span> | |
| 2080 | + <span class="step-title"> | |
| 2081 | + <?php esc_html_e( 'Information', 'wpfnl' ); ?> | |
| 2082 | + </span> | |
| 2083 | + </button> | |
| 2084 | + </li> | |
| 2085 | + | |
| 2086 | + <li class="order-review"> | |
| 2087 | + <button type="button" class="two-step" data-target="order-review"> | |
| 2088 | + <span class="step-icon"> | |
| 2089 | + <?php include WPFNL_DIR . 'public/assets/icons/icon-order-review.php'; ?> | |
| 2090 | + </span> | |
| 2091 | + <span class="step-title"> | |
| 2092 | + <?php esc_html_e( 'Payment', 'wpfnl' ); ?> | |
| 2093 | + </span> | |
| 2094 | + </button> | |
| 2095 | + </li> | |
| 2096 | + </ul> | |
| 2097 | + <?php | |
| 2098 | + } else { | |
| 2099 | + ?> | |
| 2100 | + <ul class="wpfnl-multistep-wizard"> | |
| 2101 | + <?php if ( ! is_user_logged_in() && 'yes' === get_option( 'woocommerce_enable_checkout_login_reminder' ) ) { ?> | |
| 2102 | + <li class="login current"> | |
| 2103 | + <button type="button" data-target="login"> | |
| 2104 | + <span class="step-icon"> | |
| 2105 | + <?php include WPFNL_DIR . 'public/assets/icons/icon-login.php'; ?> | |
| 2106 | + </span> | |
| 2107 | + <span class="step-title"> | |
| 2108 | + <?php esc_html_e( 'Login', 'wpfnl' ); ?> | |
| 2109 | + </span> | |
| 2110 | + </button> | |
| 2111 | + </li> | |
| 2112 | + <?php } ?> | |
| 2113 | + | |
| 2114 | + <?php | |
| 2115 | + $shipping_active_cls = ( is_user_logged_in() || 'no' === get_option( 'woocommerce_enable_checkout_login_reminder' ) ) ? 'current' : ''; | |
| 2116 | + $billing_active_cls = ( ( ! is_user_logged_in() && 'yes' === get_option( 'woocommerce_enable_checkout_login_reminder' ) ) || ( WC()->cart && ! WC()->cart->needs_shipping_address() ) ) ? 'current' : ''; | |
| 2117 | + ?> | |
| 2118 | + <?php if ( is_user_logged_in() || 'no' === get_option( 'woocommerce_enable_checkout_login_reminder' ) ) { ?> | |
| 2119 | + <?php if ( WC()->cart && WC()->cart->needs_shipping_address() ) { ?> | |
| 2120 | + <li class="shipping <?php echo esc_attr( $shipping_active_cls ); ?>"> | |
| 2121 | + <button type="button" data-target="shipping"> | |
| 2122 | + <span class="step-icon"> | |
| 2123 | + <?php include WPFNL_DIR . 'public/assets/icons/icon-shipping.php'; ?> | |
| 2124 | + </span> | |
| 2125 | + <span class="step-title"> | |
| 2126 | + <?php esc_html_e( 'Shipping', 'wpfnl' ); ?> | |
| 2127 | + </span> | |
| 2128 | + </button> | |
| 2129 | + </li> | |
| 2130 | + <?php } ?> | |
| 2131 | + <li class="billing <?php echo esc_attr( $billing_active_cls ); ?>"> | |
| 2132 | + <button type="button" data-target="billing"> | |
| 2133 | + <span class="step-icon"> | |
| 2134 | + <?php include WPFNL_DIR . 'public/assets/icons/icon-billing.php'; ?> | |
| 2135 | + </span> | |
| 2136 | + <span class="step-title"> | |
| 2137 | + <?php esc_html_e( 'Billing', 'wpfnl' ); ?> | |
| 2138 | + </span> | |
| 2139 | + </button> | |
| 2140 | + </li> | |
| 2141 | + <li class="order-review"> | |
| 2142 | + <button type="button" data-target="order-review"> | |
| 2143 | + <span class="step-icon"> | |
| 2144 | + <?php include WPFNL_DIR . 'public/assets/icons/icon-order-review.php'; ?> | |
| 2145 | + </span> | |
| 2146 | + <span class="step-title"> | |
| 2147 | + <?php esc_html_e( 'Your Order', 'wpfnl' ); ?> | |
| 2148 | + </span> | |
| 2149 | + </button> | |
| 2150 | + </li> | |
| 2151 | + <?php } ?> | |
| 2152 | + </ul> | |
| 2153 | + <?php | |
| 2154 | + } | |
| 2155 | + $fragments['.wpfnl-multistep-wizard'] = ob_get_clean(); | |
| 2156 | + | |
| 2157 | + // 4. Render .wpfnl-modern-multistep-nav and .wpfnl-modern-multistep-navigation for modern multistep | |
| 2158 | + ob_start(); | |
| 2159 | + ?> | |
| 2160 | + <nav class="wpfnl-modern-multistep-nav" aria-label="<?php esc_attr_e( 'Checkout steps', 'wpfnl' ); ?>"> | |
| 2161 | + <ul class="wpfnl-modern-multistep-nav-steps" role="tablist" aria-orientation="horizontal"> | |
| 2162 | + <li class="wpfnl-modern-multistep-nav-step active" role="presentation" data-step="information"> | |
| 2163 | + <button | |
| 2164 | + type="button" | |
| 2165 | + class="wpfnl-modern-multistep-nav-step-btn" | |
| 2166 | + role="tab" | |
| 2167 | + id="wpfnl-step-tab-information" | |
| 2168 | + aria-controls="wpfnl-step-panel-information" | |
| 2169 | + aria-selected="true" | |
| 2170 | + data-step="information" | |
| 2171 | + > | |
| 2172 | + <?php esc_html_e( 'Information', 'wpfnl' ); ?> | |
| 2173 | + </button> | |
| 2174 | + </li> | |
| 2175 | + | |
| 2176 | + <?php if ( WC()->cart && WC()->cart->needs_shipping_address() ) : ?> | |
| 2177 | + <li class="wpfnl-modern-multistep-nav-sep" aria-hidden="true" role="presentation"> | |
| 2178 | + <svg width="7" height="11" viewBox="0 0 7 11" fill="none" xmlns="http://www.w3.org/2000/svg" focusable="false" aria-hidden="true"> | |
| 2179 | + <path d="M1 1L6 5.5L1 10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> | |
| 2180 | + </svg> | |
| 2181 | + </li> | |
| 2182 | + | |
| 2183 | + <li class="wpfnl-modern-multistep-nav-step" role="presentation" data-step="billing"> | |
| 2184 | + <button | |
| 2185 | + type="button" | |
| 2186 | + class="wpfnl-modern-multistep-nav-step-btn" | |
| 2187 | + role="tab" | |
| 2188 | + id="wpfnl-step-tab-billing" | |
| 2189 | + aria-controls="wpfnl-step-panel-billing" | |
| 2190 | + aria-selected="false" | |
| 2191 | + data-step="billing" | |
| 2192 | + > | |
| 2193 | + <?php esc_html_e( 'Billing', 'wpfnl' ); ?> | |
| 2194 | + </button> | |
| 2195 | + </li> | |
| 2196 | + <?php endif; ?> | |
| 2197 | + | |
| 2198 | + <li class="wpfnl-modern-multistep-nav-sep" aria-hidden="true" role="presentation"> | |
| 2199 | + <svg width="7" height="11" viewBox="0 0 7 11" fill="none" xmlns="http://www.w3.org/2000/svg" focusable="false" aria-hidden="true"> | |
| 2200 | + <path d="M1 1L6 5.5L1 10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> | |
| 2201 | + </svg> | |
| 2202 | + </li> | |
| 2203 | + | |
| 2204 | + <li class="wpfnl-modern-multistep-nav-step" role="presentation" data-step="payment"> | |
| 2205 | + <button | |
| 2206 | + type="button" | |
| 2207 | + class="wpfnl-modern-multistep-nav-step-btn" | |
| 2208 | + role="tab" | |
| 2209 | + id="wpfnl-step-tab-payment" | |
| 2210 | + aria-controls="wpfnl-step-panel-payment" | |
| 2211 | + aria-selected="false" | |
| 2212 | + data-step="payment" | |
| 2213 | + > | |
| 2214 | + <?php esc_html_e( 'Payment', 'wpfnl' ); ?> | |
| 2215 | + </button> | |
| 2216 | + </li> | |
| 2217 | + </ul> | |
| 2218 | + </nav> | |
| 2219 | + <?php | |
| 2220 | + $fragments['.wpfnl-modern-multistep-nav'] = ob_get_clean(); | |
| 2221 | + | |
| 2222 | + ob_start(); | |
| 2223 | + ?> | |
| 2224 | + <div class="wpfnl-modern-multistep-navigation"> | |
| 2225 | + <button | |
| 2226 | + type="button" | |
| 2227 | + class="next-step-btn" | |
| 2228 | + aria-label="Proceed to the next step" | |
| 2229 | + current-step="information" | |
| 2230 | + next-step="<?php echo ( WC()->cart && WC()->cart->needs_shipping_address() ) ? 'billing' : 'payment'; ?>" | |
| 2231 | + > | |
| 2232 | + <?php esc_html_e( 'Proceed to Next Step', 'wpfnl' ); ?> | |
| 2233 | + </button> | |
| 2234 | + </div> | |
| 2235 | + <?php | |
| 2236 | + $fragments['.wpfnl-modern-multistep-navigation'] = ob_get_clean(); | |
| 2237 | + | |
| 2238 | + // 5. Render #rex-checkout-tabs for multi-step-checkout layout | |
| 2239 | + if ( 'wpfnl-multistep' === $checkout_layout ) { | |
| 2240 | + ob_start(); | |
| 2241 | + ?> | |
| 2242 | + <div class="multistep-wrapper" id="rex-checkout-tabs"> | |
| 2243 | + <?php if ( WC()->cart && WC()->cart->needs_shipping_address() ) : ?> | |
| 2244 | + <div class="single-step" id="shipping"> | |
| 2245 | + <?php | |
| 2246 | + if ( WC()->checkout()->get_checkout_fields() ) { | |
| 2247 | + do_action( 'woocommerce_checkout_before_customer_details' ); | |
| 2248 | + do_action( 'woocommerce_checkout_shipping' ); | |
| 2249 | + } | |
| 2250 | + ?> | |
| 2251 | + <div class="navigation"> | |
| 2252 | + <button type="button" id="shippingNext"><?php echo __( 'Next', 'wpfnl' ); ?></button> | |
| 2253 | + </div> | |
| 2254 | + </div> | |
| 2255 | + | |
| 2256 | + <div class="single-step" id="billing"> | |
| 2257 | + <?php | |
| 2258 | + if ( WC()->checkout()->get_checkout_fields() ) { | |
| 2259 | + do_action( 'woocommerce_checkout_billing' ); | |
| 2260 | + do_action( 'woocommerce_checkout_after_customer_details' ); | |
| 2261 | + } | |
| 2262 | + ?> | |
| 2263 | + <div class="navigation"> | |
| 2264 | + <button type="button" id="billingPrevious"><?php echo __( 'Previous', 'wpfnl' ); ?></button> | |
| 2265 | + <button type="button" id="billingNext"><?php echo __( 'Next', 'wpfnl' ); ?></button> | |
| 2266 | + </div> | |
| 2267 | + </div> | |
| 2268 | + <?php else : ?> | |
| 2269 | + <div class="single-step" id="billing"> | |
| 2270 | + <?php | |
| 2271 | + if ( WC()->checkout()->get_checkout_fields() ) { | |
| 2272 | + do_action( 'woocommerce_checkout_before_customer_details' ); | |
| 2273 | + do_action( 'woocommerce_checkout_billing' ); | |
| 2274 | + do_action( 'woocommerce_checkout_after_customer_details' ); | |
| 2275 | + } | |
| 2276 | + ?> | |
| 2277 | + <div class="navigation"> | |
| 2278 | + <button type="button" id="billingNext"><?php echo __( 'Next', 'wpfnl' ); ?></button> | |
| 2279 | + </div> | |
| 2280 | + </div> | |
| 2281 | + <?php endif; ?> | |
| 2282 | + | |
| 2283 | + <div class="single-step" id="review"> | |
| 2284 | + <?php do_action( 'woocommerce_checkout_before_order_review' ); ?> | |
| 2285 | + <div id="order_review" class="woocommerce-checkout-review-order"> | |
| 2286 | + <?php do_action( 'woocommerce_checkout_order_review' ); ?> | |
| 2287 | + </div> | |
| 2288 | + <?php do_action( 'woocommerce_checkout_after_order_review' ); ?> | |
| 2289 | + <div class="navigation"> | |
| 2290 | + <button type="button" id="reviewPrevious"><?php echo __( 'Previous', 'wpfnl' ); ?></button> | |
| 2291 | + </div> | |
| 2292 | + </div> | |
| 2293 | + </div> | |
| 2294 | + <?php | |
| 2295 | + $fragments['#rex-checkout-tabs'] = ob_get_clean(); | |
| 2296 | + } | |
| 2297 | + | |
| 2298 | + return $fragments; | |
| 2299 | + } | |
| 2300 | + | |
| 2301 | + | |
| 2302 | + /** | |
| 2303 | + * Check that the posted checkout form was rendered by a WPFunnels checkout template. | |
| 2304 | + * | |
| 2305 | + * Every WPFunnels checkout form template prints a `wpfnl_step_id` hidden input inside | |
| 2306 | + * the form, so finding it in the serialized `post_data` is what separates our own | |
| 2307 | + * markup from a theme or page builder checkout that merely runs on a funnel step. | |
| 2308 | + * | |
| 2309 | + * @return bool | |
| 2310 | + * @since 3.14.0 | |
| 2311 | + */ | |
| 2312 | + private function is_wpfnl_checkout_template_request() { | |
| 2313 | + if ( ! empty( $_POST['wpfnl_step_id'] ) ) { | |
| 2314 | + return true; | |
| 2315 | + } | |
| 2316 | + | |
| 2317 | + if ( empty( $_POST['post_data'] ) ) { | |
| 2318 | + return false; | |
| 2319 | + } | |
| 2320 | + | |
| 2321 | + $post_data = array(); | |
| 2322 | + wp_parse_str( wp_unslash( $_POST['post_data'] ), $post_data ); | |
| 2323 | + | |
| 2324 | + return ! empty( $post_data['wpfnl_step_id'] ); | |
| 2325 | + } | |
| 2326 | + | |
| 2327 | + | |
| 2328 | + /** | |
| 1707 | 2329 | * Display custom coupon field in modern checkout order review section. |
| 1708 | 2330 | * |
| 1709 | 2331 | * @return void |
| 1710 | 2332 | */ |
| @@ -1778,19 +2400,9 @@ | ||
| 1778 | 2400 | } |
| 1779 | 2401 | |
| 1780 | 2402 | $checkout_id = 0; |
| 1781 | 2403 | if ( wp_doing_ajax() ) { |
| 1782 | - if ( isset( $_POST['step_id'] ) ) { | |
| 1783 | - $checkout_id = intval( wp_unslash( $_POST['step_id'] ) ); | |
| 1784 | - } elseif ( isset( $_POST['_wpfunnels_checkout_id'] ) ) { | |
| 1785 | - $checkout_id = intval( wp_unslash( $_POST['_wpfunnels_checkout_id'] ) ); | |
| 1786 | - } elseif ( isset( $_POST['post_data'] ) ) { | |
| 1787 | - $post_data = array(); | |
| 1788 | - parse_str( wp_unslash( $_POST['post_data'] ), $post_data ); | |
| 1789 | - if ( isset( $post_data['_wpfunnels_checkout_id'] ) ) { | |
| 1790 | - $checkout_id = intval( $post_data['_wpfunnels_checkout_id'] ); | |
| 1791 | - } | |
| 1792 | - } | |
| 2404 | + $checkout_id = Wpfnl_functions::get_checkout_id_from_post( $_POST ); | |
| 1793 | 2405 | } |
| 1794 | 2406 | |
| 1795 | 2407 | if ( ! $checkout_id ) { |
| 1796 | 2408 | $checkout_id = get_the_ID(); |
| @@ -1801,9 +2413,9 @@ | ||
| 1801 | 2413 | } |
| 1802 | 2414 | |
| 1803 | 2415 | $show_coupon = Wpfnl::get_instance()->meta->get_checkout_meta_value( $checkout_id, '_wpfnl_checkout_coupon' ); |
| 1804 | 2416 | |
| 1805 | - return 'yes' === $show_coupon; | |
| 2417 | + return 'no' !== $show_coupon; | |
| 1806 | 2418 | } |
| 1807 | 2419 | |
| 1808 | 2420 | |
| 1809 | 2421 | /** |
| @@ -1813,19 +2425,9 @@ | ||
| 1813 | 2425 | */ |
| 1814 | 2426 | private function is_collapsible_coupon_enabled() { |
| 1815 | 2427 | $checkout_id = 0; |
| 1816 | 2428 | if ( wp_doing_ajax() ) { |
| 1817 | - if ( isset( $_POST['step_id'] ) ) { | |
| 1818 | - $checkout_id = intval( wp_unslash( $_POST['step_id'] ) ); | |
| 1819 | - } elseif ( isset( $_POST['_wpfunnels_checkout_id'] ) ) { | |
| 1820 | - $checkout_id = intval( wp_unslash( $_POST['_wpfunnels_checkout_id'] ) ); | |
| 1821 | - } elseif ( isset( $_POST['post_data'] ) ) { | |
| 1822 | - $post_data = array(); | |
| 1823 | - parse_str( wp_unslash( $_POST['post_data'] ), $post_data ); | |
| 1824 | - if ( isset( $post_data['_wpfunnels_checkout_id'] ) ) { | |
| 1825 | - $checkout_id = intval( $post_data['_wpfunnels_checkout_id'] ); | |
| 1826 | - } | |
| 1827 | - } | |
| 2429 | + $checkout_id = Wpfnl_functions::get_checkout_id_from_post( $_POST ); | |
| 1828 | 2430 | } |
| 1829 | 2431 | |
| 1830 | 2432 | if ( ! $checkout_id ) { |
| 1831 | 2433 | $checkout_id = get_the_ID(); |
| @@ -1948,19 +2550,9 @@ | ||
| 1948 | 2550 | private function is_modern_checkout_layout() { |
| 1949 | 2551 | $checkout_id = 0; |
| 1950 | 2552 | |
| 1951 | 2553 | if ( wp_doing_ajax() ) { |
| 1952 | - if ( isset( $_POST['step_id'] ) ) { | |
| 1953 | - $checkout_id = intval( wp_unslash( $_POST['step_id'] ) ); | |
| 1954 | - } elseif ( isset( $_POST['_wpfunnels_checkout_id'] ) ) { | |
| 1955 | - $checkout_id = intval( wp_unslash( $_POST['_wpfunnels_checkout_id'] ) ); | |
| 1956 | - } elseif ( isset( $_POST['post_data'] ) ) { | |
| 1957 | - $post_data = array(); | |
| 1958 | - parse_str( wp_unslash( $_POST['post_data'] ), $post_data ); | |
| 1959 | - if ( isset( $post_data['_wpfunnels_checkout_id'] ) ) { | |
| 1960 | - $checkout_id = intval( $post_data['_wpfunnels_checkout_id'] ); | |
| 1961 | - } | |
| 1962 | - } | |
| 2554 | + $checkout_id = Wpfnl_functions::get_checkout_id_from_post( $_POST ); | |
| 1963 | 2555 | } |
| 1964 | 2556 | |
| 1965 | 2557 | if ( ! $checkout_id ) { |
| 1966 | 2558 | $checkout_id = get_the_ID(); |
| @@ -1969,11 +2561,11 @@ | ||
| 1969 | 2561 | if ( ! $checkout_id ) { |
| 1970 | 2562 | return false; |
| 1971 | 2563 | } |
| 1972 | 2564 | |
| 1973 | - $checkout_layout = Wpfnl::get_instance()->meta->get_checkout_meta_value( $checkout_id, 'wpfnl_checkout_layout', 'wpfnl-col-2' ); | |
| 2565 | + $checkout_layout = Wpfnl_functions::get_checkout_layout( $checkout_id ); | |
| 1974 | 2566 | |
| 1975 | - return in_array( $checkout_layout, array( 'wpfnl-modern-checkout', 'wpfnl-modern-one-column' ), true ); | |
| 2567 | + return ( false !== strpos( $checkout_layout, 'modern' ) ) || in_array( $checkout_layout, array( 'wpfnl-modern-checkout', 'wpfnl-modern-one-column', 'wpfnl-modern-multistep' ), true ); | |
| 1976 | 2568 | } |
| 1977 | 2569 | |
| 1978 | 2570 | |
| 1979 | 2571 | /** |
| @@ -2101,9 +2693,9 @@ | ||
| 2101 | 2693 | |
| 2102 | 2694 | if( !is_array($discount) ){ |
| 2103 | 2695 | return; |
| 2104 | 2696 | } |
| 2105 | - | |
| 2697 | + | |
| 2106 | 2698 | if( (isset($discount['discountOptions']) && $discount['discountOptions'] !== 'original') ){ |
| 2107 | 2699 | if( 'regular' === $discount['discountapplyto'] ){ |
| 2108 | 2700 | foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) { |
| 2109 | 2701 | $product = $cart_item['data']; |
| @@ -2127,11 +2719,11 @@ | ||
| 2127 | 2719 | |
| 2128 | 2720 | |
| 2129 | 2721 | /** |
| 2130 | 2722 | * Check whether funnel checkout product is available on cart or not |
| 2131 | - * | |
| 2723 | + * | |
| 2132 | 2724 | * @return boolean true if funnel checkout product is available on cart, false otherwise |
| 2133 | - * | |
| 2725 | + * | |
| 2134 | 2726 | * @access public |
| 2135 | 2727 | * @since 3.4.15 |
| 2136 | 2728 | */ |
| 2137 | 2729 | public function is_funnel_checkout_product_available_on_cart() { |
| @@ -2243,9 +2835,16 @@ | ||
| 2243 | 2835 | $checkout_id = get_the_ID(); |
| 2244 | 2836 | } |
| 2245 | 2837 | |
| 2246 | 2838 | if ( $checkout_id ) { |
| 2247 | - $checkout_layout = Wpfnl::get_instance()->meta->get_checkout_meta_value( $checkout_id, 'wpfnl_checkout_layout', 'wpfnl-col-2' ); | |
| 2839 | + if ( | |
| 2840 | + Wpfnl_functions::check_if_this_is_step_type_by_id( $checkout_id, 'checkout' ) && | |
| 2841 | + isset( $fields['order']['order_comments']['placeholder'] ) | |
| 2842 | + ) { | |
| 2843 | + $fields['order']['order_comments']['placeholder'] = esc_attr__( 'Notes about your order', 'wpfnl' ); | |
| 2844 | + } | |
| 2845 | + | |
| 2846 | + $checkout_layout = Wpfnl_functions::get_checkout_layout( $checkout_id ); | |
| 2248 | 2847 | |
| 2249 | 2848 | if ( 'wpfnl-modern-checkout' === $checkout_layout ) { |
| 2250 | 2849 | if ( isset( $fields['account']['account_username'] ) ) { |
| 2251 | 2850 | unset( $fields['account']['account_username'] ); |