668d973889
Incluye: mu-plugins custom (fea-homepage, carta-semana), scripts de migración/traducción/deploy, documentación de auditoría, análisis de cartas y HTML de evangelios exportados desde Joomla. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1497 lines
59 KiB
PHP
1497 lines
59 KiB
PHP
<?php
|
||
/**
|
||
* Plugin Name: Fe Adulta — Homepage
|
||
* Description: Portada con selección editorial via ACF.
|
||
* Version: 1.4
|
||
*/
|
||
|
||
// ── Flush rewrite rules una sola vez tras cambios de configuración ────────
|
||
add_action('init', function() {
|
||
if (get_option('fea_flush_needed')) {
|
||
flush_rewrite_rules(true);
|
||
delete_option('fea_flush_needed');
|
||
}
|
||
});
|
||
|
||
// ── Portada multilingüe: sirve la página traducida en el home de cada idioma ──
|
||
// Polylang free no traduce page_on_front automáticamente.
|
||
// Este hook intercepta el query del home de idioma y carga la página correcta.
|
||
add_action('pre_get_posts', function(WP_Query $query) {
|
||
if (!$query->is_main_query()) return;
|
||
if (!function_exists('pll_current_language') || !function_exists('pll_get_post')) return;
|
||
|
||
// Solo actuar cuando WP cree que está en el home/front page
|
||
if (!$query->is_home() && !$query->is_front_page()) return;
|
||
|
||
$lang = pll_current_language();
|
||
if (!$lang || $lang === 'es') return;
|
||
|
||
$translated_id = pll_get_post(26542, $lang);
|
||
if (!$translated_id) return;
|
||
|
||
// Forzar carga de la página traducida como si fuera la portada estática
|
||
$query->set('page_id', $translated_id);
|
||
$query->set('post_type', 'page');
|
||
$query->is_home = false;
|
||
$query->is_front_page = true;
|
||
$query->is_singular = true;
|
||
$query->is_page = true;
|
||
}, 1);
|
||
|
||
// Asegura que option_page_on_front devuelve la página traducida al idioma actual
|
||
// (necesario para is_front_page() y para que el template FSE lo reconozca)
|
||
add_filter('option_page_on_front', function($value) {
|
||
if (!function_exists('pll_current_language') || !function_exists('pll_get_post')) return $value;
|
||
static $running = false;
|
||
if ($running) return $value; // evitar recursión
|
||
$running = true;
|
||
$lang = pll_current_language();
|
||
$running = false;
|
||
if (!$lang || $lang === 'es') return $value;
|
||
$translated = pll_get_post((int) $value, $lang);
|
||
return $translated ?: $value;
|
||
});
|
||
|
||
// ── Traducir links de categoría "Esta semana" / "Semana pasada" al idioma actual ─
|
||
// Las categorías traducidas EN/FR/IT/PT dan 404 (bug WP_Tax_Query AND 0=1 con Polylang).
|
||
// Solución: redirigir ES cat URL → post traducido directamente (no a la categoría).
|
||
// Para "Otras semanas" (cartas-de-otras-semanas, count=729): se deja como está.
|
||
add_action('wp_footer', function() {
|
||
if (!function_exists('pll_current_language') || !function_exists('pll_get_post')) return;
|
||
$lang = pll_current_language();
|
||
if (!$lang || $lang === 'es') return;
|
||
|
||
global $wpdb;
|
||
$map = [];
|
||
|
||
// Categorías de carta única (count=1) → redirigir al post traducido
|
||
$single_carta_cats = [
|
||
'cartasemana' => 6,
|
||
'carta-semana-pasada' => 22,
|
||
];
|
||
foreach ($single_carta_cats as $slug => $es_cat_id) {
|
||
// term_taxonomy_id de la categoría ES (bypassa Polylang)
|
||
$tt_id = (int) $wpdb->get_var($wpdb->prepare(
|
||
"SELECT term_taxonomy_id FROM {$wpdb->term_taxonomy}
|
||
WHERE term_id=%d AND taxonomy='category'", $es_cat_id
|
||
));
|
||
if (!$tt_id) continue;
|
||
// Post ES más reciente en esa categoría
|
||
$es_post_id = (int) $wpdb->get_var($wpdb->prepare(
|
||
"SELECT p.ID FROM {$wpdb->posts} p
|
||
JOIN {$wpdb->term_relationships} tr ON p.ID=tr.object_id
|
||
WHERE tr.term_taxonomy_id=%d AND p.post_status='publish'
|
||
ORDER BY p.post_date DESC LIMIT 1", $tt_id
|
||
));
|
||
if (!$es_post_id) continue;
|
||
// Post traducido
|
||
$trans_id = pll_get_post($es_post_id, $lang);
|
||
if (!$trans_id) continue;
|
||
$trans_url = get_permalink($trans_id);
|
||
if ($trans_url) {
|
||
$map[home_url('/category/' . $slug . '/')] = $trans_url;
|
||
}
|
||
}
|
||
if (empty($map)) return;
|
||
?>
|
||
<script>
|
||
(function(){
|
||
var map = <?php echo json_encode($map); ?>;
|
||
document.querySelectorAll('a[href]').forEach(function(a){
|
||
var clean = a.href.split('?')[0];
|
||
if (map[clean]) a.href = map[clean];
|
||
});
|
||
})();
|
||
</script>
|
||
<?php
|
||
}, 25);
|
||
|
||
// ── Foto de perfil de autor via ACF (campo en perfil de usuario) ──────────
|
||
add_action('acf/init', function() {
|
||
if (!function_exists('acf_add_local_field_group')) return;
|
||
acf_add_local_field_group([
|
||
'key' => 'group_user_foto_perfil',
|
||
'title' => 'Foto de perfil',
|
||
'fields' => [[
|
||
'key' => 'field_user_foto_perfil',
|
||
'label' => 'Foto',
|
||
'name' => 'foto_perfil',
|
||
'type' => 'image',
|
||
'instructions' => 'Sube una foto cuadrada del autor (mínimo 100×100px).',
|
||
'return_format' => 'url',
|
||
'preview_size' => 'thumbnail',
|
||
'upload_folder' => 'autores',
|
||
]],
|
||
'location' => [[
|
||
['param' => 'user_form', 'operator' => '==', 'value' => 'all'],
|
||
]],
|
||
]);
|
||
});
|
||
|
||
// Usar la foto del autor en lugar del Gravatar cuando existe
|
||
// Lee el attachment ID guardado en el meta 'foto_perfil' (campo ACF)
|
||
add_filter('get_avatar_url', function($url, $id_or_email, $args) {
|
||
$user_id = null;
|
||
if (is_numeric($id_or_email)) $user_id = (int) $id_or_email;
|
||
elseif ($id_or_email instanceof WP_User) $user_id = $id_or_email->ID;
|
||
elseif (is_string($id_or_email)) {
|
||
$user = get_user_by('email', $id_or_email);
|
||
if ($user) $user_id = $user->ID;
|
||
}
|
||
if (!$user_id) return $url;
|
||
$attach_id = get_user_meta($user_id, 'foto_perfil', true);
|
||
if ($attach_id) {
|
||
$foto = wp_get_attachment_image_url((int) $attach_id, 'full');
|
||
if ($foto) return $foto;
|
||
}
|
||
return $url;
|
||
}, 10, 3);
|
||
|
||
// ── Ordenar por fecha los resultados del buscador ACF en campos de portada ─
|
||
add_filter('acf/fields/relationship/query/key=field_portada_articulos', function($args) {
|
||
$args['orderby'] = 'date';
|
||
$args['order'] = 'DESC';
|
||
return $args;
|
||
});
|
||
add_filter('acf/fields/relationship/query/key=field_portada_multimedia', function($args) {
|
||
$args['orderby'] = 'date';
|
||
$args['order'] = 'DESC';
|
||
return $args;
|
||
});
|
||
|
||
// ── Campos ACF para la portada ────────────────────────────────────────────
|
||
add_action('acf/init', function() {
|
||
if (!function_exists('acf_add_local_field_group')) return;
|
||
|
||
$front_page_id = (int) get_option('page_on_front');
|
||
|
||
acf_add_local_field_group([
|
||
'key' => 'group_portada_fea',
|
||
'title' => 'Contenido de la portada',
|
||
'fields' => [
|
||
[
|
||
'key' => 'field_portada_articulos',
|
||
'label' => 'Artículos seleccionados',
|
||
'name' => 'portada_articulos',
|
||
'type' => 'relationship',
|
||
'instructions' => 'Elige los artículos que aparecerán en la portada esta semana (máx. 9). Puedes buscar por título.',
|
||
'post_type' => ['post'],
|
||
'post_status' => ['publish', 'draft'],
|
||
'filters' => ['search', 'taxonomy'],
|
||
'elements' => ['featured_image'],
|
||
'min' => 0,
|
||
'max' => 9,
|
||
'return_format' => 'object',
|
||
'query_args' => ['orderby' => 'date', 'order' => 'DESC'],
|
||
],
|
||
[
|
||
'key' => 'field_portada_multimedia',
|
||
'label' => 'Multimedia seleccionado',
|
||
'name' => 'portada_multimedia',
|
||
'type' => 'relationship',
|
||
'instructions' => 'Elige los vídeos o audios para la portada (máx. 4).',
|
||
'post_type' => ['post'],
|
||
'post_status' => ['publish', 'draft'],
|
||
'filters' => ['search'],
|
||
'elements' => ['featured_image'],
|
||
'min' => 0,
|
||
'max' => 4,
|
||
'return_format' => 'object',
|
||
'query_args' => ['orderby' => 'date', 'order' => 'DESC'],
|
||
],
|
||
],
|
||
'location' => [[
|
||
['param' => 'page', 'operator' => '==', 'value' => (string) $front_page_id],
|
||
]],
|
||
'position' => 'normal',
|
||
'style' => 'default',
|
||
'label_placement' => 'top',
|
||
]);
|
||
});
|
||
|
||
// ── Selector de idioma (dropdown con bandera + 2 letras) ─────────────────
|
||
add_action('wp_head', function() {
|
||
if (!function_exists('pll_the_languages')) return;
|
||
?>
|
||
<style>
|
||
#fea-lang-switcher {
|
||
position: relative;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
font-family: inherit;
|
||
z-index: 9999;
|
||
}
|
||
#fea-lang-btn {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
background: none;
|
||
border: 1px solid rgba(0,0,0,0.25);
|
||
border-radius: 5px;
|
||
padding: 4px 9px;
|
||
cursor: pointer;
|
||
font-size: 0.82rem;
|
||
font-weight: 700;
|
||
color: inherit;
|
||
line-height: 1.4;
|
||
white-space: nowrap;
|
||
}
|
||
#fea-lang-btn:hover { background: rgba(0,0,0,0.06); }
|
||
#fea-lang-btn .arrow { font-size: 0.6rem; opacity: 0.6; }
|
||
#fea-lang-dropdown {
|
||
display: none;
|
||
position: absolute;
|
||
top: calc(100% + 4px);
|
||
right: 0;
|
||
background: #fff;
|
||
border: 1px solid #ddd;
|
||
border-radius: 7px;
|
||
box-shadow: 0 6px 16px rgba(0,0,0,0.13);
|
||
min-width: 90px;
|
||
padding: 4px 0;
|
||
list-style: none;
|
||
margin: 0;
|
||
}
|
||
#fea-lang-switcher.open #fea-lang-dropdown { display: block; }
|
||
#fea-lang-dropdown li { margin: 0; padding: 0; }
|
||
#fea-lang-dropdown a {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 7px;
|
||
padding: 7px 14px;
|
||
font-size: 0.82rem;
|
||
font-weight: 600;
|
||
text-decoration: none;
|
||
color: #222;
|
||
white-space: nowrap;
|
||
}
|
||
#fea-lang-dropdown a:hover { background: #f5f5f5; }
|
||
#fea-lang-dropdown a[aria-current] { font-weight: 700; color: #000; background: #efefef; }
|
||
</style>
|
||
<?php
|
||
});
|
||
|
||
add_action('wp_footer', function() {
|
||
if (!function_exists('pll_the_languages')) return;
|
||
|
||
$flags = ['es' => '🇪🇸', 'en' => '🇬🇧', 'fr' => '🇫🇷', 'it' => '🇮🇹', 'pt' => '🇵🇹'];
|
||
|
||
$langs = pll_the_languages(['raw' => 1, 'hide_if_no_translation' => 0]);
|
||
if (!$langs) return;
|
||
|
||
$current = array_filter($langs, fn($l) => $l['current_lang']);
|
||
$current = $current ? array_values($current)[0] : null;
|
||
$cur_slug = $current ? $current['slug'] : 'es';
|
||
$cur_flag = $flags[$cur_slug] ?? '🌐';
|
||
$cur_code = strtoupper($cur_slug);
|
||
|
||
$items = '';
|
||
foreach ($langs as $l) {
|
||
$flag = $flags[$l['slug']] ?? '🌐';
|
||
$code = strtoupper($l['slug']);
|
||
$cur = $l['current_lang'] ? ' aria-current="true"' : '';
|
||
$items .= '<li><a href="' . esc_url($l['url']) . '"' . $cur . '>' . $flag . ' ' . $code . '</a></li>';
|
||
}
|
||
?>
|
||
<div id="fea-lang-switcher" role="navigation" aria-label="Idioma / Language">
|
||
<button id="fea-lang-btn" aria-haspopup="listbox" aria-expanded="false"
|
||
onclick="var s=this.closest('#fea-lang-switcher'),o=s.classList.toggle('open');this.setAttribute('aria-expanded',o)">
|
||
<?= $cur_flag ?> <?= $cur_code ?> <span class="arrow">▼</span>
|
||
</button>
|
||
<ul id="fea-lang-dropdown" role="listbox"><?= $items ?></ul>
|
||
</div>
|
||
<script>
|
||
(function() {
|
||
var sw = document.getElementById('fea-lang-switcher');
|
||
if (!sw) return;
|
||
// Cerrar al clicar fuera
|
||
document.addEventListener('click', function(e) {
|
||
if (!sw.contains(e.target)) {
|
||
sw.classList.remove('open');
|
||
document.getElementById('fea-lang-btn').setAttribute('aria-expanded', 'false');
|
||
}
|
||
});
|
||
// Inyectar en el nav principal del header
|
||
function inject() {
|
||
// Buscar la barra de navegación principal (primer nivel dentro del header)
|
||
var header = document.querySelector('header.wp-block-template-part');
|
||
if (!header) header = document.querySelector('header');
|
||
if (!header) return;
|
||
// Buscar el div/group que contiene el menú de navegación
|
||
var navGroup = header.querySelector('.wp-block-navigation__container');
|
||
if (!navGroup) navGroup = header.querySelector('nav');
|
||
if (!navGroup) {
|
||
// Fallback: poner en el header con posición absoluta
|
||
header.style.position = 'relative';
|
||
sw.style.cssText = 'position:absolute;top:50%;right:1.5rem;transform:translateY(-50%);';
|
||
header.appendChild(sw);
|
||
return;
|
||
}
|
||
// Crear li wrapper para el nav
|
||
var li = document.createElement('li');
|
||
li.className = 'wp-block-navigation-item';
|
||
li.style.cssText = 'display:flex;align-items:center;margin-left:0.5rem;';
|
||
li.appendChild(sw);
|
||
// Insertar DESPUÉS del buscador (si existe)
|
||
var searchItem = navGroup.querySelector('.wp-block-search');
|
||
if (searchItem) {
|
||
// Subir hasta el li/div hermano directo del navGroup
|
||
var anchor = searchItem;
|
||
while (anchor.parentNode && anchor.parentNode !== navGroup) {
|
||
anchor = anchor.parentNode;
|
||
}
|
||
anchor.parentNode.insertBefore(li, anchor.nextSibling);
|
||
} else {
|
||
navGroup.appendChild(li);
|
||
}
|
||
}
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', inject);
|
||
} else {
|
||
inject();
|
||
}
|
||
})();
|
||
</script>
|
||
<?php
|
||
}, 20);
|
||
|
||
// ── Centrar bloque slider+librería (header template, todas las páginas) ───
|
||
add_action('wp_head', function() {
|
||
?>
|
||
<style>
|
||
/* El bloque de columnas con el slider usa márgenes negativos del FSE
|
||
que lo desplazan. Lo forzamos a centrar con max-width explícito. */
|
||
.wp-block-columns:has(.wp-block-nextend-smartslider3) {
|
||
max-width: min(var(--wp--style--global--wide-size, 1340px), 100%);
|
||
margin-left: auto !important;
|
||
margin-right: auto !important;
|
||
box-sizing: border-box;
|
||
padding-left: var(--wp--preset--spacing--30);
|
||
padding-right: var(--wp--preset--spacing--30);
|
||
}
|
||
|
||
/* Ocultar columna librería en tablet */
|
||
@media (max-width: 900px) {
|
||
.fea-slider-block .wp-block-column:last-child {
|
||
display: none !important;
|
||
}
|
||
}
|
||
|
||
/* Ocultar slider en móvil (banner superior sigue visible) */
|
||
@media (max-width: 600px) {
|
||
.fea-slider-block {
|
||
display: none !important;
|
||
}
|
||
}
|
||
|
||
/* Buscador del header: reducir altura */
|
||
.wp-block-search__input {
|
||
padding-top: 0.25rem !important;
|
||
padding-bottom: 0.25rem !important;
|
||
line-height: 1.3 !important;
|
||
}
|
||
.wp-block-search__button {
|
||
padding-top: 0.25rem !important;
|
||
padding-bottom: 0.25rem !important;
|
||
}
|
||
</style>
|
||
<?php
|
||
});
|
||
|
||
// ── Estilos ───────────────────────────────────────────────────────────────
|
||
add_action('wp_head', function() {
|
||
if (!fea_is_front_page()) return;
|
||
?>
|
||
<style>
|
||
.fea-hero { border-bottom: 2px solid #111; padding-bottom: 2rem; margin-bottom: 2.5rem; }
|
||
.fea-hero-link { display: block; text-decoration: none; color: inherit; }
|
||
.fea-hero-link:hover .fea-hero-title { text-decoration: underline; text-underline-offset: 4px; }
|
||
.fea-section-label { display: inline-block; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: #888; margin-bottom: 0.6rem; }
|
||
.fea-hero-title { font-size: clamp(1.5rem, 4vw, 2.2rem); font-weight: 700; line-height: 1.2; margin: 0 0 0.75rem; color: #111; }
|
||
.fea-hero-meta { display: flex; align-items: center; gap: 0.5rem; font-size: 0.875rem; color: #666; }
|
||
|
||
.fea-section { margin-bottom: 3rem; }
|
||
.fea-section-title { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: #888; margin: 0 0 1.25rem; padding-bottom: 0.5rem; border-bottom: 1px solid #e0e0e0; }
|
||
|
||
.fea-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
|
||
@media (max-width: 720px) { .fea-grid { grid-template-columns: 1fr 1fr; } }
|
||
@media (max-width: 480px) { .fea-grid { grid-template-columns: 1fr; } }
|
||
|
||
.fea-card { border-bottom: 1px solid #e5e5e5; padding-bottom: 1.1rem; }
|
||
.fea-card-meta { display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.4rem; }
|
||
.fea-avatar { border-radius: 50%; width: 28px !important; height: 28px !important; flex-shrink: 0; display: inline-block !important; }
|
||
.fea-card-author { font-size: 0.78rem; font-weight: 600; color: #555; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.fea-card-title { font-size: 0.93rem; font-weight: 600; line-height: 1.35; margin: 0; }
|
||
.fea-card-title a { text-decoration: none; color: #111; }
|
||
.fea-card-title a:hover { text-decoration: underline; text-underline-offset: 3px; }
|
||
</style>
|
||
<?php
|
||
});
|
||
|
||
|
||
// ── Ocultar título de página en portadas traducidas ───────────────────────
|
||
// La portada ES usa plantilla-portada que ya oculta el título.
|
||
// Las portadas FR/IT/PT/EN usan la plantilla default que sí lo muestra.
|
||
add_action('wp_head', function() {
|
||
$id = get_queried_object_id();
|
||
$translated_ids = [42756, 42757, 42758, 43889]; // FR, IT, PT, EN
|
||
if (!$id || !in_array($id, $translated_ids, true)) return;
|
||
echo '<style>.wp-block-post-title { display:none !important; }</style>';
|
||
}, 20);
|
||
|
||
// ── Byline personalizado en artículos individuales ────────────────────────
|
||
|
||
// ── Byline personalizado: se gestiona desde el template FSE (ID 42359) ────
|
||
// El template wp_template 'single' ya contiene wp:avatar + wp:post-author-name
|
||
// + wp:post-terms. Este hook solo añade los estilos necesarios.
|
||
add_action('astra_single_header_bottom', function() {
|
||
if (!is_single()) return;
|
||
|
||
$author_id = (int) get_the_author_meta('ID');
|
||
$author_name = get_the_author_meta('display_name');
|
||
$avatar_url = get_avatar_url($author_id, ['size' => 48]);
|
||
$author_url = get_author_posts_url($author_id);
|
||
|
||
$cat_str = '';
|
||
$cats = get_the_category();
|
||
if ($cats) {
|
||
$cat_url = get_category_link($cats[0]->term_id);
|
||
$cat_str = '<a href="' . esc_url($cat_url) . '" class="fea-byline-cat">'
|
||
. esc_html($cats[0]->name) . '</a>';
|
||
}
|
||
|
||
echo '<div class="fea-byline">'
|
||
. '<a href="' . esc_url($author_url) . '" class="fea-byline-avatar-link">'
|
||
. '<img src="' . esc_url($avatar_url) . '" alt="" width="48" height="48" class="fea-byline-avatar">'
|
||
. '</a>'
|
||
. '<div class="fea-byline-info">'
|
||
. '<a href="' . esc_url($author_url) . '" class="fea-byline-name">' . esc_html($author_name) . '</a>'
|
||
. $cat_str
|
||
. '</div>'
|
||
. '</div>';
|
||
});
|
||
|
||
add_action('wp_head', function() {
|
||
if (!is_single()) return;
|
||
?>
|
||
<style>
|
||
.fea-byline { display: flex; align-items: center; gap: 0.75rem; margin-top: 0.75rem; }
|
||
.fea-byline-avatar-link { flex-shrink: 0; }
|
||
.fea-byline-avatar { border-radius: 50%; display: block; }
|
||
.fea-byline-info { display: flex; flex-direction: column; gap: 0.2rem; }
|
||
.fea-byline-name { font-size: 0.9rem; font-weight: 600; color: #222; text-decoration: none; }
|
||
.fea-byline-name:hover { text-decoration: underline; }
|
||
.fea-byline-cat { font-size: 0.78rem; color: #888; text-decoration: none; }
|
||
.fea-byline-cat:hover { text-decoration: underline; color: #555; }
|
||
</style>
|
||
<?php
|
||
});
|
||
|
||
// ── Helpers ───────────────────────────────────────────────────────────────
|
||
function fea_title(string $title): string {
|
||
$lower = mb_strtolower($title, 'UTF-8');
|
||
return mb_strtoupper(mb_substr($lower, 0, 1, 'UTF-8'), 'UTF-8') . mb_substr($lower, 1, null, 'UTF-8');
|
||
}
|
||
|
||
function fea_card(object $post): string {
|
||
$author_id = $post->post_author;
|
||
$author_name = get_the_author_meta('display_name', $author_id);
|
||
$avatar_url = get_avatar_url($author_id, ['size' => 40, 'default' => 'identicon']);
|
||
$url = get_permalink($post->ID);
|
||
$title = fea_title($post->post_title);
|
||
return '<article class="fea-card">'
|
||
. '<div class="fea-card-meta">'
|
||
. '<img src="' . esc_url($avatar_url) . '" alt="" width="28" height="28" class="fea-avatar" loading="lazy">'
|
||
. '<span class="fea-card-author">' . esc_html($author_name) . '</span>'
|
||
. '</div>'
|
||
. '<h3 class="fea-card-title"><a href="' . esc_url($url) . '">' . esc_html($title) . '</a></h3>'
|
||
. '</article>';
|
||
}
|
||
|
||
/** IDs de las páginas de portada en todos los idiomas. */
|
||
function fea_front_page_ids(): array {
|
||
return [26542, 42756, 42757, 42758, 43889]; // ES, FR, IT, PT, EN
|
||
}
|
||
|
||
/** True si la página actual es alguna de las portadas (multilingüe). */
|
||
function fea_is_front_page(): bool {
|
||
if (is_front_page()) return true;
|
||
$id = get_queried_object_id();
|
||
return $id && in_array($id, fea_front_page_ids(), true);
|
||
}
|
||
|
||
/** Devuelve el idioma actual de Polylang, o 'es' si no está activo. */
|
||
function fea_current_lang(): string {
|
||
return (function_exists('pll_current_language') ? pll_current_language() : null) ?: 'es';
|
||
}
|
||
|
||
/** Etiquetas de sección traducidas por idioma. */
|
||
function fea_labels(): array {
|
||
$all = [
|
||
'es' => [
|
||
'carta' => 'Carta de la semana',
|
||
'evangelio' => 'Comentarios al evangelio',
|
||
'articulos' => 'Artículos de esta semana',
|
||
'eucaristia' => 'Para una eucaristía más participativa',
|
||
'multimedia' => 'Multimedia',
|
||
],
|
||
'en' => [
|
||
'carta' => 'Letter of the week',
|
||
'evangelio' => 'Gospel commentary',
|
||
'articulos' => 'Articles of the week',
|
||
'eucaristia' => 'For a more participatory Eucharist',
|
||
'multimedia' => 'Multimedia',
|
||
],
|
||
'fr' => [
|
||
'carta' => 'Lettre de la semaine',
|
||
'evangelio' => 'Commentaires de l\'évangile',
|
||
'articulos' => 'Articles de la semaine',
|
||
'eucaristia' => 'Pour une eucharistie plus participative',
|
||
'multimedia' => 'Multimédia',
|
||
],
|
||
'it' => [
|
||
'carta' => 'Lettera della settimana',
|
||
'evangelio' => 'Commenti al vangelo',
|
||
'articulos' => 'Articoli della settimana',
|
||
'eucaristia' => 'Per una eucaristia più partecipativa',
|
||
'multimedia' => 'Multimedia',
|
||
],
|
||
'pt' => [
|
||
'carta' => 'Carta da semana',
|
||
'evangelio' => 'Comentários ao evangelho',
|
||
'articulos' => 'Artigos da semana',
|
||
'eucaristia' => 'Para uma eucaristia mais participativa',
|
||
'multimedia' => 'Multimédia',
|
||
],
|
||
];
|
||
return $all[fea_current_lang()] ?? $all['es'];
|
||
}
|
||
|
||
/**
|
||
* ID de la página de portada para el idioma actual.
|
||
*/
|
||
function fea_front_page_id(): int {
|
||
$es_front = 26542;
|
||
$lang = fea_current_lang();
|
||
if ($lang === 'es') return $es_front;
|
||
if (function_exists('pll_get_post')) {
|
||
$translated = pll_get_post($es_front, $lang);
|
||
if ($translated) return (int) $translated;
|
||
}
|
||
return $es_front;
|
||
}
|
||
|
||
/**
|
||
* Traduce un term_id de categoría ES al idioma actual.
|
||
* Si no hay traducción disponible, devuelve el ID original.
|
||
*/
|
||
function fea_cat(int $es_cat_id): int {
|
||
$lang = fea_current_lang();
|
||
if ($lang === 'es') return $es_cat_id;
|
||
if (function_exists('pll_get_term')) {
|
||
$translated = pll_get_term($es_cat_id, $lang);
|
||
if ($translated) return (int) $translated;
|
||
}
|
||
return $es_cat_id;
|
||
}
|
||
|
||
// ── Shortcode: [fea_carta_semana_hero] ────────────────────────────────────
|
||
add_shortcode('fea_carta_semana_hero', function() {
|
||
$lang = fea_current_lang();
|
||
$labels = fea_labels();
|
||
|
||
$cartas = get_posts([
|
||
'posts_per_page' => 1,
|
||
'category__in' => [fea_cat(6)],
|
||
'post_status' => 'publish',
|
||
'orderby' => 'date',
|
||
'order' => 'DESC',
|
||
]);
|
||
if (!$cartas) return '';
|
||
|
||
$c = $cartas[0];
|
||
$url = get_permalink($c->ID);
|
||
$fecha = date_i18n('j F Y', strtotime($c->post_date));
|
||
$author_name = get_the_author_meta('display_name', $c->post_author);
|
||
$avatar_url = get_avatar_url($c->post_author, ['size' => 32, 'default' => 'identicon']);
|
||
|
||
return '<section class="fea-hero">'
|
||
. '<a href="' . esc_url($url) . '" class="fea-hero-link">'
|
||
. '<span class="fea-section-label">' . esc_html($labels['carta']) . '</span>'
|
||
. '<h2 class="fea-hero-title">' . esc_html(fea_title($c->post_title)) . '</h2>'
|
||
. '<div class="fea-hero-meta">'
|
||
. '<img src="' . esc_url($avatar_url) . '" alt="" width="32" height="32" class="fea-avatar">'
|
||
. '<span>' . esc_html($author_name) . ' · ' . $fecha . '</span>'
|
||
. '</div>'
|
||
. '</a></section>';
|
||
});
|
||
|
||
// ── Shortcode: [fea_articulos_semana] ─────────────────────────────────────
|
||
add_shortcode('fea_articulos_semana', function($atts) {
|
||
$lang = fea_current_lang();
|
||
$labels = fea_labels();
|
||
$atts = shortcode_atts(['titulo' => $labels['articulos']], $atts);
|
||
$page = fea_front_page_id();
|
||
|
||
// Selección editorial ACF (solo para ES; otros idiomas usan fallback)
|
||
$posts = [];
|
||
if ($lang === 'es' && function_exists('get_field')) {
|
||
$seleccion = get_field('portada_articulos', $page) ?: [];
|
||
foreach ($seleccion as $p) {
|
||
if ($p->post_status === 'publish') $posts[] = $p;
|
||
}
|
||
}
|
||
|
||
// Fallback: últimos artículos en el idioma actual
|
||
if (empty($posts)) {
|
||
$posts = get_posts([
|
||
'posts_per_page' => 9,
|
||
'category__in' => [fea_cat(1650)],
|
||
'category__not_in' => array_map('fea_cat', [6, 21, 22, 23, 26, 58, 40, 1645, 1646, 1647, 1648, 1649, 1651, 1652]),
|
||
'post_status' => 'publish',
|
||
'orderby' => 'date',
|
||
'order' => 'DESC',
|
||
]);
|
||
}
|
||
if (!$posts) return '';
|
||
|
||
$html = '<section class="fea-section">'
|
||
. '<h2 class="fea-section-title">' . esc_html($atts['titulo']) . '</h2>'
|
||
. '<div class="fea-grid">';
|
||
foreach ($posts as $post) $html .= fea_card($post);
|
||
return $html . '</div></section>';
|
||
});
|
||
|
||
// ── Shortcode: [fea_evangelio] ────────────────────────────────────────────
|
||
// Editorial (cat 1646) primero, luego comentarios (cat 1647). Máx 7 en total.
|
||
add_shortcode('fea_evangelio', function($atts) {
|
||
$lang = fea_current_lang();
|
||
$labels = fea_labels();
|
||
$atts = shortcode_atts(['titulo' => $labels['evangelio']], $atts);
|
||
|
||
$editorial = get_posts([
|
||
'posts_per_page' => 1,
|
||
'category__in' => [fea_cat(1646)],
|
||
'post_status' => 'publish',
|
||
'orderby' => 'date',
|
||
'order' => 'DESC',
|
||
]);
|
||
|
||
$comentarios = get_posts([
|
||
'posts_per_page' => 6,
|
||
'category__in' => [fea_cat(1647)],
|
||
'category__not_in' => [fea_cat(1646)],
|
||
'post_status' => 'publish',
|
||
'orderby' => 'date',
|
||
'order' => 'DESC',
|
||
]);
|
||
|
||
$posts = array_merge($editorial, $comentarios);
|
||
if (!$posts) return '';
|
||
|
||
$html = '<section class="fea-section">'
|
||
. '<h2 class="fea-section-title">' . esc_html($atts['titulo']) . '</h2>'
|
||
. '<div class="fea-grid">';
|
||
foreach ($posts as $post) $html .= fea_card($post);
|
||
return $html . '</div></section>';
|
||
});
|
||
|
||
// ── Shortcode: [fea_eucaristia] ───────────────────────────────────────────
|
||
add_shortcode('fea_eucaristia', function($atts) {
|
||
$lang = fea_current_lang();
|
||
$labels = fea_labels();
|
||
$atts = shortcode_atts(['titulo' => $labels['eucaristia']], $atts);
|
||
|
||
$posts = get_posts([
|
||
'posts_per_page' => 6,
|
||
'category__in' => [fea_cat(1648)],
|
||
'post_status' => 'publish',
|
||
'orderby' => 'date',
|
||
'order' => 'DESC',
|
||
]);
|
||
if (!$posts) return '';
|
||
|
||
$html = '<section class="fea-section">'
|
||
. '<h2 class="fea-section-title">' . esc_html($atts['titulo']) . '</h2>'
|
||
. '<div class="fea-grid">';
|
||
foreach ($posts as $post) $html .= fea_card($post);
|
||
return $html . '</div></section>';
|
||
});
|
||
|
||
// ── Shortcode: [fea_multimedia] ───────────────────────────────────────────
|
||
add_shortcode('fea_multimedia', function($atts) {
|
||
$lang = fea_current_lang();
|
||
$labels = fea_labels();
|
||
$atts = shortcode_atts(['titulo' => $labels['multimedia']], $atts);
|
||
$page = fea_front_page_id();
|
||
|
||
$posts = [];
|
||
if ($lang === 'es' && function_exists('get_field')) {
|
||
$seleccion = get_field('portada_multimedia', $page) ?: [];
|
||
foreach ($seleccion as $p) {
|
||
if ($p->post_status === 'publish') $posts[] = $p;
|
||
}
|
||
}
|
||
|
||
if (empty($posts)) {
|
||
$posts = get_posts([
|
||
'posts_per_page' => 4,
|
||
'category__in' => array_map('fea_cat', [1649, 26, 58]),
|
||
'post_status' => 'publish',
|
||
'orderby' => 'date',
|
||
'order' => 'DESC',
|
||
]);
|
||
}
|
||
if (!$posts) return '';
|
||
|
||
$html = '<section class="fea-section">'
|
||
. '<h2 class="fea-section-title">' . esc_html($atts['titulo']) . '</h2>'
|
||
. '<div class="fea-grid">';
|
||
foreach ($posts as $post) $html .= fea_card($post);
|
||
return $html . '</div></section>';
|
||
});
|
||
|
||
// ── Reescribir links internos al idioma activo (Polylang) ─────────────────
|
||
add_filter('the_content', function($content) {
|
||
if (!function_exists('pll_current_language') || !function_exists('pll_get_post')) return $content;
|
||
$lang = pll_current_language();
|
||
if (!$lang || $lang === 'es') return $content;
|
||
|
||
return preg_replace_callback(
|
||
'/<a\s([^>]*\s)?href=["\']([^"\']+)["\']([^>]*)>/i',
|
||
function($m) use ($lang) {
|
||
$href = $m[2];
|
||
$home = home_url();
|
||
if (strpos($href, $home) === false) return $m[0];
|
||
|
||
$post_id = url_to_postid($href);
|
||
if (!$post_id) return $m[0];
|
||
|
||
$translated_id = pll_get_post($post_id, $lang);
|
||
if (!$translated_id || $translated_id === $post_id) return $m[0];
|
||
|
||
$new_url = get_permalink($translated_id);
|
||
if (!$new_url) return $m[0];
|
||
|
||
return str_replace($href, $new_url, $m[0]);
|
||
},
|
||
$content
|
||
);
|
||
}, 20);
|
||
|
||
// ── Ordenar categoría Evangelios y Comentarios por título ASC ─────────────
|
||
add_action('pre_get_posts', function($query) {
|
||
if ($query->is_main_query() && $query->is_category('evangelios-y-comentarios')) {
|
||
$query->set('orderby', 'title');
|
||
$query->set('order', 'ASC');
|
||
}
|
||
});
|
||
|
||
|
||
// ── Acordeón de versículos en posts de Evangelios y Comentarios ───────────
|
||
add_action('wp_footer', function() {
|
||
if (!is_single()) return;
|
||
global $post;
|
||
if (!has_category('evangelios-y-comentarios', $post)) return;
|
||
?>
|
||
<style>
|
||
.versiculo-group { margin: 0.5em 0; }
|
||
.versiculo-toggle {
|
||
display: flex; align-items: center; gap: 10px;
|
||
cursor: default; margin: 0.8em 0 0;
|
||
}
|
||
.versiculo-toggle .v-icon {
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
width: 22px; height: 22px; min-width: 22px; border-radius: 50%;
|
||
background: #c8860a; color: white; font-size: 18px; line-height: 1;
|
||
cursor: pointer; user-select: none; font-weight: bold;
|
||
transition: background 0.15s;
|
||
}
|
||
.versiculo-group.open .v-icon { background: #6b3080; }
|
||
.v-icon::after { content: '+'; }
|
||
.versiculo-group.open .v-icon::after { content: '\2212'; }
|
||
.versiculo-body { display: none; padding-left: 4px; }
|
||
.versiculo-group.open .versiculo-body { display: block; }
|
||
</style>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
var content = document.querySelector('.wp-block-post-content, .entry-content');
|
||
if (!content) return;
|
||
|
||
var verseRe = /^(JUAN|LUCAS|MARCOS|MATEO)\s+\d/i;
|
||
|
||
function isVerse(el) {
|
||
if (el.tagName !== 'P') return false;
|
||
var links = el.querySelectorAll('a');
|
||
if (links.length !== 1) return false;
|
||
return verseRe.test(el.textContent.trim());
|
||
}
|
||
|
||
var children = Array.from(content.children);
|
||
var i = 0;
|
||
while (i < children.length) {
|
||
var child = children[i];
|
||
if (isVerse(child)) {
|
||
var group = document.createElement('div');
|
||
group.className = 'versiculo-group';
|
||
|
||
var header = document.createElement('div');
|
||
header.className = 'versiculo-toggle';
|
||
|
||
var icon = document.createElement('span');
|
||
icon.className = 'v-icon';
|
||
|
||
var link = child.querySelector('a').cloneNode(true);
|
||
header.appendChild(icon);
|
||
header.appendChild(link);
|
||
group.appendChild(header);
|
||
|
||
var body = document.createElement('div');
|
||
body.className = 'versiculo-body';
|
||
|
||
child.parentNode.insertBefore(group, child);
|
||
child.remove();
|
||
i++;
|
||
|
||
while (i < children.length && !isVerse(children[i])) {
|
||
body.appendChild(children[i]);
|
||
i++;
|
||
}
|
||
|
||
group.appendChild(body);
|
||
|
||
icon.addEventListener('click', function() {
|
||
this.closest('.versiculo-group').classList.toggle('open');
|
||
});
|
||
} else {
|
||
i++;
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
<?php
|
||
}, 30);
|
||
|
||
// ── Avatares en artículos de versículos (Evangelios y Comentarios) ─────────
|
||
add_action('wp_footer', function() {
|
||
if (!is_single()) return;
|
||
global $post, $wpdb;
|
||
if (!has_category('evangelios-y-comentarios', $post)) return;
|
||
|
||
// Extraer todos los slugs de links internos del contenido
|
||
preg_match_all('/<a\s[^>]*href=["\']([^"\']+)["\']/', $post->post_content, $m);
|
||
$slugs = [];
|
||
foreach ($m[1] as $url) {
|
||
$slug = basename(rtrim(parse_url($url, PHP_URL_PATH), '/'));
|
||
if ($slug) {
|
||
$slugs[] = $slug;
|
||
}
|
||
}
|
||
$slugs = array_values(array_unique(array_filter($slugs)));
|
||
if (empty($slugs)) return;
|
||
|
||
// Una sola query: slug → author_id
|
||
$ph = implode(',', array_fill(0, count($slugs), '%s'));
|
||
$rows = $wpdb->get_results(
|
||
$wpdb->prepare(
|
||
"SELECT post_name, post_author FROM {$wpdb->posts}
|
||
WHERE post_name IN ($ph) AND post_status IN ('publish','draft') AND post_type='post'",
|
||
$slugs
|
||
)
|
||
);
|
||
|
||
// Construir mapa slug → avatar_url (reutilizando cache de autor)
|
||
$author_cache = [];
|
||
$avatar_map = [];
|
||
foreach ($rows as $row) {
|
||
$aid = (int) $row->post_author;
|
||
if (!isset($author_cache[$aid])) {
|
||
$user = get_userdata($aid);
|
||
$author_cache[$aid] = ['src' => get_avatar_url($aid, ['size' => 40, 'default' => 'identicon']), 'name' => $user ? $user->display_name : ''];
|
||
}
|
||
if ($author_cache[$aid]) {
|
||
$avatar_map[$row->post_name] = $author_cache[$aid];
|
||
}
|
||
}
|
||
if (empty($avatar_map)) return;
|
||
?>
|
||
<style>
|
||
.versiculo-body ul { padding-left: 0; list-style: none; }
|
||
.versiculo-body li { display: flex; align-items: center; gap: 7px; margin-bottom: 4px; }
|
||
.fea-li-avatar { width: 24px; height: 24px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
|
||
.transl-toggle { font-size: 11px; color: #888; cursor: pointer; margin-left: 6px; user-select: none; white-space: nowrap; flex-shrink: 0; }
|
||
.transl-toggle:hover { color: #777; }
|
||
.transl-block { display: none; margin: 2px 0 6px 32px; font-size: 11px; line-height: 1.8; }
|
||
.transl-block.open { display: block; }
|
||
.transl-block a { color: #aaa; display: block; }
|
||
.transl-block a:hover { color: #555; }
|
||
</style>
|
||
<script>
|
||
(function() {
|
||
var map = <?php echo json_encode($avatar_map); ?>;
|
||
function slug(url) {
|
||
return url.replace(/\/$/, '').split('/').pop().split('?')[0].split('#')[0];
|
||
}
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
document.querySelectorAll('.versiculo-body li').forEach(function(li) {
|
||
var a = li.querySelector('a');
|
||
if (!a) return;
|
||
var entry = map[slug(a.href)];
|
||
if (!entry) return;
|
||
var img = document.createElement('img');
|
||
img.src = entry.src;
|
||
img.title = entry.name;
|
||
img.alt = '';
|
||
img.className = 'fea-li-avatar';
|
||
li.insertBefore(img, li.firstChild);
|
||
});
|
||
|
||
// Colapsar traducciones (p margin-left:90px) bajo "(…)"
|
||
document.querySelectorAll('.versiculo-body').forEach(function(body) {
|
||
Array.from(body.children).forEach(function(el) {
|
||
if (el.tagName !== 'P') return;
|
||
var ml = parseInt(el.style.marginLeft || '0');
|
||
if (ml < 60) return;
|
||
var prev = el.previousElementSibling;
|
||
while (prev && prev.tagName !== 'UL') prev = prev.previousElementSibling;
|
||
if (!prev) return;
|
||
var lis = prev.querySelectorAll('li');
|
||
if (!lis.length) return;
|
||
var lastLi = lis[lis.length - 1];
|
||
el.classList.add('transl-block');
|
||
var btn = document.createElement('span');
|
||
btn.className = 'transl-toggle';
|
||
btn.textContent = 'Otros idiomas (\u2026)';
|
||
lastLi.appendChild(btn);
|
||
btn.addEventListener('click', function(e) {
|
||
e.stopPropagation();
|
||
el.classList.toggle('open');
|
||
});
|
||
});
|
||
});
|
||
});
|
||
})();
|
||
</script>
|
||
<?php
|
||
}, 31);
|
||
|
||
|
||
// ── Shortcodes lista de autores ────────────────────────────────────────────
|
||
|
||
// IDs excluidos: Fe Adulta (1,890), Ediciones Feadulta (1540), José Chicharro (1049)
|
||
if (!defined('FEA_AUTORES_EXCLUIR')) define('FEA_AUTORES_EXCLUIR', [1, 890, 1049, 1540]);
|
||
if (!defined('FEA_LANG_ES_TTID')) define('FEA_LANG_ES_TTID', 1404);
|
||
|
||
function fea_autores_query($min_count = 0, $extra_exclude = []) {
|
||
global $wpdb;
|
||
$excl = implode(',', array_merge(FEA_AUTORES_EXCLUIR, $extra_exclude));
|
||
$ttid = FEA_LANG_ES_TTID;
|
||
$having = $min_count > 0 ? "HAVING cnt >= $min_count" : '';
|
||
$order = $min_count > 0 ? 'cnt DESC' : 'u.display_name ASC';
|
||
return $wpdb->get_results("
|
||
SELECT u.ID, u.display_name, COUNT(*) as cnt
|
||
FROM {$wpdb->posts} p
|
||
JOIN {$wpdb->term_relationships} tr ON tr.object_id = p.ID
|
||
JOIN {$wpdb->users} u ON u.ID = p.post_author
|
||
WHERE p.post_type = 'post'
|
||
AND p.post_status = 'publish'
|
||
AND tr.term_taxonomy_id = $ttid
|
||
AND u.ID NOT IN ($excl)
|
||
GROUP BY p.post_author
|
||
$having
|
||
ORDER BY $order
|
||
");
|
||
}
|
||
|
||
function fea_autores_html($rows, $show_count = false, $extra_class = "") {
|
||
$extra = $extra_class ? ' ' . $extra_class : '';
|
||
$out = '<ul class="fea-autores-lista' . $extra . '" style="list-style:none;padding-left:0;">';
|
||
foreach ($rows as $r) {
|
||
$url = esc_url(get_author_posts_url($r->ID));
|
||
$name = esc_html($r->display_name);
|
||
$avatar = esc_url(get_avatar_url($r->ID, ['size' => 40, 'default' => 'identicon']));
|
||
$cnt = $show_count ? ' <span class="fea-autor-cnt">(' . $r->cnt . ')</span>' : '';
|
||
$out .= '<li><span style="display:inline-block;width:40px;height:40px;min-width:40px;border-radius:50%;overflow:hidden;flex-shrink:0;"><img src="' . $avatar . '" width="40" height="40" alt="" loading="lazy" style="width:40px;height:40px;object-fit:cover;display:block;"></span> <a href="' . $url . '">' . $name . '</a>' . $cnt . '</li>';
|
||
}
|
||
$out .= '</ul>';
|
||
return $out;
|
||
}
|
||
|
||
add_shortcode('fea_autores_habituales', function() {
|
||
$rows = fea_autores_query(30, [948, 1048]);
|
||
if (empty($rows)) return '<p>No hay datos disponibles.</p>';
|
||
$n = count($rows);
|
||
$out = '<details class="fea-autores-section"><summary class="fea-autores-summary">Autores habituales <span class="fea-autor-cnt">(' . $n . ' autores)</span></summary>';
|
||
$out .= fea_autores_html($rows, true);
|
||
$out .= '</details>';
|
||
return $out;
|
||
});
|
||
|
||
add_shortcode('fea_autores_completo', function() {
|
||
$rows = fea_autores_query(0);
|
||
if (empty($rows)) return '<p>No hay datos disponibles.</p>';
|
||
$n = count($rows);
|
||
$out = '<details class="fea-autores-section"><summary class="fea-autores-summary">Lista completa por orden alfabético <span class="fea-autor-cnt">(' . $n . ' autores)</span></summary>';
|
||
$out .= fea_autores_html($rows, false, 'fea-autores-completo');
|
||
$out .= '</details>';
|
||
return $out;
|
||
});
|
||
|
||
add_action('wp_head', function() {
|
||
if (!is_page('autores-lista')) return;
|
||
?>
|
||
<style>
|
||
.fea-autores-section { margin-bottom: 1.5em; }
|
||
.fea-autores-summary {
|
||
font-size: 1.3rem; font-weight: 600; cursor: pointer;
|
||
padding: 0.5em 0; list-style: none;
|
||
display: flex; align-items: center; gap: 0.5em;
|
||
border-bottom: 2px solid #046bd2; margin-bottom: 0.8em;
|
||
user-select: none;
|
||
}
|
||
.fea-autores-summary::-webkit-details-marker { display: none; }
|
||
.fea-autores-summary::before {
|
||
content: "\25B6"; font-size: 0.75em; color: #046bd2;
|
||
transition: transform 0.2s; display: inline-block;
|
||
}
|
||
details[open] > .fea-autores-summary::before { transform: rotate(90deg); }
|
||
.fea-autores-lista { list-style: none; padding: 0; margin: 0.5em 0 1em; }
|
||
.fea-autores-lista li {
|
||
display: flex; align-items: center; gap: 12px;
|
||
padding: 3px 0; border-bottom: 1px solid #f5f5f5;
|
||
}
|
||
.fea-autores-lista li img.fea-autor-avatar {
|
||
width: 40px; height: 40px; min-width: 40px;
|
||
border-radius: 50%; clip-path: circle(50%);
|
||
object-fit: cover; display: block; flex-shrink: 0;
|
||
}
|
||
.fea-autor-cnt { color: #888; font-size: 0.85em; }
|
||
.fea-autores-completo { column-count: 3; column-gap: 2em; }
|
||
.fea-autores-completo li { break-inside: avoid; }
|
||
@media (max-width: 700px) { .fea-autores-completo { column-count: 2; } }
|
||
@media (max-width: 480px) { .fea-autores-completo { column-count: 1; } }
|
||
</style>
|
||
<?php
|
||
}, 20);
|
||
|
||
// ── Aumentar posts por página en archivos de autor ─────────────────────────
|
||
add_action('pre_get_posts', function($query) {
|
||
if ($query->is_main_query() && $query->is_author()) {
|
||
$query->set('posts_per_page', 30);
|
||
}
|
||
});
|
||
|
||
// ── Shortcodes EFFA (Escuela de Formación en Fe Adulta) ────────────────────
|
||
|
||
// Sección de vídeos (subpáginas): thumbnail YT o primera imagen del contenido
|
||
add_shortcode('effa_seccion', function($atts) {
|
||
$atts = shortcode_atts(['cat' => '', 'num' => -1], $atts);
|
||
if (!$atts['cat']) return '';
|
||
|
||
$posts = get_posts([
|
||
'numberposts' => (int) $atts['num'],
|
||
'category_name' => $atts['cat'],
|
||
'post_status' => 'publish',
|
||
'orderby' => 'meta_value',
|
||
'meta_key' => '_effa_joomla_alias',
|
||
'order' => 'ASC',
|
||
]);
|
||
|
||
if (!$posts) return '<p>No hay contenido en esta sección todavía.</p>';
|
||
|
||
$items = [];
|
||
foreach ($posts as $p) {
|
||
$url = get_permalink($p->ID);
|
||
$thumb = get_the_post_thumbnail_url($p->ID, 'medium');
|
||
if (!$thumb && preg_match('~youtube\.com/watch\?v=([a-zA-Z0-9_-]+)~', $p->post_content, $m)) {
|
||
$thumb = 'https://img.youtube.com/vi/' . $m[1] . '/mqdefault.jpg';
|
||
}
|
||
if (!$thumb && preg_match('~<img[^>]+src="([^"]+)"~', $p->post_content, $mi)) {
|
||
$thumb = $mi[1];
|
||
}
|
||
$cell = '<td style="width:25%;padding:6px;vertical-align:top;">';
|
||
$cell .= '<a href="' . esc_url($url) . '" style="text-decoration:none;color:inherit;display:block;">';
|
||
if ($thumb) $cell .= '<img src="' . esc_url($thumb) . '" style="width:100%;height:auto;display:block;border-radius:4px;">';
|
||
$cell .= '<strong style="display:block;font-size:0.85rem;margin-top:5px;color:#222;">' . esc_html(fea_title($p->post_title)) . '</strong>';
|
||
$cell .= '</a>';
|
||
$cell .= '</td>';
|
||
$items[] = $cell;
|
||
}
|
||
|
||
$html = '<table style="width:100%;border-collapse:collapse;table-layout:fixed;">';
|
||
foreach (array_chunk($items, 4) as $row) {
|
||
while (count($row) < 4) $row[] = '<td></td>';
|
||
$html .= '<tr>' . implode('', $row) . '</tr>';
|
||
}
|
||
$html .= '</table>';
|
||
return $html;
|
||
});
|
||
|
||
// Hub del proyecto (8 artículos de presentación): primera imagen + extracto
|
||
add_shortcode('effa_proyecto', function() {
|
||
$posts = get_posts([
|
||
'numberposts' => -1,
|
||
'category_name' => 'proyecat',
|
||
'post_status' => 'publish',
|
||
'orderby' => 'name',
|
||
'order' => 'ASC',
|
||
]);
|
||
if (!$posts) return '';
|
||
|
||
$items = [];
|
||
foreach ($posts as $p) {
|
||
$url = get_permalink($p->ID);
|
||
preg_match('~<img[^>]+src="([^"]+)"~', $p->post_content, $mi);
|
||
$thumb = $mi[1] ?? '';
|
||
$text = trim(preg_replace('/\s+/', ' ', wp_strip_all_tags($p->post_content)));
|
||
$excerpt = wp_trim_words($text, 12, '…');
|
||
|
||
$cell = '<td style="width:25%;padding:6px;vertical-align:top;">';
|
||
$cell .= '<a href="' . esc_url($url) . '" style="text-decoration:none;color:inherit;display:block;">';
|
||
if ($thumb) $cell .= '<img src="' . esc_url($thumb) . '" style="width:100%;height:auto;display:block;border-radius:4px;">';
|
||
$cell .= '<strong style="display:block;font-size:0.85rem;margin-top:5px;color:#222;">' . esc_html(fea_title($p->post_title)) . '</strong>';
|
||
$cell .= '</a>';
|
||
$cell .= '<span style="display:block;font-size:0.75rem;color:#666;margin-top:3px;line-height:1.3;">' . esc_html($excerpt) . '</span>';
|
||
$cell .= '</td>';
|
||
$items[] = $cell;
|
||
}
|
||
|
||
$html = '<table style="width:100%;border-collapse:collapse;table-layout:fixed;">';
|
||
foreach (array_chunk($items, 4) as $row) {
|
||
while (count($row) < 4) $row[] = '<td></td>';
|
||
$html .= '<tr>' . implode('', $row) . '</tr>';
|
||
}
|
||
$html .= '</table>';
|
||
return $html;
|
||
});
|
||
|
||
// CSS EFFA (tabs nav, logo, CTA, cards)
|
||
add_action('wp_head', function() {
|
||
global $post;
|
||
if (!$post || (strpos($post->post_content, 'effa_') === false && strpos($post->post_name ?? '', 'effa') === false)) return;
|
||
?>
|
||
<style>
|
||
.effa-logo { display: block; margin: 0 auto 1rem; max-width: 200px; }
|
||
.effa-intro { text-align: center; margin-bottom: 1.5rem; }
|
||
.effa-nav { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1.5rem 0 2rem; padding: 0 0 1rem; list-style: none; border-bottom: 2px solid #e5e5e5; }
|
||
.effa-nav li { list-style: none; }
|
||
.effa-nav a { display: inline-block; padding: 0.35em 1em; border: 1px solid #ccc; border-radius: 999px; font-size: 0.85rem; text-decoration: none; color: #444; transition: background 0.15s, color 0.15s, border-color 0.15s; }
|
||
.effa-nav a:hover, .effa-nav a.active { background: #E89A1A; color: #fff; border-color: #E89A1A; }
|
||
.effa-cta-wrap { text-align: center; margin: 2rem 0 1rem; }
|
||
.effa-cta { display: inline-block; padding: 0.6em 1.8em; background: #E89A1A; color: #fff; border-radius: 999px; text-decoration: none; font-weight: 700; font-size: 1rem; }
|
||
.effa-cta:hover { background: #c97d10; color: #fff; }
|
||
</style>
|
||
<?php
|
||
}, 20);
|
||
|
||
// ── Índice dinámico de evangelio por libro ─────────────────────────────────
|
||
|
||
// "Jn 4, 5-42" → "jn-4-5-42" (anchor ID format)
|
||
function fea_cita_to_anchor(string $cita): string {
|
||
return strtolower(preg_replace('/[,\.\s]+/', '-', trim($cita)));
|
||
}
|
||
|
||
// Parse "Jn 4, 5-42" → [4, 5] for numeric sorting
|
||
function fea_cita_sort_key(string $cita): array {
|
||
preg_match('/(\d+),\s*(\d+)/', $cita, $m);
|
||
return [(int)($m[1] ?? 0), (int)($m[2] ?? 0)];
|
||
}
|
||
|
||
add_shortcode('fea_citas_evangelio', function($atts) {
|
||
$atts = shortcode_atts(['libro' => 'Jn'], $atts);
|
||
$libro = preg_replace('/[^A-Za-z]/', '', $atts['libro']); // sanitize
|
||
global $wpdb;
|
||
$cat_com = 1647;
|
||
|
||
// One query: all posts + author + avatar email in this book
|
||
$rows = $wpdb->get_results($wpdb->prepare(
|
||
"SELECT p.ID, p.post_title, p.post_author,
|
||
pm.meta_value AS cita,
|
||
u.display_name AS autor_name,
|
||
u.user_email AS autor_email
|
||
FROM {$wpdb->posts} p
|
||
JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID AND pm.meta_key = '_cita_evangelio'
|
||
JOIN {$wpdb->term_relationships} tr ON tr.object_id = p.ID
|
||
JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id = tr.term_taxonomy_id AND tt.term_id = %d
|
||
JOIN {$wpdb->users} u ON u.ID = p.post_author
|
||
WHERE p.post_status = 'publish'
|
||
AND pm.meta_value LIKE %s
|
||
ORDER BY pm.meta_value, p.post_date ASC",
|
||
$cat_com, $libro . ' %'
|
||
));
|
||
|
||
if (empty($rows)) return '<p>No hay comentarios para este evangelio.</p>';
|
||
|
||
// Group by cita
|
||
$groups = [];
|
||
foreach ($rows as $r) $groups[$r->cita][] = $r;
|
||
|
||
// Sort groups numerically by chapter, then verse
|
||
uksort($groups, function($a, $b) {
|
||
[$ca, $va] = fea_cita_sort_key($a);
|
||
[$cb, $vb] = fea_cita_sort_key($b);
|
||
return $ca !== $cb ? $ca - $cb : $va - $vb;
|
||
});
|
||
|
||
// Avatar URL by email (Gravatar, with fallback)
|
||
$avatar_cache = [];
|
||
$avatar_url = function(string $email, int $id) use (&$avatar_cache): string {
|
||
if (!isset($avatar_cache[$id])) {
|
||
$url = get_avatar_url($id, ['size' => 40, 'default' => 'mystery']);
|
||
$avatar_cache[$id] = $url ?: 'https://www.gravatar.com/avatar/' . md5(strtolower(trim($email))) . '?s=40&d=mystery';
|
||
}
|
||
return $avatar_cache[$id];
|
||
};
|
||
|
||
$html = '<div class="fea-indice-evangelio">';
|
||
|
||
foreach ($groups as $cita => $posts) {
|
||
$n = count($posts);
|
||
$anchor = fea_cita_to_anchor($cita);
|
||
$html .= '<details class="fea-cita-group" id="' . esc_attr($anchor) . '">';
|
||
$html .= '<summary class="fea-cita-summary">'
|
||
. '<span class="fea-cita-ref">' . esc_html($cita) . '</span>'
|
||
. ' <span class="fea-cita-count">' . $n . ' comentario' . ($n !== 1 ? 's' : '') . '</span>'
|
||
. '</summary>';
|
||
$html .= '<ul class="fea-cita-lista">';
|
||
foreach ($posts as $p) {
|
||
$av = $avatar_url($p->autor_email, $p->post_author);
|
||
$html .= '<li class="fea-cita-item">'
|
||
. '<span class="fea-cita-avatar">'
|
||
. '<img src="' . esc_url($av) . '" width="40" height="40" alt="" loading="lazy">'
|
||
. '</span>'
|
||
. '<span class="fea-cita-meta">'
|
||
. '<a href="' . esc_url(get_permalink($p->ID)) . '">' . esc_html(fea_title($p->post_title)) . '</a>'
|
||
. '<span class="fea-cita-autor">' . esc_html($p->autor_name) . '</span>'
|
||
. '</span>'
|
||
. '</li>';
|
||
}
|
||
$html .= '</ul></details>';
|
||
}
|
||
|
||
$html .= '</div>';
|
||
return $html;
|
||
});
|
||
|
||
add_action('wp_head', function() {
|
||
global $post;
|
||
if (!$post || !has_shortcode($post->post_content, 'fea_citas_evangelio')) return;
|
||
?>
|
||
<style>
|
||
.fea-indice-evangelio { margin: 1.5rem 0; }
|
||
|
||
.fea-cita-group {
|
||
border-bottom: 1px solid #e5e5e5;
|
||
padding: 0;
|
||
}
|
||
.fea-cita-summary {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 0.6rem;
|
||
padding: 0.75rem 0.5rem;
|
||
cursor: pointer;
|
||
list-style: none;
|
||
user-select: none;
|
||
}
|
||
.fea-cita-summary::-webkit-details-marker { display: none; }
|
||
.fea-cita-summary::before {
|
||
content: '›';
|
||
font-size: 1.1rem;
|
||
color: #046bd2;
|
||
transition: transform 0.15s;
|
||
display: inline-block;
|
||
flex-shrink: 0;
|
||
}
|
||
.fea-cita-group[open] > .fea-cita-summary::before { transform: rotate(90deg); }
|
||
.fea-cita-ref {
|
||
font-weight: 700;
|
||
font-size: 0.95rem;
|
||
}
|
||
.fea-cita-count {
|
||
font-size: 0.8rem;
|
||
color: #888;
|
||
}
|
||
|
||
.fea-cita-lista {
|
||
list-style: none;
|
||
padding: 0 0 0.75rem 1.5rem;
|
||
margin: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0.5rem;
|
||
}
|
||
.fea-cita-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
}
|
||
.fea-cita-avatar {
|
||
display: inline-block;
|
||
width: 40px; height: 40px; min-width: 40px;
|
||
border-radius: 50%;
|
||
overflow: hidden;
|
||
flex-shrink: 0;
|
||
}
|
||
.fea-cita-avatar img {
|
||
width: 40px; height: 40px;
|
||
object-fit: cover; display: block;
|
||
}
|
||
.fea-cita-meta {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0.1rem;
|
||
line-height: 1.3;
|
||
}
|
||
.fea-cita-meta a { font-size: 0.9rem; }
|
||
.fea-cita-autor {
|
||
font-size: 0.78rem;
|
||
color: #888;
|
||
}
|
||
</style>
|
||
<?php
|
||
}, 20);
|
||
|
||
// ── Pie de comentario: carta, cita evangelio, otros comentarios ────────────
|
||
|
||
// Add id anchors to verse headings in the 4 gospel index pages
|
||
add_filter('the_content', function($content) {
|
||
global $post;
|
||
$index_ids = [17874, 17881, 17882, 17883];
|
||
if (!isset($post->ID) || !in_array($post->ID, $index_ids)) return $content;
|
||
|
||
$bookmap = ['JUAN'=>'Jn','LUCAS'=>'Lc','MARCOS'=>'Mc','MATEO'=>'Mt'];
|
||
|
||
return preg_replace_callback(
|
||
'~<p([^>]*)>\s*(<a[^>]*>)\s*((JUAN|LUCAS|MARCOS|MATEO)\s+(\d+),\s*([\d\-–\s]+))\s*(</a>)\s*</p>~i',
|
||
function($m) use ($bookmap) {
|
||
$abbr = $bookmap[strtoupper($m[4])] ?? '';
|
||
if (!$abbr) return $m[0];
|
||
$anchor = strtolower($abbr . '-' . $m[5] . '-' . preg_replace('/[\s–\-]+/', '-', trim($m[6])));
|
||
$anchor = rtrim($anchor, '-');
|
||
return '<p' . $m[1] . ' id="' . $anchor . '">' . $m[2] . $m[3] . $m[7] . '</p>';
|
||
},
|
||
$content
|
||
);
|
||
}, 9); // priority 9 so it runs before the_content shortcode processing
|
||
|
||
add_filter('the_content', function($content) {
|
||
if (!is_single()) return $content;
|
||
global $post;
|
||
if (!in_category('comentarios-al-evangelio', $post)) return $content;
|
||
|
||
$carta_id = get_post_meta($post->ID, '_carta_id', true);
|
||
$cita = get_post_meta($post->ID, '_cita_evangelio', true);
|
||
|
||
if (!$carta_id && !$cita) return $content;
|
||
|
||
$html = '<div class="fea-com-footer">';
|
||
|
||
// --- Carta de la semana ---
|
||
if ($carta_id) {
|
||
$carta = get_post($carta_id);
|
||
if ($carta && $carta->post_status === 'publish') {
|
||
$fecha = date_i18n('j F Y', strtotime($carta->post_date));
|
||
$html .= '<div class="fea-com-row fea-com-carta">'
|
||
. '<span class="fea-com-label">Carta de la semana</span>'
|
||
. '<a href="' . esc_url(get_permalink($carta_id)) . '">'
|
||
. esc_html(fea_title($carta->post_title))
|
||
. ' <span class="fea-com-fecha">(' . $fecha . ')</span>'
|
||
. '</a>'
|
||
. '</div>';
|
||
}
|
||
}
|
||
|
||
// --- Cita del evangelio — link directo al anchor en el índice ---
|
||
if ($cita) {
|
||
$book_post_id = ['Mt' => 43908, 'Mc' => 43909, 'Lc' => 43907, 'Jn' => 43906];
|
||
$abbr = substr($cita, 0, 2);
|
||
$anchor = fea_cita_to_anchor($cita);
|
||
$index_url = isset($book_post_id[$abbr])
|
||
? esc_url(get_permalink($book_post_id[$abbr]) . '#' . $anchor)
|
||
: '';
|
||
|
||
$html .= '<div class="fea-com-row fea-com-cita">'
|
||
. '<span class="fea-com-label">Evangelio</span>'
|
||
. ($index_url
|
||
? '<a href="' . $index_url . '">' . esc_html($cita) . '</a>'
|
||
: '<span>' . esc_html($cita) . '</span>')
|
||
. '</div>';
|
||
}
|
||
|
||
// --- Otros comentarios de esta misma cita ---
|
||
if ($cita) {
|
||
$others = get_posts([
|
||
'post_type' => 'post',
|
||
'post_status' => 'publish',
|
||
'posts_per_page' => 30,
|
||
'post__not_in' => [$post->ID],
|
||
'category_name' => 'comentarios-al-evangelio',
|
||
'meta_key' => '_cita_evangelio',
|
||
'meta_value' => $cita,
|
||
'orderby' => 'date',
|
||
'order' => 'ASC',
|
||
]);
|
||
|
||
if (!empty($others)) {
|
||
$html .= '<div class="fea-com-row fea-com-otros">'
|
||
. '<span class="fea-com-label">Otros comentarios sobre ' . esc_html($cita) . '</span>'
|
||
. '<ul class="fea-com-lista">';
|
||
foreach ($others as $o) {
|
||
$html .= '<li><a href="' . esc_url(get_permalink($o->ID)) . '">'
|
||
. esc_html(fea_title($o->post_title)) . '</a></li>';
|
||
}
|
||
$html .= '</ul></div>';
|
||
}
|
||
}
|
||
|
||
$html .= '</div>'; // .fea-com-footer
|
||
return $content . $html;
|
||
});
|
||
|
||
add_action('wp_head', function() {
|
||
if (!is_single()) return;
|
||
global $post;
|
||
if (!$post || !in_category('comentarios-al-evangelio', $post)) return;
|
||
?>
|
||
<style>
|
||
.fea-com-footer {
|
||
margin-top: 2.5rem;
|
||
padding-top: 1.5rem;
|
||
border-top: 2px solid #e5e5e5;
|
||
font-size: 0.9rem;
|
||
}
|
||
.fea-com-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 0.4rem 0.8rem;
|
||
align-items: baseline;
|
||
margin-bottom: 1rem;
|
||
}
|
||
.fea-com-label {
|
||
font-weight: 700;
|
||
color: #555;
|
||
white-space: nowrap;
|
||
flex-shrink: 0;
|
||
}
|
||
.fea-com-label::after { content: ':'; margin-right: 0.2em; }
|
||
.fea-com-fecha { color: #888; font-size: 0.85em; }
|
||
.fea-com-lista {
|
||
list-style: none;
|
||
padding: 0;
|
||
margin: 0.3rem 0 0;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 0.3rem 0;
|
||
flex-direction: column;
|
||
}
|
||
.fea-com-lista li::before {
|
||
content: '›';
|
||
margin-right: 0.4em;
|
||
color: #046bd2;
|
||
}
|
||
.fea-com-otros .fea-com-label { display: block; margin-bottom: 0.4rem; }
|
||
.fea-com-otros { flex-direction: column; align-items: flex-start; }
|
||
</style>
|
||
<?php
|
||
}, 20);
|