Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force WooCommerce to update fragment

I created plugin which uses WooCommerce fragments for showing to user how many points they have. When user uses some of the points (by adding product into cart) everything works ok.

But when admin adds points to user by admin-interface, the fragment is not updated until user adds a new product into cart.

Here is code sample:

function create_points_widget_content() {
    $usersPoints = esc_attr( get_user_meta( get_current_user_id(), USERS_POINTS, true ));
    if (!isset($userPoints) || $userPoints == "") $userPoints = 0;
    $usedPoints = get_current_points_in_cart('', 0);

    ?>
        <div class="points-widget-v2">
            <div><?php echo __("Your points", "plugin-domain"); ?>:<span class="users-points"><?php echo $usersPoints; ?></span></div>
            <div><?php echo __("Actually used", "plugin-domain"); ?>:<span class="used-points"><?php echo $usedPoints; ?></span></div>
        </div>
    <?php
}

// Update top right price
function add_points_widget_to_fragment( $fragments ) {
    global $woocommerce;
    ob_start();

    create_points_widget_content();

    $fragments['div.points-widget-v2'] = ob_get_clean();
    return $fragments;
}
add_filter('add_to_cart_fragments', 'add_points_widget_to_fragment');

Is there any way how to force fragments to refresh itself?

like image 984
Jan Herzán Avatar asked Jan 21 '17 17:01

Jan Herzán


3 Answers

There is probably a shorter answer by triggering a core handler found in Woocommerce to refresh fragments via ajax.

function refresh_fragments() {
    console.log('fragments refreshed!');
    $( document.body ).trigger( 'wc_fragment_refresh' );
}

refresh_fragments();
setInterval(refresh_fragments, 60000);

This code should trigger the following function binded to 'wc_fragment_refresh' found in cart-fragments.js

function refresh_cart_fragment() {
    $.ajax( $fragment_refresh );
}
like image 182
Chris Medina Avatar answered Sep 28 '22 21:09

Chris Medina


After hours of digging if finaly figured out, why this is happening.

First things first: Woocommerce saves content of the fragments into sessionStorage inside of browser and doesn't update it until a new product is inserted into cart. On the other hand, the sessionStorage is monitored for changes so fragments are updated at all tabs (if there are any) at the same time.

Based on this, I created easy solution which refreshes fragments after page reload and then it updates fragments every minute.

The javascript needed for reloading:

jQuery( function ($) {
    var cart_hash_key = substitutions.cart_hash_key;

    function refresh_fragments() {
        // Better to put there 'blank' string then empty string
        window.sessionStorage.setItem(cart_hash_key, 'blank'); 
        var e = $.Event("storage");

        e.originalEvent = {
            key: cart_hash_key,
        };

        $(window).trigger(e);
    }

    refresh_fragments();
    setInterval(refresh_fragments, 60000);
});

Last bit is inserting the script into page with correct substitutions:

function register_load_fragments_script() {
    // Register the script
    wp_register_script( 'load-fragments-script', get_template_directory_uri() . '/js/load-fragments.js', array(), '20170121', true  );

    // Substitustions in script
    $translation_array = array(
        'cart_hash_key' => WC()->ajax_url() . '-wc_cart_hash'
    );
    wp_localize_script( 'load-fragments-script', 'substitutions', $translation_array );

    wp_enqueue_script( 'load-fragments-script' );
}

I hope this will help someone not to spend whole day trying to solve it ;-)

like image 37
Jan Herzán Avatar answered Sep 28 '22 22:09

Jan Herzán


In my case, I just wanted to refresh the cart once for all my users since I had made a significant change to how the cart items are displayed. Going with a script would require me to remove it after some time (when I think most of my users have had their carts refreshed). I found clearing all existing Woocommerce Sessions by going to Woocommerce -> Tools and clicking Clear under Clear customer sessions to be better suited for my use case.

like image 25
erika_dike Avatar answered Sep 28 '22 23:09

erika_dike