From 1f85d517f0e10b7caa8a7d75f39510b09f9f78ed Mon Sep 17 00:00:00 2001 From: Malin Date: Thu, 5 Mar 2026 08:44:52 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20remap=20add-to-cart=E2=86=92product=5Fid?= =?UTF-8?q?=20for=20AJAX,=20fallback=20zone=20detection=20for=20guest=20FS?= =?UTF-8?q?N=20amount?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/js/floating-cart.js | 12 +++++++- cgkit-floating-cart.php | 59 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/assets/js/floating-cart.js b/assets/js/floating-cart.js index bf0077b..e18ab4d 100644 --- a/assets/js/floating-cart.js +++ b/assets/js/floating-cart.js @@ -113,7 +113,17 @@ e.preventDefault(); $btn.addClass( 'loading' ).data( 'cgkit-fc-handled', true ); - $.post( ajaxUrl, $form.serialize() ) + // WC's wc-ajax=add_to_cart reads $_POST['product_id'], but the + // single-product form submits the ID as field name 'add-to-cart'. + // Append the correctly-named field so the endpoint finds it. + var serialized = $form.serialize(); + var productId = $form.find( '[name="add-to-cart"]' ).val() || + $form.find( '[name="product_id"]' ).val() || ''; + if ( productId && serialized.indexOf( 'product_id=' ) === -1 ) { + serialized += '&product_id=' + encodeURIComponent( productId ); + } + + $.post( ajaxUrl, serialized ) .done( function ( response ) { if ( ! response ) { self.formFallback( $form, $btn ); diff --git a/cgkit-floating-cart.php b/cgkit-floating-cart.php index 51e83e8..2f87151 100644 --- a/cgkit-floating-cart.php +++ b/cgkit-floating-cart.php @@ -3,7 +3,7 @@ * Plugin Name: CommerceKit Floating Cart * Plugin URI: https://www.commercegurus.com * Description: Adds a floating cart icon (bottom-right) and auto-opens the CommerceKit minicart after add to cart. Requires CommerceGurus CommerceKit and WooCommerce. - * Version: 1.1.0 + * Version: 1.1.1 * Author: CommerceGurus * Author URI: https://www.commercegurus.com * License: GPLv3 @@ -19,7 +19,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; } -define( 'CGKIT_FC_VERSION', '1.1.0' ); +define( 'CGKIT_FC_VERSION', '1.1.1' ); define( 'CGKIT_FC_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); define( 'CGKIT_FC_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); @@ -56,6 +56,61 @@ add_filter( 'option_commercekit', function ( $options ) { return $options; }, 1 ); +/** + * Fallback free-shipping amount for guests / users without a shipping address. + * + * CommerceKit bails with `if (!$free_amount) return ''` BEFORE it reaches the + * `fsn_before_ship` check. The bail happens because for guests WooCommerce zone + * detection falls back to "Rest of World" (empty destination in session), which + * often has no free_shipping method → amount stays 0. + * + * Fix: if the amount is still 0 after CommerceKit's own lookup, redo the zone + * detection using the shop's base country/state so we always resolve against + * the same zone as a logged-in customer in the store's home country. + */ +add_filter( 'commercekit_fsn_get_cart_options', function ( array $options ): array { + // Amount already resolved — nothing to do. + if ( $options['amount'] > 0 ) { + return $options; + } + + // Re-run zone detection with the store base location. + $fake_package = [ + 'destination' => [ + 'country' => WC()->countries->get_base_country(), + 'state' => WC()->countries->get_base_state(), + 'postcode' => '', + 'city' => '', + ], + ]; + + $zone = wc_get_shipping_zone( $fake_package ); + $th_sep = wc_get_price_thousand_separator(); + $dc_sep = wc_get_price_decimal_separator(); + + foreach ( $zone->get_shipping_methods( true ) as $method ) { + if ( 'free_shipping' !== $method->id ) { + continue; + } + + $instance = $method->instance_settings ?? []; + $amount = isset( $instance['min_amount'] ) ? $instance['min_amount'] : 0; + $requires = isset( $instance['requires'] ) ? $instance['requires'] : ''; + $amount = floatval( str_replace( $dc_sep, '.', str_replace( $th_sep, '', $amount ) ) ); + + // Only use this fallback when the method just needs a minimum order + // amount — coupon-gated thresholds can't be shown without a coupon. + if ( $amount > 0 && 'min_amount' === $requires ) { + $options['amount'] = $amount; + $options['requires'] = $requires; + $options['shipping'] = true; + } + break; + } + + return $options; +}, 10 ); + /** * Main plugin class. */