fix: FSN for guests via option filter, AJAX add-to-cart on single product pages
This commit is contained in:
@@ -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.0.4
|
||||
* Version: 1.1.0
|
||||
* Author: CommerceGurus
|
||||
* Author URI: https://www.commercegurus.com
|
||||
* License: GPLv3
|
||||
@@ -19,7 +19,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
define( 'CGKIT_FC_VERSION', '1.0.4' );
|
||||
define( 'CGKIT_FC_VERSION', '1.1.0' );
|
||||
define( 'CGKIT_FC_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
||||
define( 'CGKIT_FC_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
||||
|
||||
@@ -32,6 +32,30 @@ add_action( 'before_woocommerce_init', function () {
|
||||
}
|
||||
} );
|
||||
|
||||
/**
|
||||
* Force CommerceKit's "show FSN before shipping address is entered" flag on.
|
||||
*
|
||||
* Registered early (plugins_loaded priority 5) so it is in place before
|
||||
* CommerceKit reads the option at plugins_loaded priority 10+.
|
||||
*
|
||||
* Why here rather than in the class: this filter must be attached BEFORE
|
||||
* WooCommerce and CommerceKit finish loading so the very first option read
|
||||
* during any request already sees fsn_before_ship = 1.
|
||||
*
|
||||
* What fsn_before_ship does inside CommerceKit:
|
||||
* if ( ! $fsn_before_ship ) {
|
||||
* if ( ! $show_shipping ) { return ''; } // bails for guests
|
||||
* }
|
||||
* Setting it to 1 skips that entire block, so the notification renders
|
||||
* regardless of whether WooCommerce has calculated shipping yet.
|
||||
*/
|
||||
add_filter( 'option_commercekit', function ( $options ) {
|
||||
if ( is_array( $options ) ) {
|
||||
$options['fsn_before_ship'] = 1;
|
||||
}
|
||||
return $options;
|
||||
}, 1 );
|
||||
|
||||
/**
|
||||
* Main plugin class.
|
||||
*/
|
||||
@@ -55,40 +79,9 @@ class CommerceKit_Floating_Cart {
|
||||
// stays put and we can open the minicart instead.
|
||||
add_filter( 'pre_option_woocommerce_cart_redirect_after_add', [ $this, 'disable_cart_redirect' ] );
|
||||
|
||||
// Ensure WooCommerce's AJAX add-to-cart is active so the body receives
|
||||
// the `added_to_cart` JS event that our script listens for.
|
||||
// Ensure WooCommerce's AJAX add-to-cart is active so archive/shop page
|
||||
// buttons fire the `added_to_cart` JS event without a page reload.
|
||||
add_filter( 'pre_option_woocommerce_enable_ajax_add_to_cart', [ $this, 'enable_ajax_add_to_cart' ] );
|
||||
|
||||
// Show the CommerceKit free shipping notification for guests.
|
||||
// WC's show_shipping() returns false for logged-out users when the store
|
||||
// hides shipping costs until an address is entered, which causes CommerceKit
|
||||
// to skip rendering the bar entirely. We force shipping => true for any
|
||||
// non-empty cart so the notification always renders.
|
||||
add_filter( 'commercekit_fsn_get_cart_options', [ $this, 'fsn_show_for_guests' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the CommerceKit free shipping notification to render for logged-out
|
||||
* users. WC_Cart::show_shipping() returns false for guests when the store
|
||||
* option "Hide shipping costs until an address is entered" is active, which
|
||||
* makes CommerceKit bail before building the bar HTML. Overriding the
|
||||
* `shipping` key here only affects the FSN display logic — WooCommerce's
|
||||
* actual shipping calculation is untouched.
|
||||
*
|
||||
* @param array $options Result from commercekit_fsn_get_cart_options().
|
||||
* @return array
|
||||
*/
|
||||
public function fsn_show_for_guests( array $options ): array {
|
||||
if ( ! isset( $options['shipping'] ) || $options['shipping'] ) {
|
||||
return $options; // already showing, nothing to do.
|
||||
}
|
||||
|
||||
$cart = WC()->cart;
|
||||
if ( $cart && $cart->get_cart_contents_count() > 0 && $options['amount'] > 0 ) {
|
||||
$options['shipping'] = true;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,10 +93,8 @@ class CommerceKit_Floating_Cart {
|
||||
|
||||
/**
|
||||
* Return 'yes' so WooCommerce uses AJAX add-to-cart on archive/shop pages.
|
||||
* This ensures `added_to_cart` JS event fires without a page reload.
|
||||
*/
|
||||
public function enable_ajax_add_to_cart( string $value ): string {
|
||||
// Only override when it's not already enabled.
|
||||
return ( 'yes' === $value ) ? $value : 'yes';
|
||||
}
|
||||
|
||||
@@ -128,39 +119,17 @@ class CommerceKit_Floating_Cart {
|
||||
|
||||
/**
|
||||
* Filter: cgkit_fc_minicart_trigger
|
||||
*
|
||||
* CSS selector(s) for the theme's minicart open button. The floating
|
||||
* cart icon and the add-to-cart auto-open both programmatically click
|
||||
* the first matching element.
|
||||
*
|
||||
* For Shoptimizer / CommerceKit the default covers the most common
|
||||
* header cart selectors. Override this filter in your child theme if
|
||||
* needed.
|
||||
*
|
||||
* @param string $selector A comma-separated CSS selector string.
|
||||
* CSS selector(s) for the theme's minicart open button.
|
||||
*/
|
||||
$trigger = apply_filters(
|
||||
'cgkit_fc_minicart_trigger',
|
||||
'.shoptimizer-cart .cart-contents, .site-header-cart .cart-contents, .wcmenucart, .header-cart-link'
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter: cgkit_fc_auto_open
|
||||
*
|
||||
* Set to false to disable auto-opening the minicart after add to cart.
|
||||
*
|
||||
* @param bool $auto_open
|
||||
*/
|
||||
/** Filter: cgkit_fc_auto_open — set false to disable auto-open after add. */
|
||||
$auto_open = (bool) apply_filters( 'cgkit_fc_auto_open', true );
|
||||
|
||||
/**
|
||||
* Filter: cgkit_fc_auto_open_delay
|
||||
*
|
||||
* Milliseconds to wait before opening the minicart after add to cart,
|
||||
* to allow WooCommerce fragments to refresh first.
|
||||
*
|
||||
* @param int $delay
|
||||
*/
|
||||
/** Filter: cgkit_fc_auto_open_delay — ms to wait before opening (default 400). */
|
||||
$delay = (int) apply_filters( 'cgkit_fc_auto_open_delay', 400 );
|
||||
|
||||
wp_localize_script( 'cgkit-floating-cart', 'cgkitFC', [
|
||||
@@ -168,6 +137,8 @@ class CommerceKit_Floating_Cart {
|
||||
'autoOpen' => $auto_open ? 'yes' : 'no',
|
||||
'autoOpenDelay' => $delay,
|
||||
'cartUrl' => wc_get_cart_url(),
|
||||
// WooCommerce AJAX endpoint used for single-product AJAX add-to-cart.
|
||||
'wcAjaxUrl' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
|
||||
] );
|
||||
}
|
||||
|
||||
@@ -187,15 +158,11 @@ class CommerceKit_Floating_Cart {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a WooCommerce fragment so the badge count updates via AJAX
|
||||
* (e.g. after mini-cart quantity changes or AJAX add-to-cart).
|
||||
*
|
||||
* @param array $fragments
|
||||
* @return array
|
||||
* WooCommerce fragment — keeps the badge count live after AJAX operations.
|
||||
*/
|
||||
public function cart_count_fragment( array $fragments ): array {
|
||||
$count = WC()->cart ? WC()->cart->get_cart_contents_count() : 0;
|
||||
$fragments['#cgkit-fc-count'] = $this->count_badge_html( $count );
|
||||
$count = WC()->cart ? WC()->cart->get_cart_contents_count() : 0;
|
||||
$fragments['#cgkit-fc-count'] = $this->count_badge_html( $count );
|
||||
return $fragments;
|
||||
}
|
||||
|
||||
@@ -203,9 +170,6 @@ class CommerceKit_Floating_Cart {
|
||||
// Private helpers
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return the count badge HTML (targeted by fragments).
|
||||
*/
|
||||
private function count_badge_html( int $count ): string {
|
||||
$hidden = 0 === $count ? ' cgkit-floating-cart__count--hidden' : '';
|
||||
return sprintf(
|
||||
@@ -215,9 +179,6 @@ class CommerceKit_Floating_Cart {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shopping-cart SVG icon (Feather icons style, matches CommerceKit aesthetic).
|
||||
*/
|
||||
private function cart_icon_svg(): string {
|
||||
return '<svg class="cgkit-floating-cart__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
|
||||
width="24" height="24" aria-hidden="true" focusable="false"
|
||||
|
||||
Reference in New Issue
Block a user