/** * Plugin Name: Baypass – Lightweight Counts (Burst Refresh) * Description: Счётчик корзины без фрагментов. События Woo сохраняются (анимация остаётся). Быстрое обновление через серию лёгких запросов к серверу. * Version: 1.6.2 */ if (!defined('ABSPATH')) exit; /** ===== Точная кука (видима JS) ===== */ function bp_set_cart_count_cookie($count = null) { if (!function_exists('WC')) return; if ($count === null) $count = (WC()->cart ? WC()->cart->get_cart_contents_count() : 0); $count = max(0, (int)$count); $expire = time() + 30 * DAY_IN_SECONDS; if (function_exists('wc_setcookie')) { wc_setcookie('bp_cart_count', (string)$count, $expire, is_ssl(), false); // HttpOnly=false } else { setcookie('bp_cart_count', (string)$count, $expire, COOKIEPATH ?: '/', COOKIE_DOMAIN, is_ssl(), false); } } /** ===== Синхронизация куки на все изменения корзины ===== */ add_action('woocommerce_add_to_cart', function(){ bp_set_cart_count_cookie(); }, 9999); add_action('woocommerce_ajax_added_to_cart', function(){ bp_set_cart_count_cookie(); }, 9999); add_action('woocommerce_cart_item_removed', function(){ bp_set_cart_count_cookie(); }, 9999); add_action('woocommerce_cart_item_restored', function(){ bp_set_cart_count_cookie(); }, 9999); add_action('woocommerce_after_cart_item_quantity_update', function(){ bp_set_cart_count_cookie(); }, 9999, 0); add_action('woocommerce_cart_emptied', function(){ bp_set_cart_count_cookie(0); }, 9999); /** Держим актуальность на обычных просмотрах */ add_action('template_redirect', function () { if (is_admin() && !defined('DOING_AJAX')) return; if (function_exists('WC') && WC()->cart) bp_set_cart_count_cookie(); }, 20); /** ===== AJAX: bp_cart_count (JSON) – точное число ===== */ function bp_ajax_cart_count() { if (function_exists('wc_load_cart')) wc_load_cart(); if (function_exists('WC') && WC()->session && ! WC()->session->has_session()) { WC()->session->set_customer_session_cookie(true); } $count = (function_exists('WC') && WC()->cart) ? WC()->cart->get_cart_contents_count() : 0; bp_set_cart_count_cookie($count); wp_send_json_success(['count' => (int)$count]); } add_action('wp_ajax_bp_cart_count', 'bp_ajax_cart_count'); add_action('wp_ajax_nopriv_bp_cart_count', 'bp_ajax_cart_count'); /** ===== Совместимость: update_cart_counter (plain text) ===== */ function bp_ajax_update_cart_counter_plain() { if (function_exists('wc_load_cart')) wc_load_cart(); if (function_exists('WC') && WC()->session && ! WC()->session->has_session()) { WC()->session->set_customer_session_cookie(true); } $count = (function_exists('WC') && WC()->cart) ? (int) WC()->cart->get_cart_contents_count() : 0; if (function_exists('bp_set_cart_count_cookie')) bp_set_cart_count_cookie($count); wp_die((string)$count); // фронт ждёт строку-число } add_action('wp_ajax_update_cart_counter', 'bp_ajax_update_cart_counter_plain'); add_action('wp_ajax_nopriv_update_cart_counter', 'bp_ajax_update_cart_counter_plain'); /** ===== Чистим старые привязки проекта (если остались) ===== */ add_action('init', function () { remove_action('wp_ajax_get_wishlist_count', 'tpl_get_wishlist_count'); remove_action('wp_ajax_nopriv_get_wishlist_count', 'tpl_get_wishlist_count'); }, 20); /** ===== Отключаем только фрагменты (анимацию не трогаем) ===== */ add_action('wp_enqueue_scripts', function(){ if (is_admin()) return; if (function_exists('is_cart') && (is_cart() || is_checkout())) return; wp_dequeue_script('wc-cart-fragments'); wp_deregister_script('wc-cart-fragments'); }, 20); /** ===== Снимаем старые фронтовые апдейтеры, если вдруг цепляются ===== */ add_action('wp_enqueue_scripts', function () { foreach (['tpl-update-badges','update_bages','update_badges','tpl-update-badges-js','bp-update-badges'] as $h) { wp_dequeue_script($h); wp_deregister_script($h); } }, 100); /** ===== Фронт: бурст-обновление счётчика по событиям Woo/jQuery ===== */ add_action('wp_enqueue_scripts', function () { wp_register_script('baypass-counts-inline', false, [], null, true); wp_enqueue_script('baypass-counts-inline'); $ajax_url = admin_url('admin-ajax.php'); $js = <<0) ? String(n) : ''; }); } function updateWishBadges(){ var w = getCookie('woocommerce_wishlist_items'); var c = w ? w.split(',').filter(Boolean).length : 0; document.querySelectorAll(SEL_WISH).forEach(function(el){ el.textContent = (c>0) ? String(c) : ''; }); } // точный запрос к серверу var inFlight=false,lastT=0; function refreshFromServer() { var now = Date.now(); if (inFlight && now - lastT < 90) return Promise.resolve(); inFlight=true; lastT=now; return fetch(AJAX_URL, { method:'POST', headers:{'Content-Type':'application/x-www-form-urlencoded'}, credentials:'same-origin', body:'action=bp_cart_count' }).then(function(r){ return r.json(); }) .then(function(j){ if (j && j.success && j.data && typeof j.data.count==='number') { updateCartBadges(j.data.count); } }) .catch(function(){}) .finally(function(){ inFlight=false; }); } // быстрый ряд запросов: ловим момент обновления корзины function burstRefresh(intervalMs, times){ intervalMs = intervalMs || 120; times = times || 8; // ~1 сек суммарно function tick(){ refreshFromServer().finally(function(){ if (--times > 0) setTimeout(tick, intervalMs); }); } tick(); } // первичная отрисовка document.addEventListener('DOMContentLoaded', function(){ refreshFromServer().then(updateWishBadges); }); document.addEventListener('visibilitychange', function(){ if (!document.hidden) refreshFromServer(); }); // Woo/jQuery события — анимацию не ломаем, только подхватываем обновления if (window.jQuery && jQuery(document)) { // как только Woo начал добавление — запускаем быстрый короткий бурст jQuery(document.body).on('adding_to_cart', function(){ burstRefresh(120, 6); // ~0.7с }); // как только завершил — добиваем точным значением jQuery(document.body).on('added_to_cart wc_fragments_refreshed updated_wc_div cart_page_refreshed', function(){ burstRefresh(150, 3); }); // если тема трогает свои AJAX, тоже ловим jQuery(document).ajaxComplete(function(e,xhr,settings){ try{ var u=(settings&&settings.url)?String(settings.url):''; var d=(settings&&settings.data)?String(settings.data):''; if (u.indexOf('wc-ajax=add_to_cart')!==-1 || (u.indexOf('admin-ajax.php')!==-1 && /add_to_cart|woocommerce_add_to_cart|product_id|add-to-cart/i.test(d))) { burstRefresh(120, 5); } }catch(err){} }); } // клик по любым кнопкам «в корзину» — на всякий случай тоже стартуем бурст document.addEventListener('click', function(e){ var btn = e.target && e.target.closest('.add_to_cart_button, button.single_add_to_cart_button, [name="add-to-cart"], a[href*="add-to-cart="]'); if (!btn) return; burstRefresh(120, 6); }, false); })(); JS; wp_add_inline_script('baypass-counts-inline', $js); }, 9999);