/* ---------- CONTROL ESTRICTO MULTICAPA DEL OBSEQUIO ---------- */ /** * CAPA 1: Sincronización activa al cargar el carrito. * Si detecta que no hay productos legítimos, remueve el obsequio y el cupón de inmediato. * También fuerza la cantidad del obsequio a siempre ser 1. */ add_action('woocommerce_cart_loaded_from_session', 'nwc_strict_gift_sync', 9999); add_action('woocommerce_before_calculate_totals', 'nwc_strict_gift_sync', 9999); function nwc_strict_gift_sync() { if (is_admin() && !defined('DOING_AJAX')) return; $cart = WC()->cart; if (!$cart) return; $has_normal_products = false; $gift_cart_key = null; // Analizar el contenido del carrito foreach ($cart->get_cart() as $cart_item_key => $cart_item) { if (isset($cart_item['nwc_is_gift']) && $cart_item['nwc_is_gift']) { $gift_cart_key = $cart_item_key; // Forzar cantidad estricta a 1 si intentan alterarla if ($cart_item['quantity'] != 1) { $cart->set_quantity($cart_item_key, 1, false); } } else { // El producto NO es un obsequio, es una compra legítima $has_normal_products = true; } } // Si encontramos un regalo pero CERO productos de pago, eliminamos el beneficio if ($gift_cart_key && !$has_normal_products) { $coupon_code = $cart->get_cart_contents()[$gift_cart_key]['nwc_coupon_code'] ?? ''; // Remover de forma silenciosa e inmediata $cart->remove_cart_item($gift_cart_key); if (!empty($coupon_code)) { $cart->remove_coupon($coupon_code); } nwc_log("Sincronización Estricta: Se eliminó el obsequio y el cupón porque el cliente quitó los productos de pago."); } } /** * CAPA 2: Bloqueo Crítico en el Checkout y Validación de Pedido. * Esta es la pared definitiva. Si por algún error de AJAX el obsequio se quedara solo, * este hook detecta la inconsistencia e impide físicamente que se procese la orden de compra. */ add_action('woocommerce_check_cart_items', 'nwc_block_checkout_if_gift_alone'); add_action('woocommerce_after_checkout_validation', 'nwc_block_checkout_if_gift_alone_validation', 10, 2); function nwc_block_checkout_if_gift_alone() { if (is_admin()) return; if (!nwc_is_cart_valid_with_gift()) { wc_add_notice(__('El obsequio requiere la compra de al menos un producto comercial. Ha sido removido.', 'nwc'), 'error'); // Forzar limpieza por si acaso nwc_strict_gift_sync(); } } function nwc_block_checkout_if_gift_alone_validation($data, $errors) { if (!nwc_is_cart_valid_with_gift()) { $errors->add('nwc_invalid_checkout', __('No puedes procesar el pedido solo con el obsequio. Añade un producto comercial.', 'nwc')); nwc_strict_gift_sync(); } } /** * HELPER: Valida si el carrito es lícito (No permite al regalo quedarse solo) */ function nwc_is_cart_valid_with_gift() { $cart = function_exists('WC') ? WC()->cart : null; if (!$cart) return true; $has_gift = false; $has_normal_products = false; foreach ($cart->get_cart() as $cart_item) { if (isset($cart_item['nwc_is_gift']) && $cart_item['nwc_is_gift']) { $has_gift = true; } else { $has_normal_products = true; } } // Si tiene regalo pero NO tiene productos normales, el carrito es inválido if ($has_gift && !$has_normal_products) { return false; } return true; } /** * CAPA 3: Limpieza ante eliminaciones manuales directas (API / Webhooks / Bloques) */ add_action('woocommerce_cart_item_removed', 'nwc_on_gift_removed_cleanup', 10, 2); function nwc_on_gift_removed_cleanup($cart_item_key, $cart) { $removed_item = $cart->removed_cart_contents[$cart_item_key] ?? null; if ($removed_item && isset($removed_item['nwc_is_gift']) && $removed_item['nwc_is_gift']) { $coupon_code = $removed_item['nwc_coupon_code'] ?? ''; if (!empty($coupon_code) && WC()->cart->has_discount($coupon_code)) { WC()->cart->remove_coupon($coupon_code); nwc_log("Limpieza: Se removió el cupón $coupon_code porque el usuario eliminó el obsequio."); } } }