id . '_' . $booking_date . '_' . ( $timezone ?: 'default' ); if ( isset( $slot_cache[ $cache_key ] ) ) { return $slot_cache[ $cache_key ]; } if ( ! $timezone ) { $timezone = $this->getTimezone(); } if ( $booking_date == null ) { $booking_date = evavel_now_timezone( $timezone )->format( "Y-m-d" ); } // Verificación rápida: ¿Es la fecha reservable? if ( ! $this->isDateBookable( $booking_date ) ) { $slot_cache[ $cache_key ] = false; return false; } // Optimización: Pre-calcular valores que se usan múltiples veces $now = evavel_now_timezone( $timezone ); $first_seating = $this->getFirstSeatingForDate( $booking_date ); $last_seating = $this->getLastSeatingForDate( $booking_date ); // Verificación rápida: ¿Hay slots disponibles básicos? if ( $first_seating >= $last_seating ) { $slot_cache[ $cache_key ] = false; return false; } // Obtener slots bloqueados una sola vez $blocked_slots = $this->getBlockedSlotsMap( $booking_date ); // Verificar si hay al menos un slot que esté: // 1. No bloqueado // 2. Dentro del horario de apertura/cierre // 3. En el futuro for ( $time = $first_seating; $time <= $last_seating; $time += $this->interval ) { // Skip si el slot está bloqueado if ( isset( $blocked_slots[ $time ] ) && ! $blocked_slots[ $time ] ) { continue; } // Verificación optimizada de horarios de apertura/cierre if ( $this->isSlotWithinOpenCloseWindow( $booking_date, $time, $now, $timezone ) ) { $slot_cache[ $cache_key ] = true; return true; } } $slot_cache[ $cache_key ] = false; return false; } /** * Obtener mapa de slots bloqueados optimizado */ private function getBlockedSlotsMap( $date ) { static $blocked_cache = []; $cache_key = $this->id . '_blocked_' . $date; if ( isset( $blocked_cache[ $cache_key ] ) ) { return $blocked_cache[ $cache_key ]; } $blocked_slots = []; $first_seating = $this->getFirstSeatingForDate( $date ); $last_seating = $this->getLastSeatingForDate( $date ); // Inicializar todos como disponibles for ( $time = $first_seating; $time <= $last_seating; $time += $this->interval ) { $blocked_slots[ $time ] = true; } // Aplicar bloqueos $block_slots = $this->getBlockSlotsForDate( $date ); foreach ( $block_slots as $block_slot ) { if ( isset( $blocked_slots[ $block_slot['time'] ] ) ) { $blocked_slots[ $block_slot['time'] ] = ! $block_slot['block']; } } $blocked_cache[ $cache_key ] = $blocked_slots; return $blocked_slots; } /** * Verificación optimizada de ventana de apertura/cierre */ private function isSlotWithinOpenCloseWindow( $booking_date, $time, $now, $timezone ) { static $window_cache = []; $cache_key = $this->id . '_' . $booking_date . '_' . $time; if ( isset( $window_cache[ $cache_key ] ) ) { return $window_cache[ $cache_key ]; } $booking_date_time = evavel_carbon( $booking_date, $time, $timezone ); // Si el slot ya pasó, no está disponible if ( $now > $booking_date_time ) { $window_cache[ $cache_key ] = false; return false; } $open_date = $this->openDate( $booking_date, $time, $timezone ); $close_date = $this->closeDate( $booking_date, $time, $timezone ); $available = true; if ( $open_date > $close_date ) { $available = false; } else if ( $now < $open_date ) { $available = false; } else if ( $now > $close_date ) { $available = false; } $window_cache[ $cache_key ] = $available; return $available; } }