Skip to content

Instantly share code, notes, and snippets.

@xlplugins
Created December 10, 2025 08:31
Show Gist options
  • Select an option

  • Save xlplugins/8a3232e8a693935f1e3e4768936b98c8 to your computer and use it in GitHub Desktop.

Select an option

Save xlplugins/8a3232e8a693935f1e3e4768936b98c8 to your computer and use it in GitHub Desktop.
Funnelkit Order Bump: Enables cascading/sequential order bumps functionality where selecting one order bump can trigger another bump to appear based on cart rules.
if ( ! class_exists( 'WFOB_Cascading_Bumps_Handler' ) ) {
class WFOB_Cascading_Bumps_Handler {
/**
* Flag to track if fragment unsetting should be processed
*
* @var bool
*/
private $process = false;
/**
* Constructor - Register all hooks
*/
public function __construct() {
// Allow bump items to be counted in cart rules (enables cascading)
add_filter( 'wfob_dont_allow_bump_item_in_rule', [ $this, 'allow_bump_items_in_rules' ], 10, 2 );
// Check for fragment unset flag during checkout update
add_action( 'woocommerce_checkout_update_order_review', [ $this, 'check_fragment_unset_flag' ], 5 );
// Unset fragments to prevent conflicts during bump updates
add_filter( 'woocommerce_update_order_review_fragments', [ $this, 'unset_fragments_on_bump_action' ], 900 );
// Add JavaScript to handle bump add/remove events
add_action( 'wp_footer', [ $this, 'add_bump_control_script' ] );
}
/**
* Allow order bump items to be included in cart rule calculations
*
* By default, FunnelKit excludes bump items from rules. This filter
* overrides that behavior to enable cascading bumps.
*
* @param bool $status Current status (true = exclude, false = include)
* @param array $item Cart item data
* @return bool False to include bump items in rules
*/
public function allow_bump_items_in_rules( $status, $item ) {
if ( isset( $item['_wfob_product'] ) ) {
// Return false to INCLUDE bump items in rule calculations
// This allows Order Bump 1 to trigger Order Bump 2's rules
$status = false;
}
return $status;
}
/**
* Check for fragment unset flag in posted checkout data
*
* When a bump is added/removed, the JavaScript sets a flag that
* tells this method to unset fragments on the next update.
*
* @param string $data Posted checkout data
* @return void
*/
public function check_fragment_unset_flag( $data ) {
if ( empty( $data ) ) {
return;
}
// Parse the posted data string
parse_str( $data, $post_data );
if ( empty( $post_data ) || empty( $post_data['wfob_input_hidden_data'] ) ) {
return;
}
// Decode the bump action data
$bump_action_data = json_decode( $post_data['wfob_input_hidden_data'], true );
if ( empty( $bump_action_data ) ) {
return;
}
// Check if fragment unsetting was requested
if ( isset( $bump_action_data['temp_unset_frg'] ) ) {
$this->process = true;
}
}
/**
* Unset WFACP and WFOB fragments during bump actions
*
* Prevents fragment update conflicts when bumps are added/removed.
* Allows checkout to fully refresh and re-evaluate all bump rules.
*
* @param array $fragments Checkout fragments to be updated
* @return array Modified fragments array
*/
public function unset_fragments_on_bump_action( $fragments ) {
// Only process if flag was set
if ( false == $this->process ) {
return $fragments;
}
// Remove WFACP and WFOB fragments to prevent conflicts
foreach ( $fragments as $k => $fragment ) {
if ( ( false !== strpos( $k, 'wfacp' ) || false !== strpos( $k, 'wfob' ) ) ) {
unset( $fragments[ $k ] );
}
}
// Also remove cart total to force recalculation
unset( $fragments['cart_total'] );
return $fragments;
}
/**
* Add JavaScript to handle bump add/remove events
*
* This script:
* 1. Sets a flag when bumps are added/removed
* 2. Triggers checkout update to re-evaluate bump rules
* 3. Enables cascading bumps to appear/disappear dynamically
*
* @return void
*/
public function add_bump_control_script() {
// Only run on checkout page
if ( ! is_checkout() ) {
return;
}
?>
<script>
window.addEventListener('load', function () {
(function ($) {
// Hook into FunnelKit's bump add/remove filters
wfob_frontend.hooks.addFilter('wfob_before_ajax_data_add_order_bump', set_fragment_unset_flag);
wfob_frontend.hooks.addFilter('wfob_before_ajax_data_remove_order_bump', set_fragment_unset_flag);
// Trigger checkout update after bump actions
wfob_frontend.hooks.addAction('wfob_ajax_add_order_bump', trigger_checkout_refresh);
wfob_frontend.hooks.addAction('wfob_ajax_remove_order_bump', trigger_checkout_refresh);
/**
* Set flag to unset fragments during next checkout update
*/
function set_fragment_unset_flag(data) {
data['temp_unset_frg'] = 'yes';
return data;
}
/**
* Trigger checkout update to re-evaluate bump rules
*/
function trigger_checkout_refresh(rsp) {
$(document.body).trigger('update_checkout');
}
})(jQuery);
});
</script>
<?php
}
}
// Initialize the cascading bumps handler
new WFOB_Cascading_Bumps_Handler();
} // End class_exists check
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment