fix(analytics): Corregir URLs en analytics usando post_name desde BD
Problema: - URLs en analytics mostraban dominio incorrecto (HTTP_HOST) - URLs usaban formato /?p=ID en lugar de permalinks Solución: - class-search-engine.php: Agregar propiedad $prefix, incluir p.post_name en 5 queries fetch, agregar helpers getSiteUrlFromDb(), getPermalinkStructure() y buildPermalink() - search-endpoint.php: Obtener site_url y permalink_structure desde wp_options, construir URLs con post_name - click-endpoint.php: Fallback de dest usando post_name desde BD Archivos modificados: - includes/class-search-engine.php - api/search-endpoint.php - api/click-endpoint.php 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
195
includes/class-redis-cache.php
Normal file
195
includes/class-redis-cache.php
Normal file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
/**
|
||||
* Redis Cache Handler for ROI APU Search
|
||||
*
|
||||
* Provides caching layer for search results using Redis.
|
||||
*
|
||||
* @package ROI_APU_Search
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// Prevent direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redis cache handler with singleton pattern
|
||||
*/
|
||||
final class ROI_APU_Search_Redis
|
||||
{
|
||||
private static ?self $instance = null;
|
||||
private ?\Redis $redis = null;
|
||||
private bool $available = false;
|
||||
|
||||
private const CACHE_PREFIX = 'apu_search:';
|
||||
private const CACHE_TTL = 900; // 15 minutes
|
||||
|
||||
/**
|
||||
* Get singleton instance
|
||||
*/
|
||||
public static function get_instance(): self
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor - initialize Redis connection
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
$this->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()];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user