Añadir mu-plugins y scripts de feadulta
This commit is contained in:
@@ -0,0 +1,277 @@
|
||||
<?php
|
||||
/**
|
||||
* fea-recopilatorios — Listados dinámicos auto-actualizables (issues #96-#118).
|
||||
*
|
||||
* Sustituye las páginas-recopilatorio MANUALES de Joomla (tablas/listas de
|
||||
* enlaces mantenidas a mano) por un listado generado desde una categoría.
|
||||
* Así, cada carta/post nuevo que entre en la categoría aparece solo, sin
|
||||
* copiar y pegar.
|
||||
*
|
||||
* Uso:
|
||||
* [fea_recopilatorio cat="1648"] (por term_id)
|
||||
* [fea_recopilatorio cat="eucaristia"] (por slug)
|
||||
* [fea_recopilatorio cat="1648" per_page="150" group="year" order="desc"]
|
||||
*
|
||||
* - group="year" (def.): separadores por año. group="none": lista plana.
|
||||
* - Paginación propia (?recop=N) para no chocar con la paginación del tema.
|
||||
* - Títulos normalizados con fea_title() si existe (legacy en MAYÚSCULAS).
|
||||
*/
|
||||
|
||||
if (!defined('FEA_RECOP_DEFAULT_PER_PAGE')) {
|
||||
define('FEA_RECOP_DEFAULT_PER_PAGE', 200);
|
||||
}
|
||||
|
||||
function fea_recop_resolve_term($cat): int {
|
||||
$cat = trim((string) $cat);
|
||||
if ($cat === '') return 0;
|
||||
if (ctype_digit($cat)) return (int) $cat;
|
||||
$t = get_term_by('slug', $cat, 'category');
|
||||
return $t ? (int) $t->term_id : 0;
|
||||
}
|
||||
|
||||
function fea_recop_title(string $raw): string {
|
||||
return function_exists('fea_title') ? fea_title($raw) : $raw;
|
||||
}
|
||||
|
||||
function fea_recop_render(array $atts = []): string {
|
||||
$atts = shortcode_atts([
|
||||
'cat' => '',
|
||||
'per_page' => (string) FEA_RECOP_DEFAULT_PER_PAGE,
|
||||
'group' => 'year',
|
||||
'order' => 'desc',
|
||||
], $atts, 'fea_recopilatorio');
|
||||
|
||||
$term_id = fea_recop_resolve_term($atts['cat']);
|
||||
if (!$term_id) return '<p class="fea-recop-empty">Recopilatorio no disponible.</p>';
|
||||
|
||||
$per_page = max(20, min(500, (int) $atts['per_page']));
|
||||
$order = strtolower($atts['order']) === 'asc' ? 'ASC' : 'DESC';
|
||||
$paged = isset($_GET['recop']) ? max(1, (int) $_GET['recop']) : 1;
|
||||
|
||||
$q = new WP_Query([
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'cat' => $term_id,
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $paged,
|
||||
'orderby' => 'date',
|
||||
'order' => $order,
|
||||
'ignore_sticky_posts' => true,
|
||||
'no_found_rows' => false,
|
||||
]);
|
||||
|
||||
if (!$q->have_posts()) {
|
||||
wp_reset_postdata();
|
||||
return '<p class="fea-recop-empty">Todavía no hay entradas en esta sección.</p>';
|
||||
}
|
||||
|
||||
$by_year = ($atts['group'] === 'year');
|
||||
$html = '<div class="fea-recop">';
|
||||
$cur_year = null;
|
||||
$open = false;
|
||||
|
||||
while ($q->have_posts()) {
|
||||
$q->the_post();
|
||||
if ($by_year) {
|
||||
$y = get_the_date('Y');
|
||||
if ($y !== $cur_year) {
|
||||
if ($open) $html .= '</ul>';
|
||||
$html .= '<h3 class="fea-recop-year">' . esc_html($y) . '</h3><ul class="fea-recop-list">';
|
||||
$cur_year = $y; $open = true;
|
||||
}
|
||||
} elseif (!$open) {
|
||||
$html .= '<ul class="fea-recop-list">'; $open = true;
|
||||
}
|
||||
$title = fea_recop_title(get_the_title());
|
||||
$html .= '<li><a href="' . esc_url(get_permalink()) . '">' . esc_html($title) . '</a>'
|
||||
. ' <span class="fea-recop-date">' . esc_html(get_the_date('j M Y')) . '</span></li>';
|
||||
}
|
||||
if ($open) $html .= '</ul>';
|
||||
wp_reset_postdata();
|
||||
|
||||
// Paginación propia
|
||||
$total_pages = (int) $q->max_num_pages;
|
||||
if ($total_pages > 1) {
|
||||
$html .= '<nav class="fea-recop-pages" aria-label="Paginación del recopilatorio">';
|
||||
if ($paged > 1) {
|
||||
$html .= '<a href="' . esc_url(add_query_arg('recop', $paged - 1)) . '">Anterior</a>';
|
||||
}
|
||||
$html .= '<span>Página ' . $paged . ' de ' . $total_pages . '</span>';
|
||||
if ($paged < $total_pages) {
|
||||
$html .= '<a href="' . esc_url(add_query_arg('recop', $paged + 1)) . '">Siguiente</a>';
|
||||
}
|
||||
$html .= '</nav>';
|
||||
}
|
||||
$html .= '</div>';
|
||||
return $html;
|
||||
}
|
||||
add_shortcode('fea_recopilatorio', 'fea_recop_render');
|
||||
|
||||
// ── [fea_multimedia_indice] — galería visual de multimedia (issue #110) ──────
|
||||
// Sustituye la página intermedia /multimedia/ (4 enlaces) por la lista directa
|
||||
// de los artículos de las categorías multimedia, con preview visual (miniatura
|
||||
// de YouTube o primera imagen del contenido) + extracto, para invitar al clic.
|
||||
|
||||
/** Extrae una preview del contenido: ['type'=>'video'|'image'|'none','src'=>url]. */
|
||||
function fea_mm_preview(string $content): array {
|
||||
// 1) Vídeo de YouTube embebido → miniatura hqdefault
|
||||
if (preg_match('~(?:youtube(?:-nocookie)?\.com/(?:embed/|watch\?v=)|youtu\.be/)([A-Za-z0-9_-]{6,})~', $content, $m)) {
|
||||
return ['type' => 'video', 'src' => 'https://img.youtube.com/vi/' . $m[1] . '/hqdefault.jpg'];
|
||||
}
|
||||
// 2) Vimeo → sin thumbnail server-side fiable; marcar como vídeo sin src
|
||||
if (preg_match('~vimeo\.com/(?:video/)?(\d+)~', $content)) {
|
||||
return ['type' => 'video', 'src' => ''];
|
||||
}
|
||||
// 3) Primera imagen del contenido
|
||||
if (preg_match('~<img[^>]+src=["\']([^"\']+)["\']~i', $content, $m)) {
|
||||
return ['type' => 'image', 'src' => $m[1]];
|
||||
}
|
||||
return ['type' => 'none', 'src' => ''];
|
||||
}
|
||||
|
||||
function fea_mm_indice_render(array $atts = []): string {
|
||||
$atts = shortcode_atts([
|
||||
'cats' => '1649,26', // Multimedia + Índice multimedia
|
||||
'per_page' => '24',
|
||||
], $atts, 'fea_multimedia_indice');
|
||||
|
||||
$cats = array_filter(array_map('intval', explode(',', $atts['cats'])));
|
||||
if (!$cats) return '';
|
||||
$per_page = max(6, min(60, (int) $atts['per_page']));
|
||||
$paged = isset($_GET['mmpag']) ? max(1, (int) $_GET['mmpag']) : 1;
|
||||
|
||||
$q = new WP_Query([
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'category__in' => $cats,
|
||||
'posts_per_page' => $per_page,
|
||||
'paged' => $paged,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
'ignore_sticky_posts' => true,
|
||||
]);
|
||||
|
||||
if (!$q->have_posts()) {
|
||||
wp_reset_postdata();
|
||||
return '<p class="fea-recop-empty">Todavía no hay multimedia disponible.</p>';
|
||||
}
|
||||
|
||||
$html = '<div class="fea-mm-wrap"><div class="fea-mm-grid">';
|
||||
while ($q->have_posts()) {
|
||||
$q->the_post();
|
||||
$content = get_the_content();
|
||||
$prev = fea_mm_preview($content);
|
||||
$title = fea_recop_title(get_the_title());
|
||||
$url = get_permalink();
|
||||
$excerpt = wp_trim_words(trim(preg_replace('/\s+/', ' ', wp_strip_all_tags($content))), 22, '…');
|
||||
|
||||
$thumb = '';
|
||||
if ($prev['src'] !== '') {
|
||||
$thumb = '<img class="fea-mm-img" src="' . esc_url($prev['src']) . '" alt="" loading="lazy" '
|
||||
. 'onerror="this.style.display=\'none\';this.parentNode.classList.add(\'fea-mm-noimg\');">';
|
||||
}
|
||||
$cls = 'fea-mm-thumb' . ($prev['src'] === '' ? ' fea-mm-noimg' : '');
|
||||
$play = $prev['type'] === 'video'
|
||||
? '<span class="fea-mm-play" aria-hidden="true"></span>' : '';
|
||||
|
||||
$html .= '<a class="fea-mm-card" href="' . esc_url($url) . '">'
|
||||
. '<span class="' . $cls . '">' . $thumb . $play . '</span>'
|
||||
. '<span class="fea-mm-body">'
|
||||
. '<span class="fea-mm-title">' . esc_html($title) . '</span>'
|
||||
. '<span class="fea-mm-date">' . esc_html(get_the_date('j M Y')) . '</span>'
|
||||
. '<span class="fea-mm-excerpt">' . esc_html($excerpt) . '</span>'
|
||||
. '</span></a>';
|
||||
}
|
||||
$html .= '</div>';
|
||||
|
||||
$total_pages = (int) $q->max_num_pages;
|
||||
wp_reset_postdata();
|
||||
if ($total_pages > 1) {
|
||||
$html .= '<nav class="fea-recop-pages" aria-label="Paginación de multimedia">';
|
||||
if ($paged > 1) $html .= '<a href="' . esc_url(add_query_arg('mmpag', $paged - 1)) . '">Anterior</a>';
|
||||
$html .= '<span>Página ' . $paged . ' de ' . $total_pages . '</span>';
|
||||
if ($paged < $total_pages) $html .= '<a href="' . esc_url(add_query_arg('mmpag', $paged + 1)) . '">Siguiente</a>';
|
||||
$html .= '</nav>';
|
||||
}
|
||||
$html .= '</div>'; // .fea-mm-wrap
|
||||
return $html;
|
||||
}
|
||||
add_shortcode('fea_multimedia_indice', 'fea_mm_indice_render');
|
||||
|
||||
add_action('wp_head', function () {
|
||||
if (is_admin()) return;
|
||||
?>
|
||||
<style id="fea-recop-css">
|
||||
.fea-recop { margin: 1.5rem 0; }
|
||||
.fea-recop-year {
|
||||
font-family: 'Fraunces', Georgia, serif; font-weight: 600;
|
||||
color: #8b1a2e; margin: 1.6rem 0 0.6rem; font-size: 1.3rem;
|
||||
border-bottom: 1px solid #efe7d8; padding-bottom: 0.25rem;
|
||||
}
|
||||
.fea-recop-list { list-style: none; margin: 0; padding: 0; }
|
||||
.fea-recop-list li {
|
||||
padding: 0.35rem 0; border-bottom: 1px solid #f4eee2;
|
||||
display: flex; justify-content: space-between; gap: 1rem; align-items: baseline;
|
||||
}
|
||||
.fea-recop-list a { text-decoration: none; color: #2a2320; }
|
||||
.fea-recop-list a:hover { color: #8b1a2e; text-decoration: underline; }
|
||||
.fea-recop-date { color: #998; font-size: 0.82rem; white-space: nowrap; }
|
||||
.fea-recop-pages {
|
||||
display: flex; gap: 1rem; align-items: center; justify-content: center;
|
||||
margin-top: 1.4rem; font-size: 0.95rem;
|
||||
}
|
||||
.fea-recop-pages a {
|
||||
padding: 0.4rem 0.8rem; border: 1px solid #8b1a2e; border-radius: 6px;
|
||||
text-decoration: none; color: #8b1a2e;
|
||||
}
|
||||
/* Galería multimedia (#110) */
|
||||
/* wrapper: el padre es entry-content alignfull (ancho completo), así que basta
|
||||
centrar con margin:auto; max-width:none vence el cap de is-layout-constrained */
|
||||
.fea-mm-wrap {
|
||||
width: min(1180px, 100%);
|
||||
max-width: none;
|
||||
margin: 1.5rem auto 2rem;
|
||||
}
|
||||
.fea-mm-grid {
|
||||
display: grid; gap: 1.3rem;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
@media (min-width: 520px) { .fea-mm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
|
||||
@media (min-width: 760px) { .fea-mm-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
|
||||
@media (max-width: 700px) { .fea-mm-wrap { width: min(100%, calc(100vw - 1rem)); } }
|
||||
.fea-mm-card {
|
||||
display: flex; flex-direction: column; text-decoration: none;
|
||||
background: #fff; border: 1px solid #efe7d8; border-radius: 10px;
|
||||
overflow: hidden; transition: box-shadow .15s, transform .15s;
|
||||
}
|
||||
.fea-mm-card:hover { box-shadow: 0 6px 18px rgba(139,26,46,.13); transform: translateY(-2px); }
|
||||
.fea-mm-thumb {
|
||||
position: relative; display: block; aspect-ratio: 16/9; background: #f4eee2;
|
||||
overflow: hidden;
|
||||
}
|
||||
.fea-mm-img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||
.fea-mm-noimg {
|
||||
background: linear-gradient(135deg, #8b1a2e 0%, #b34255 100%);
|
||||
}
|
||||
.fea-mm-play {
|
||||
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
|
||||
width: 54px; height: 54px; border-radius: 50%;
|
||||
background: rgba(0,0,0,.55); pointer-events: none;
|
||||
}
|
||||
.fea-mm-play::after {
|
||||
content: ''; position: absolute; top: 50%; left: 54%; transform: translate(-50%, -50%);
|
||||
border-style: solid; border-width: 11px 0 11px 18px;
|
||||
border-color: transparent transparent transparent #fff;
|
||||
}
|
||||
.fea-mm-card:hover .fea-mm-play { background: rgba(139,26,46,.85); }
|
||||
.fea-mm-body { padding: 0.8rem 0.9rem 1rem; display: flex; flex-direction: column; gap: 0.3rem; }
|
||||
.fea-mm-title {
|
||||
font-family: 'Fraunces', Georgia, serif; font-weight: 600; color: #2a2320;
|
||||
font-size: 1.02rem; line-height: 1.25;
|
||||
}
|
||||
.fea-mm-card:hover .fea-mm-title { color: #8b1a2e; }
|
||||
.fea-mm-date { color: #998; font-size: 0.78rem; }
|
||||
.fea-mm-excerpt { color: #5a534e; font-size: 0.85rem; line-height: 1.4; margin-top: 0.15rem; }
|
||||
</style>
|
||||
<?php
|
||||
}, 26);
|
||||
Reference in New Issue
Block a user