Sincronizar mu-plugins/ y scripts/ con el estado real del sitio (2026-07-16)

Este repo llevaba desde el 28-jun sin actualizarse (salvo sync_carta_from_prod.py).
Se pone al dia con 3 semanas de trabajo que solo vivian en el checkout local
completo del proyecto:

- Fix del buscador (issue #178): AND obligatorio en FULLTEXT (antes devolvia
  practicamente todo el sitio con cualquier busqueda), exclusion de paginas
  indice residuales de la migracion K2, soporte de frase exacta entre comillas.
- Nuevos mu-plugins ya desplegados a prod: fea-carta-id-api, fea-cloudflare-realip,
  fea-crear-autor-api, fea-gsc-verification, fea-legacy-redirect (cutover
  Joomla->WP, ver issue #162).
- TTS multi-voz por autor, scripts de traduccion, sync de audio a prod,
  homenajes Mardones/Galarreta.

Se mantiene la estructura plana del repo (mu-plugins/ + scripts/, sin el
wordpress/wp-content/ del checkout completo) tal y como documenta el README:
es la convencion establecida para este repo, mas limpia para quien solo
necesita leer el codigo. Anadido .gitignore (cache de Python que no debia
commitearse).

Fuente: checkout local completo del proyecto, rama main (commit 69e849d).
This commit is contained in:
2026-07-15 20:26:43 -04:00
parent d044e229dc
commit 6b61250b0b
35 changed files with 1482 additions and 45 deletions
+33 -3
View File
@@ -6,7 +6,7 @@
* relevancia FULLTEXT si no se pide otro criterio de orden. Degradación elegante:
* si no hay término o el índice FULLTEXT no existe, usa el comportamiento nativo.
* Convive con fea-search-advanced.php (filtros pre_get_posts de autor/cat/cita/fecha).
* Version: 1.1
* Version: 1.3
*/
if (!defined('ABSPATH')) exit;
@@ -38,16 +38,46 @@ function fea_ft_index_exists(): bool {
}
/**
* Calcula el término FULLTEXT en Boolean Mode (cada palabra con prefijo *).
* Calcula el término FULLTEXT en Boolean Mode.
*
* Caso normal (sin comillas): cada palabra requerida con prefijo + y sufijo *. El '+'
* fuerza AND entre palabras — sin él, Boolean Mode las une con OR implícito y cualquier
* post que contenga UNA sola palabra común (p.ej. "ser") entra en el resultado, lo que en
* la práctica devolvía casi todo el sitio (~24.700 de ~24.780 posts, bug #8 reportado en
* feedback: "Tu verdadero ser" devolvía cientos de artículos irrelevantes).
*
* Caso frase exacta (entrecomillado, ej. `"tu verdadero ser"`): Boolean Mode soporta
* nativamente búsqueda de frase entre comillas dobles (coincidencia de adyacencia, no
* solo de palabras sueltas). Reenviamos el contenido saneado tal cual entre comillas, sin
* partirlo en palabras con + ni *, para que el usuario que escribe entre comillas obtenga
* de verdad una búsqueda de cadena exacta.
*
* Devuelve '' si el término sanitizado queda vacío.
*/
function fea_ft_boolean_term(string $raw): string {
// Frase exacta: todo el término entre comillas dobles.
if (preg_match('/^"(.*)"$/us', $raw, $m)) {
$phrase = trim(substr(preg_replace('/[^\p{L}\p{N}\s\'\-]/u', '', $m[1]), 0, 200));
if ($phrase === '') return '';
return '"' . $phrase . '"';
}
$term = trim(substr(preg_replace('/[^\p{L}\p{N}\s\'\-]/u', '', $raw), 0, 200));
if ($term === '') return '';
global $wpdb;
$words = preg_split('/\s+/', $term);
return implode('* ', array_map(fn($w) => $wpdb->esc_like($w), $words)) . '*';
// Descartamos palabras por debajo de innodb_ft_min_token_size (3 en este servidor):
// MySQL las excluye del índice, y forzarlas igualmente como término obligatorio ('+')
// no aporta nada al filtrado (WP igual las ignora) pero SÍ rompe el cálculo de
// relevancia: si un término '+' no existe en el índice, MATCH()...AGAINST() en modo
// boolean puede devolver 0 aunque la fila cumpla el resto de términos, dejando el
// ORDER BY sin poder distinguir resultados relevantes de irrelevantes.
$words = array_values(array_filter($words, fn($w) => mb_strlen($w) >= 3));
if (empty($words)) return '';
return implode(' ', array_map(fn($w) => '+' . $wpdb->esc_like($w) . '*', $words));
}
/**