feat(#8): buscador visible (MVP nativo)

- fea-search.php: barra de búsqueda visible en móvil (donde el menú
  colapsa y oculta el buscador del menú); multiidioma por Polylang.
- set_search_template.php: template FSE 'search' con resultados en
  rejilla de tarjetas (reutiliza el layout de archive #63) en vez del
  patrón del tema que los mostraba 'todos seguidos'.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-27 11:18:50 -04:00
parent 84ec9163b2
commit 8ea4d51fd2
2 changed files with 147 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
<?php
/**
* set_search_template.php (#8) — instala un template FSE 'search' con resultados
* COMPACTOS (rejilla de tarjetas título+fecha+extracto), igual que el 'archive'
* (#63), en vez del patrón genérico del tema que muestra los posts «todos seguidos».
*
* Reutiliza las clases fea-archive-grid / fea-archive-card (mismo CSS ya presente).
* Idempotente: crea el wp_template 'search' si no existe, o actualiza su contenido.
*
* Uso (dentro del contenedor / wp-cli):
* wp eval-file scripts/set_search_template.php # DRY-RUN
* APPLY=1 wp eval-file scripts/set_search_template.php # aplica
*/
$apply = getenv('APPLY') === '1';
$theme = get_stylesheet(); // twentytwentyfive
$content = <<<HTML
<!-- wp:template-part {"slug":"header","theme":"{$theme}"} /-->
<!-- wp:group {"tagName":"main","style":{"spacing":{"margin":{"top":"var:preset|spacing|60"}}},"layout":{"type":"constrained"}} -->
<main class="wp-block-group" style="margin-top:var(--wp--preset--spacing--60)"><!-- wp:query-title {"type":"search","align":"wide","fontSize":"x-large"} /-->
<!-- wp:spacer {"height":"var:preset|spacing|40"} -->
<div style="height:var(--wp--preset--spacing--40)" aria-hidden="true" class="wp-block-spacer"></div>
<!-- /wp:spacer -->
<!-- wp:query {"queryId":74,"query":{"perPage":12,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":true,"taxQuery":null,"parents":[]},"align":"wide","layout":{"type":"default"}} -->
<div class="wp-block-query alignwide"><!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group"><!-- wp:query-no-results {"align":"wide","fontSize":"medium"} -->
<!-- wp:paragraph -->
<p>Lo siento, no se ha encontrado nada. Por favor, prueba a buscar con otras palabras clave.</p>
<!-- /wp:paragraph -->
<!-- /wp:query-no-results --></div>
<!-- /wp:group -->
<!-- wp:post-template {"align":"wide","className":"fea-archive-grid","style":{"spacing":{"blockGap":"1.5rem"}},"layout":{"type":"grid","columnCount":3}} -->
<!-- wp:group {"className":"fea-archive-card","layout":{"type":"constrained"}} -->
<div class="wp-block-group fea-archive-card"><!-- wp:post-title {"isLink":true,"className":"fea-archive-title","fontSize":"medium"} /-->
<!-- wp:post-date {"isLink":true,"className":"fea-archive-date","fontSize":"small"} /-->
<!-- wp:post-excerpt {"showMoreOnNewLine":false,"excerptLength":22,"className":"fea-archive-excerpt"} /--></div>
<!-- /wp:group -->
<!-- /wp:post-template -->
<!-- wp:spacer {"height":"var:preset|spacing|30"} -->
<div style="height:var(--wp--preset--spacing--30)" aria-hidden="true" class="wp-block-spacer"></div>
<!-- /wp:spacer -->
<!-- wp:group {"align":"full","style":{"spacing":{"margin":{"top":"var:preset|spacing|40","bottom":"var:preset|spacing|40"}}},"layout":{"type":"constrained"}} -->
<div class="wp-block-group alignfull" style="margin-top:var(--wp--preset--spacing--40);margin-bottom:var(--wp--preset--spacing--40)"><!-- wp:query-pagination {"align":"full","style":{"typography":{"fontStyle":"normal","fontWeight":"400"}},"layout":{"type":"flex","justifyContent":"space-between","flexWrap":"wrap"}} -->
<!-- wp:query-pagination-previous /-->
<!-- wp:query-pagination-numbers /-->
<!-- wp:query-pagination-next /-->
<!-- /wp:query-pagination --></div>
<!-- /wp:group --></div>
<!-- /wp:query --></main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","theme":"{$theme}"} /-->
HTML;
$existing = get_posts(['post_type' => 'wp_template', 'name' => 'search', 'post_status' => 'any', 'posts_per_page' => 1]);
if ($existing) {
$id = $existing[0]->ID;
echo "Template 'search' existe (post $id) → " . ($apply ? "actualizando" : "[dry] actualizaría") . "\n";
if ($apply) wp_update_post(['ID' => $id, 'post_content' => $content]);
} else {
echo ($apply ? "Creando" : "[dry] crearía") . " wp_template 'search' (theme $theme)\n";
if ($apply) {
$id = wp_insert_post([
'post_type' => 'wp_template',
'post_status' => 'publish',
'post_name' => 'search',
'post_title' => 'Search Results',
'post_content' => $content,
], true);
if (is_wp_error($id)) { echo "ERROR: " . $id->get_error_message() . "\n"; return; }
wp_set_object_terms($id, $theme, 'wp_theme');
echo " creado post $id\n";
}
}
if (function_exists('wp_cache_flush')) wp_cache_flush();
echo ($apply ? "APLICADO" : "DRY-RUN") . "\n";
@@ -0,0 +1,61 @@
<?php
/**
* Plugin Name: Fe Adulta — Buscador visible (#8, MVP nativo)
* Description: Inyecta una barra de búsqueda visible bajo la cabecera (template part
* FSE 'header'), usando el buscador nativo de WordPress (/?s=). Multiidioma:
* el form apunta a la home del idioma actual (Polylang filtra por idioma).
* Fase 2: sustituir el motor por Typesense (self-host) manteniendo esta UI.
* Version: 1.0
*/
if (!defined('ABSPATH')) exit;
/** HTML del formulario de búsqueda (home del idioma actual como action). */
function fea_search_form_html(): string {
// Raíz del idioma actual (Polylang) para que /?s= busque en ese idioma:
// ES (idioma por defecto) → /; EN/FR/IT/PT → /<lang>/.
$base = home_url('/');
if (function_exists('pll_current_language')) {
$lang = pll_current_language();
$default = function_exists('pll_default_language') ? pll_default_language() : 'es';
if ($lang && $lang !== $default) $base = home_url('/' . $lang . '/');
}
$action = esc_url($base);
$q = esc_attr(get_search_query());
$ph = esc_attr__('Buscar reflexiones, artículos, autores…', 'default');
$svg = '<svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true" focusable="false">'
. '<path fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 1 0-.7.7l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0A4.5 4.5 0 1 1 14 9.5 4.5 4.5 0 0 1 9.5 14z"/></svg>';
return '<div class="fea-search-bar"><form role="search" method="get" class="fea-search" action="' . $action . '">'
. '<input type="search" name="s" value="' . $q . '" placeholder="' . $ph . '" aria-label="Buscar">'
. '<button type="submit" aria-label="Buscar">' . $svg . '</button>'
. '</form></div>';
}
/** Inyecta la barra al final del template part 'header'. */
add_filter('render_block', function ($html, $block) {
if (is_admin()) return $html;
if (($block['blockName'] ?? '') !== 'core/template-part') return $html;
// El home usa el part 'cabecera-portada'; el resto del sitio usa 'header'.
if (!in_array($block['attrs']['slug'] ?? '', ['header', 'cabecera-portada'], true)) return $html;
return $html . fea_search_form_html();
}, 20, 2);
add_action('wp_head', function () {
?>
<style>
/* En desktop se usa el buscador del menú; esta barra es para móvil, donde el
menú colapsa en hamburguesa y el buscador del menú queda oculto (#8). */
.fea-search-bar{display:none;justify-content:center;padding:.5rem 1rem;
background:#faf6f7;border-top:1px solid #efe2e5;border-bottom:1px solid #efe2e5}
@media(max-width:600px){.fea-search-bar{display:flex}}
.fea-search{display:flex;align-items:center;width:100%;max-width:560px;
background:#fff;border:1px solid #d9c4c9;border-radius:999px;overflow:hidden}
.fea-search input[type=search]{flex:1 1 auto;border:0;outline:0;background:transparent;
font-size:.95rem;padding:.55rem .9rem;color:#222}
.fea-search input[type=search]::placeholder{color:#9a8a8e}
.fea-search button{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
border:0;cursor:pointer;background:#8b1a2e;color:#fff;width:42px;align-self:stretch}
.fea-search button:hover{background:#6f1525}
@media(max-width:600px){.fea-search-bar{padding:.45rem .6rem}}
</style>
<?php
});