connect(); } /** * Connect to Redis server */ private function connect(): void { if (!class_exists('Redis')) { $this->available = false; return; } try { $this->redis = new \Redis(); $connected = @$this->redis->connect('127.0.0.1', 6379, 1.0); if ($connected) { // Select database 1 for search cache (avoid conflicts) $this->redis->select(1); $this->available = true; } else { $this->available = false; } } catch (\Throwable $e) { error_log('ROI APU Search Redis Error: ' . $e->getMessage()); $this->available = false; } } /** * Check if Redis is available */ public function isAvailable(): bool { return $this->available; } /** * Generate cache key from search parameters */ public function generateKey(string $term, int $limit, int $offset, array $categories): string { $term = mb_strtolower(trim($term), 'UTF-8'); sort($categories); $cats = implode(',', $categories); return self::CACHE_PREFIX . md5("{$term}|{$limit}|{$offset}|{$cats}"); } /** * Get cached search results * * @param string $key Cache key * @return array|null Cached results or null if not found */ public function get(string $key): ?array { if (!$this->available) { return null; } try { $data = $this->redis->get($key); if ($data === false) { return null; } $decoded = json_decode($data, true); return is_array($decoded) ? $decoded : null; } catch (\Throwable $e) { error_log('ROI APU Search Redis Get Error: ' . $e->getMessage()); return null; } } /** * Set cached search results * * @param string $key Cache key * @param array $data Data to cache * @param int|null $ttl Time to live in seconds (default: 900) * @return bool Success status */ public function set(string $key, array $data, ?int $ttl = null): bool { if (!$this->available) { return false; } try { $ttl = $ttl ?? self::CACHE_TTL; $json = json_encode($data, JSON_UNESCAPED_UNICODE); return $this->redis->setex($key, $ttl, $json); } catch (\Throwable $e) { error_log('ROI APU Search Redis Set Error: ' . $e->getMessage()); return false; } } /** * Flush all search cache entries * * @return int Number of keys deleted */ public function flush(): int { if (!$this->available) { return 0; } try { $keys = $this->redis->keys(self::CACHE_PREFIX . '*'); if (empty($keys)) { return 0; } return $this->redis->del($keys); } catch (\Throwable $e) { error_log('ROI APU Search Redis Flush Error: ' . $e->getMessage()); return 0; } } /** * Get cache statistics * * @return array Stats including keys count and memory usage */ public function getStats(): array { if (!$this->available) { return ['available' => false]; } try { $keys = $this->redis->keys(self::CACHE_PREFIX . '*'); $info = $this->redis->info('memory'); return [ 'available' => true, 'keys_count' => count($keys), 'memory_used' => $info['used_memory_human'] ?? 'unknown', 'ttl' => self::CACHE_TTL, ]; } catch (\Throwable $e) { return ['available' => true, 'error' => $e->getMessage()]; } } }