914 lines
35 KiB
PHP
914 lines
35 KiB
PHP
<?php
|
|
/**
|
|
* Shortcodes para mostrar contenido en el frontend
|
|
*
|
|
* @package Bloques_Transicion
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class Bloques_Shortcodes {
|
|
|
|
/**
|
|
* Registrar shortcodes
|
|
*/
|
|
public static function register() {
|
|
// Shortcode principal unificado
|
|
add_shortcode('bloques-listado', [__CLASS__, 'render_listado']);
|
|
|
|
// Alias y shortcuts
|
|
add_shortcode('bloques-grid', [__CLASS__, 'render_grid']);
|
|
add_shortcode('bloques-recursos', [__CLASS__, 'render_recursos']);
|
|
add_shortcode('bloques-noticias', [__CLASS__, 'render_noticias']);
|
|
add_shortcode('bloques-eventos', [__CLASS__, 'render_eventos']);
|
|
|
|
// Bloques con header (para Home)
|
|
add_shortcode('bloques-novedades', [__CLASS__, 'render_novedades']);
|
|
add_shortcode('bloques-agenda', [__CLASS__, 'render_agenda']);
|
|
|
|
// Taxonomías
|
|
add_shortcode('bloques-iniciativas', [__CLASS__, 'render_iniciativas']);
|
|
add_shortcode('bloques-lineas', [__CLASS__, 'render_lineas_trabajo']);
|
|
|
|
// AJAX handlers
|
|
add_action('wp_ajax_bloques_filter', [__CLASS__, 'ajax_filter']);
|
|
add_action('wp_ajax_nopriv_bloques_filter', [__CLASS__, 'ajax_filter']);
|
|
add_action('wp_ajax_bloques_load_more', [__CLASS__, 'ajax_load_more']);
|
|
add_action('wp_ajax_nopriv_bloques_load_more', [__CLASS__, 'ajax_load_more']);
|
|
|
|
// Rewrite rules para noticias de bloques
|
|
add_action('init', [__CLASS__, 'register_rewrite_rules']);
|
|
add_filter('post_link', [__CLASS__, 'filter_post_permalink'], 10, 2);
|
|
add_filter('query_vars', [__CLASS__, 'add_query_vars']);
|
|
}
|
|
|
|
/**
|
|
* Registrar reglas de rewrite para noticias de bloques
|
|
*/
|
|
public static function register_rewrite_rules() {
|
|
add_rewrite_rule(
|
|
'^bloques-en-transicion/noticias/([^/]+)/?$',
|
|
'index.php?name=$matches[1]&bloques_noticia=1',
|
|
'top'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Añadir query vars
|
|
*/
|
|
public static function add_query_vars($vars) {
|
|
$vars[] = 'bloques_noticia';
|
|
return $vars;
|
|
}
|
|
|
|
/**
|
|
* Filtrar permalink de posts con categoría bloques-en-transicion
|
|
*/
|
|
public static function filter_post_permalink($permalink, $post) {
|
|
if ($post->post_type !== 'post') {
|
|
return $permalink;
|
|
}
|
|
|
|
if (has_category('bloques-en-transicion', $post) || has_category('bloques', $post)) {
|
|
return home_url('/bloques-en-transicion/noticias/' . $post->post_name . '/');
|
|
}
|
|
|
|
return $permalink;
|
|
}
|
|
|
|
/**
|
|
* Construir tax_query correcta según el tipo de contenido.
|
|
*
|
|
* Para noticias: siempre incluye la condición base (category = bloques-en-transicion)
|
|
* y la combina con AND con los filtros de iniciativa/linea_trabajo.
|
|
* Para CPTs: solo filtra por iniciativa/linea_trabajo.
|
|
*
|
|
* @param string $type Tipo de contenido (noticias, actuaciones, recursos, eventos)
|
|
* @param string $iniciativa Slug de iniciativa para filtrar (vacío = sin filtro)
|
|
* @param string $linea Slug de línea de trabajo para filtrar (vacío = sin filtro)
|
|
* @return array tax_query lista para WP_Query
|
|
*/
|
|
private static function build_tax_query($type, $iniciativa = '', $linea = '') {
|
|
$tax_query = [];
|
|
|
|
// Para noticias: siempre requerir la categoría base
|
|
if ($type === 'noticias') {
|
|
$tax_query[] = [
|
|
'taxonomy' => 'category',
|
|
'field' => 'slug',
|
|
'terms' => ['bloques-en-transicion', 'bloques'],
|
|
'include_children' => true,
|
|
];
|
|
}
|
|
|
|
// Filtro por iniciativa
|
|
if (!empty($iniciativa)) {
|
|
$tax_query[] = [
|
|
'taxonomy' => 'iniciativa',
|
|
'field' => 'slug',
|
|
'terms' => is_array($iniciativa) ? $iniciativa : explode(',', $iniciativa),
|
|
];
|
|
}
|
|
|
|
// Filtro por línea de trabajo
|
|
if (!empty($linea)) {
|
|
$tax_query[] = [
|
|
'taxonomy' => 'linea_trabajo',
|
|
'field' => 'slug',
|
|
'terms' => is_array($linea) ? $linea : explode(',', $linea),
|
|
];
|
|
}
|
|
|
|
// Si hay más de una condición, usar AND
|
|
if (count($tax_query) > 1) {
|
|
$tax_query['relation'] = 'AND';
|
|
}
|
|
|
|
return $tax_query;
|
|
}
|
|
|
|
/**
|
|
* Mapeo de tipos
|
|
*/
|
|
private static function get_type_config($type) {
|
|
$configs = [
|
|
'actuaciones' => [
|
|
'post_type' => 'actuacion',
|
|
'template' => 'actuaciones',
|
|
'label_singular' => __('actuación', 'bloques-transicion'),
|
|
'label_plural' => __('actuaciones', 'bloques-transicion'),
|
|
],
|
|
'recursos' => [
|
|
'post_type' => 'recurso_bloques',
|
|
'template' => 'recursos',
|
|
'label_singular' => __('recurso', 'bloques-transicion'),
|
|
'label_plural' => __('recursos', 'bloques-transicion'),
|
|
],
|
|
'eventos' => [
|
|
'post_type' => 'evento_bloques',
|
|
'template' => 'eventos',
|
|
'label_singular' => __('evento', 'bloques-transicion'),
|
|
'label_plural' => __('eventos', 'bloques-transicion'),
|
|
],
|
|
'noticias' => [
|
|
'post_type' => 'post',
|
|
'template' => 'noticias',
|
|
'label_singular' => __('noticia', 'bloques-transicion'),
|
|
'label_plural' => __('noticias', 'bloques-transicion'),
|
|
],
|
|
];
|
|
|
|
return $configs[$type] ?? $configs['actuaciones'];
|
|
}
|
|
|
|
/**
|
|
* Shortcode principal: [bloques-listado]
|
|
*
|
|
* Atributos:
|
|
* - type: actuaciones|recursos|eventos|noticias (requerido)
|
|
* - widget: grid|list (default: grid)
|
|
* - columns: 1|2|3|4 (default: 3)
|
|
* - limit: número de items a mostrar (default: -1 = todos)
|
|
* - pagination: true|false - botón "Ver más" (default: false)
|
|
* - filter: true|false - filtros tipo botonera (default: false)
|
|
* - search: true|false - campo de búsqueda (default: false)
|
|
* - iniciativa: slug de iniciativa para filtrar
|
|
* - linea: slug de línea de trabajo para filtrar
|
|
* - orderby: date|title|menu_order (default: date)
|
|
* - order: ASC|DESC (default: DESC)
|
|
* - upcoming: solo eventos futuros (default: true para eventos)
|
|
* - class: clase CSS adicional
|
|
*/
|
|
public static function render_listado($atts) {
|
|
$atts = shortcode_atts([
|
|
'type' => 'recursos',
|
|
'widget' => 'grid',
|
|
'columns' => 3,
|
|
'limit' => -1,
|
|
'pagination' => 'false',
|
|
'filter' => 'false',
|
|
'search' => 'false',
|
|
'iniciativa' => '',
|
|
'linea' => '',
|
|
'orderby' => 'date',
|
|
'order' => 'DESC',
|
|
'upcoming' => 'true',
|
|
'class' => '',
|
|
], $atts, 'bloques-listado');
|
|
|
|
$type_config = self::get_type_config($atts['type']);
|
|
$post_type = $type_config['post_type'];
|
|
$show_filter = filter_var($atts['filter'], FILTER_VALIDATE_BOOLEAN);
|
|
$show_search = filter_var($atts['search'], FILTER_VALIDATE_BOOLEAN);
|
|
$show_pagination = filter_var($atts['pagination'], FILTER_VALIDATE_BOOLEAN);
|
|
$upcoming = filter_var($atts['upcoming'], FILTER_VALIDATE_BOOLEAN);
|
|
$limit = intval($atts['limit']);
|
|
|
|
// Query args
|
|
$args = [
|
|
'post_type' => $post_type,
|
|
'posts_per_page' => $limit > 0 ? $limit : -1,
|
|
'orderby' => $atts['orderby'],
|
|
'order' => $atts['order'],
|
|
'post_status' => 'publish',
|
|
];
|
|
|
|
// Ordenar eventos por fecha de inicio
|
|
if ($post_type === 'evento_bloques') {
|
|
$args['meta_key'] = 'fecha_inicio';
|
|
$args['orderby'] = 'meta_value';
|
|
$args['order'] = 'ASC';
|
|
|
|
// Solo eventos futuros
|
|
if ($upcoming) {
|
|
$args['meta_query'] = [
|
|
[
|
|
'key' => 'fecha_inicio',
|
|
'value' => date('Ymd'),
|
|
'compare' => '>=',
|
|
'type' => 'DATE',
|
|
],
|
|
];
|
|
}
|
|
}
|
|
|
|
// Construir tax_query (para noticias incluye automáticamente la categoría base)
|
|
$tax_query = self::build_tax_query($atts['type'], $atts['iniciativa'], $atts['linea']);
|
|
if (!empty($tax_query)) {
|
|
$args['tax_query'] = $tax_query;
|
|
}
|
|
|
|
$query = new WP_Query($args);
|
|
$total_posts = $query->found_posts;
|
|
|
|
// Generar ID único para el contenedor
|
|
$container_id = 'bloques-listado-' . wp_rand(1000, 9999);
|
|
|
|
ob_start();
|
|
?>
|
|
<div id="<?php echo esc_attr($container_id); ?>"
|
|
class="bloques-listado bloques-type-<?php echo esc_attr($atts['type']); ?> bloques-widget-<?php echo esc_attr($atts['widget']); ?> <?php echo esc_attr($atts['class']); ?>"
|
|
data-type="<?php echo esc_attr($atts['type']); ?>"
|
|
data-post-type="<?php echo esc_attr($post_type); ?>"
|
|
data-widget="<?php echo esc_attr($atts['widget']); ?>"
|
|
data-columns="<?php echo esc_attr($atts['columns']); ?>"
|
|
data-limit="<?php echo esc_attr($limit); ?>"
|
|
data-offset="<?php echo esc_attr($limit > 0 ? $limit : 0); ?>"
|
|
data-total="<?php echo esc_attr($total_posts); ?>"
|
|
data-upcoming="<?php echo esc_attr($atts['upcoming']); ?>">
|
|
|
|
<?php if ($show_filter || $show_search): ?>
|
|
<?php echo self::render_filter_bar($atts['type'], $container_id, $show_search, $total_posts, $type_config); ?>
|
|
<?php endif; ?>
|
|
|
|
<div class="bloques-items bloques-cols-<?php echo esc_attr($atts['columns']); ?>">
|
|
<?php
|
|
if ($query->have_posts()) {
|
|
while ($query->have_posts()) {
|
|
$query->the_post();
|
|
echo self::render_item(get_post(), $atts['type'], $atts['widget']);
|
|
}
|
|
wp_reset_postdata();
|
|
} else {
|
|
echo '<p class="bloques-no-results">' . __('No se encontraron resultados.', 'bloques-transicion') . '</p>';
|
|
}
|
|
?>
|
|
</div>
|
|
|
|
<?php if ($show_pagination && $limit > 0 && $total_posts > $limit): ?>
|
|
<div class="bloques-load-more-wrapper">
|
|
<button type="button" class="bloques-btn bloques-btn-load-more" data-container="<?php echo esc_attr($container_id); ?>">
|
|
<?php _e('Ver más', 'bloques-transicion'); ?>
|
|
<span class="bloques-arrow">→</span>
|
|
</button>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php
|
|
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/**
|
|
* Renderizar barra de filtros estilo botonera
|
|
*/
|
|
private static function render_filter_bar($type, $container_id, $show_search, $total_posts, $type_config) {
|
|
$iniciativas = get_terms([
|
|
'taxonomy' => 'iniciativa',
|
|
'hide_empty' => true,
|
|
]);
|
|
|
|
$lineas = get_terms([
|
|
'taxonomy' => 'linea_trabajo',
|
|
'hide_empty' => true,
|
|
]);
|
|
|
|
ob_start();
|
|
?>
|
|
<div class="bloques-filters" data-container="<?php echo esc_attr($container_id); ?>">
|
|
<?php if ($show_search): ?>
|
|
<div class="bloques-search-wrapper">
|
|
<input type="text" class="bloques-search-input" placeholder="<?php echo esc_attr(sprintf(__('Buscar %s...', 'bloques-transicion'), $type_config['label_plural'])); ?>">
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($iniciativas) && !is_wp_error($iniciativas)): ?>
|
|
<div class="bloques-filter-group">
|
|
<span class="bloques-filter-label"><?php _e('Filtrar por Iniciativa', 'bloques-transicion'); ?></span>
|
|
<div class="bloques-filter-buttons">
|
|
<button type="button" class="bloques-filter-btn active" data-taxonomy="iniciativa" data-value="">
|
|
<?php _e('Todas las iniciativas', 'bloques-transicion'); ?>
|
|
</button>
|
|
<?php foreach ($iniciativas as $term):
|
|
$color = get_field('color', $term);
|
|
$icono = get_field('icono', $term);
|
|
?>
|
|
<button type="button" class="bloques-filter-btn"
|
|
data-taxonomy="iniciativa"
|
|
data-value="<?php echo esc_attr($term->slug); ?>"
|
|
style="<?php echo $color ? '--btn-active-color: ' . esc_attr($color) . ';' : ''; ?>">
|
|
<?php if ($icono): ?>
|
|
<img src="<?php echo esc_url($icono); ?>" alt="" class="bloques-filter-icon">
|
|
<?php endif; ?>
|
|
<?php echo esc_html($term->name); ?>
|
|
</button>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($lineas) && !is_wp_error($lineas)): ?>
|
|
<div class="bloques-filter-group">
|
|
<span class="bloques-filter-label"><?php _e('Filtrar por eje de trabajo', 'bloques-transicion'); ?></span>
|
|
<div class="bloques-filter-buttons">
|
|
<button type="button" class="bloques-filter-btn active" data-taxonomy="linea_trabajo" data-value="">
|
|
<?php _e('Todos los ejes', 'bloques-transicion'); ?>
|
|
</button>
|
|
<?php foreach ($lineas as $term):
|
|
$color = get_field('color', $term);
|
|
$icono = get_field('icono', $term);
|
|
?>
|
|
<button type="button" class="bloques-filter-btn"
|
|
data-taxonomy="linea_trabajo"
|
|
data-value="<?php echo esc_attr($term->slug); ?>"
|
|
style="<?php echo $color ? '--btn-active-color: ' . esc_attr($color) . ';' : ''; ?>">
|
|
<?php if ($icono): ?>
|
|
<img src="<?php echo esc_url($icono); ?>" alt="" class="bloques-filter-icon">
|
|
<?php endif; ?>
|
|
<?php echo esc_html($term->name); ?>
|
|
</button>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="bloques-filters-footer">
|
|
<span class="bloques-results-count">
|
|
<?php _e('Mostrando', 'bloques-transicion'); ?>
|
|
<strong class="bloques-results-number"><?php echo esc_html($total_posts); ?></strong>
|
|
<span class="bloques-results-label"><?php echo esc_html($type_config['label_plural']); ?></span>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/**
|
|
* Renderizar un item individual
|
|
*/
|
|
public static function render_item($post, $type, $widget = 'grid') {
|
|
$template = BLOQUES_PLUGIN_DIR . "templates/frontend/item-{$type}.php";
|
|
|
|
if (!file_exists($template)) {
|
|
$template = BLOQUES_PLUGIN_DIR . 'templates/frontend/item-default.php';
|
|
}
|
|
|
|
// Preparar datos comunes
|
|
$data = self::prepare_item_data($post, $type, $widget);
|
|
|
|
// Extraer variables para el template
|
|
extract($data);
|
|
|
|
ob_start();
|
|
include $template;
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/**
|
|
* Preparar datos de un item
|
|
*/
|
|
private static function prepare_item_data($post, $type, $widget) {
|
|
$data = [
|
|
'id' => $post->ID,
|
|
'title' => get_the_title($post),
|
|
'excerpt' => get_the_excerpt($post),
|
|
'content' => apply_filters('the_content', $post->post_content),
|
|
'permalink' => get_permalink($post),
|
|
'thumbnail' => get_the_post_thumbnail_url($post, 'medium_large'),
|
|
'thumbnail_alt' => get_post_meta(get_post_thumbnail_id($post), '_wp_attachment_image_alt', true),
|
|
'iniciativas' => wp_get_post_terms($post->ID, 'iniciativa'),
|
|
'lineas' => wp_get_post_terms($post->ID, 'linea_trabajo'),
|
|
'widget' => $widget,
|
|
'type' => $type,
|
|
'date' => get_the_date('j M Y', $post),
|
|
];
|
|
|
|
// Datos específicos por tipo
|
|
switch ($type) {
|
|
case 'actuaciones':
|
|
$data['es_piloto'] = get_field('es_piloto', $post->ID);
|
|
$data['direccion'] = get_field('direccion', $post->ID);
|
|
$data['localidad'] = get_field('localidad', $post->ID);
|
|
$data['latitud'] = get_field('latitud', $post->ID);
|
|
$data['longitud'] = get_field('longitud', $post->ID);
|
|
break;
|
|
|
|
case 'recursos':
|
|
$data['archivo'] = get_field('archivo', $post->ID);
|
|
$data['tipo_recurso'] = get_field('tipo_recurso', $post->ID);
|
|
$data['url_externa'] = get_field('url_externa', $post->ID);
|
|
break;
|
|
|
|
case 'eventos':
|
|
$data['fecha_inicio'] = get_field('fecha_inicio', $post->ID);
|
|
$data['hora_inicio'] = get_field('hora_inicio', $post->ID);
|
|
$data['fecha_fin'] = get_field('fecha_fin', $post->ID);
|
|
$data['hora_fin'] = get_field('hora_fin', $post->ID);
|
|
$data['lugar'] = get_field('lugar', $post->ID);
|
|
$data['direccion'] = get_field('direccion', $post->ID);
|
|
$data['url_online'] = get_field('url_online', $post->ID);
|
|
$data['url_inscripcion'] = get_field('url_inscripcion', $post->ID);
|
|
$data['tipos_evento'] = wp_get_post_terms($post->ID, 'tipo_evento');
|
|
break;
|
|
|
|
case 'noticias':
|
|
// Obtener categorías del post (excluyendo bloques-en-transicion)
|
|
$categories = get_the_category($post->ID);
|
|
$display_category = null;
|
|
$category_color = '#F97316';
|
|
|
|
foreach ($categories as $cat) {
|
|
if (!in_array($cat->slug, ['bloques-en-transicion', 'bloques'])) {
|
|
$display_category = $cat;
|
|
// Intentar obtener color de iniciativa si existe con ese slug
|
|
$iniciativa = get_term_by('slug', $cat->slug, 'iniciativa');
|
|
if ($iniciativa) {
|
|
$color = get_field('color', $iniciativa);
|
|
if ($color) {
|
|
$category_color = $color;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!$display_category && !empty($categories)) {
|
|
$display_category = $categories[0];
|
|
}
|
|
|
|
$data['category'] = $display_category;
|
|
$data['category_color'] = $category_color;
|
|
break;
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Shortcode para grid simple: [bloques-grid]
|
|
*/
|
|
public static function render_grid($atts) {
|
|
$atts['widget'] = 'grid';
|
|
return self::render_listado($atts);
|
|
}
|
|
|
|
/**
|
|
* Shortcode para recursos: [bloques-recursos]
|
|
*/
|
|
public static function render_recursos($atts) {
|
|
$atts = shortcode_atts([
|
|
'widget' => 'grid',
|
|
'columns' => 3,
|
|
'limit' => -1,
|
|
'pagination' => 'false',
|
|
'filter' => 'true',
|
|
'search' => 'true',
|
|
'class' => '',
|
|
], $atts, 'bloques-recursos');
|
|
|
|
$atts['type'] = 'recursos';
|
|
return self::render_listado($atts);
|
|
}
|
|
|
|
/**
|
|
* Shortcode para noticias: [bloques-noticias]
|
|
*/
|
|
public static function render_noticias($atts) {
|
|
$atts = shortcode_atts([
|
|
'widget' => 'grid',
|
|
'columns' => 3,
|
|
'limit' => -1,
|
|
'pagination' => 'false',
|
|
'filter' => 'false',
|
|
'class' => '',
|
|
], $atts, 'bloques-noticias');
|
|
|
|
$atts['type'] = 'noticias';
|
|
return self::render_listado($atts);
|
|
}
|
|
|
|
/**
|
|
* Shortcode específico para eventos: [bloques-eventos]
|
|
*/
|
|
public static function render_eventos($atts) {
|
|
$atts = shortcode_atts([
|
|
'widget' => 'list',
|
|
'columns' => 1,
|
|
'limit' => 5,
|
|
'upcoming' => 'true',
|
|
'pagination' => 'false',
|
|
'filter' => 'false',
|
|
'class' => '',
|
|
], $atts, 'bloques-eventos');
|
|
|
|
$atts['type'] = 'eventos';
|
|
return self::render_listado($atts);
|
|
}
|
|
|
|
/**
|
|
* Shortcode para Novedades con header: [bloques-novedades]
|
|
*/
|
|
public static function render_novedades($atts) {
|
|
$atts = shortcode_atts([
|
|
'limit' => 3,
|
|
'columns' => 1,
|
|
'title' => __('Novedades', 'bloques-transicion'),
|
|
'subtitle' => __('Últimas noticias del proyecto', 'bloques-transicion'),
|
|
'show_header' => 'true',
|
|
'link_text' => __('Ver todas las novedades', 'bloques-transicion'),
|
|
'link_url' => '/bloques-en-transicion/noticias/',
|
|
'class' => '',
|
|
], $atts, 'bloques-novedades');
|
|
|
|
$show_header = filter_var($atts['show_header'], FILTER_VALIDATE_BOOLEAN);
|
|
|
|
ob_start();
|
|
?>
|
|
<div class="bloques-block bloques-novedades-block <?php echo esc_attr($atts['class']); ?>">
|
|
<?php if ($show_header): ?>
|
|
<div class="bloques-block-header">
|
|
<div class="bloques-block-icon">
|
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M19 5V19H5V5H19ZM19 3H5C3.9 3 3 3.9 3 5V19C3 20.1 3.9 21 5 21H19C20.1 21 21 20.1 21 19V5C21 3.9 20.1 3 19 3ZM14 17H7V15H14V17ZM17 13H7V11H17V13ZM17 9H7V7H17V9Z" fill="currentColor"/>
|
|
</svg>
|
|
</div>
|
|
<div class="bloques-block-titles">
|
|
<h3 class="bloques-block-title"><?php echo esc_html($atts['title']); ?></h3>
|
|
<?php if ($atts['subtitle']): ?>
|
|
<p class="bloques-block-subtitle"><?php echo esc_html($atts['subtitle']); ?></p>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php
|
|
echo self::render_listado([
|
|
'type' => 'noticias',
|
|
'widget' => 'compact',
|
|
'columns' => $atts['columns'],
|
|
'limit' => $atts['limit'],
|
|
'class' => 'bloques-novedades-list',
|
|
]);
|
|
?>
|
|
|
|
<?php if ($atts['link_text'] && $atts['link_url']): ?>
|
|
<div class="bloques-block-footer">
|
|
<a href="<?php echo esc_url($atts['link_url']); ?>" class="bloques-link-more">
|
|
<?php echo esc_html($atts['link_text']); ?>
|
|
<span class="bloques-arrow">→</span>
|
|
</a>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/**
|
|
* Shortcode para Agenda con header: [bloques-agenda]
|
|
*/
|
|
public static function render_agenda($atts) {
|
|
$atts = shortcode_atts([
|
|
'limit' => 4,
|
|
'title' => __('Agenda', 'bloques-transicion'),
|
|
'subtitle' => __('Próximas actividades', 'bloques-transicion'),
|
|
'show_header' => 'true',
|
|
'link_text' => __('Ver calendario completo', 'bloques-transicion'),
|
|
'link_url' => '/bloques-en-transicion/noticias/',
|
|
'upcoming' => 'true',
|
|
'class' => '',
|
|
], $atts, 'bloques-agenda');
|
|
|
|
$show_header = filter_var($atts['show_header'], FILTER_VALIDATE_BOOLEAN);
|
|
|
|
ob_start();
|
|
?>
|
|
<div class="bloques-block bloques-agenda-block <?php echo esc_attr($atts['class']); ?>">
|
|
<?php if ($show_header): ?>
|
|
<div class="bloques-block-header">
|
|
<div class="bloques-block-icon bloques-block-icon-agenda">
|
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M19 4H18V2H16V4H8V2H6V4H5C3.89 4 3 4.9 3 6V20C3 21.1 3.89 22 5 22H19C20.1 22 21 21.1 21 20V6C21 4.9 20.1 4 19 4ZM19 20H5V9H19V20ZM9 11H7V13H9V11ZM13 11H11V13H13V11ZM17 11H15V13H17V11ZM9 15H7V17H9V15ZM13 15H11V17H13V15ZM17 15H15V17H17V15Z" fill="currentColor"/>
|
|
</svg>
|
|
</div>
|
|
<div class="bloques-block-titles">
|
|
<h3 class="bloques-block-title"><?php echo esc_html($atts['title']); ?></h3>
|
|
<?php if ($atts['subtitle']): ?>
|
|
<p class="bloques-block-subtitle"><?php echo esc_html($atts['subtitle']); ?></p>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php
|
|
echo self::render_listado([
|
|
'type' => 'eventos',
|
|
'widget' => 'agenda',
|
|
'columns' => 1,
|
|
'limit' => $atts['limit'],
|
|
'upcoming' => $atts['upcoming'],
|
|
'class' => 'bloques-agenda-list',
|
|
]);
|
|
?>
|
|
|
|
<?php if ($atts['link_text'] && $atts['link_url']): ?>
|
|
<div class="bloques-block-footer">
|
|
<a href="<?php echo esc_url($atts['link_url']); ?>" class="bloques-link-more">
|
|
<?php echo esc_html($atts['link_text']); ?>
|
|
<span class="bloques-arrow">→</span>
|
|
</a>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/**
|
|
* Shortcode para mostrar iniciativas: [bloques-iniciativas]
|
|
*/
|
|
public static function render_iniciativas($atts) {
|
|
$atts = shortcode_atts([
|
|
'widget' => 'cards',
|
|
'columns' => 4,
|
|
'show_description' => 'true',
|
|
'class' => '',
|
|
], $atts, 'bloques-iniciativas');
|
|
|
|
$iniciativas = get_terms([
|
|
'taxonomy' => 'iniciativa',
|
|
'hide_empty' => false,
|
|
]);
|
|
|
|
$show_desc = filter_var($atts['show_description'], FILTER_VALIDATE_BOOLEAN);
|
|
|
|
ob_start();
|
|
?>
|
|
<div class="bloques-iniciativas bloques-cols-<?php echo esc_attr($atts['columns']); ?> <?php echo esc_attr($atts['class']); ?>">
|
|
<?php foreach ($iniciativas as $term):
|
|
$icono = get_field('icono', $term);
|
|
$color = get_field('color', $term);
|
|
$ubicacion = get_field('ubicacion_texto', $term);
|
|
$estado = get_field('estado', $term);
|
|
?>
|
|
<div class="bloques-iniciativa-card" style="<?php echo $color ? '--iniciativa-color: ' . esc_attr($color) . ';' : ''; ?>">
|
|
<?php if ($icono): ?>
|
|
<div class="bloques-iniciativa-icono">
|
|
<img src="<?php echo esc_url($icono); ?>" alt="<?php echo esc_attr($term->name); ?>">
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<h3 class="bloques-iniciativa-titulo">
|
|
<a href="<?php echo esc_url(get_term_link($term)); ?>">
|
|
<?php echo esc_html($term->name); ?>
|
|
</a>
|
|
</h3>
|
|
|
|
<?php if ($show_desc && $term->description): ?>
|
|
<p class="bloques-iniciativa-descripcion">
|
|
<?php echo esc_html($term->description); ?>
|
|
</p>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($ubicacion): ?>
|
|
<p class="bloques-iniciativa-ubicacion">
|
|
<span class="dashicons dashicons-location"></span>
|
|
<?php echo esc_html($ubicacion); ?>
|
|
</p>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($estado): ?>
|
|
<span class="bloques-iniciativa-estado"><?php echo esc_html($estado); ?></span>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/**
|
|
* Shortcode para mostrar líneas de trabajo: [bloques-lineas]
|
|
*/
|
|
public static function render_lineas_trabajo($atts) {
|
|
$atts = shortcode_atts([
|
|
'widget' => 'icons',
|
|
'columns' => 6,
|
|
'show_description' => 'true',
|
|
'class' => '',
|
|
], $atts, 'bloques-lineas');
|
|
|
|
$lineas = get_terms([
|
|
'taxonomy' => 'linea_trabajo',
|
|
'hide_empty' => false,
|
|
]);
|
|
|
|
$show_desc = filter_var($atts['show_description'], FILTER_VALIDATE_BOOLEAN);
|
|
|
|
ob_start();
|
|
?>
|
|
<div class="bloques-lineas bloques-cols-<?php echo esc_attr($atts['columns']); ?> <?php echo esc_attr($atts['class']); ?>">
|
|
<?php foreach ($lineas as $term):
|
|
$icono = get_field('icono', $term);
|
|
$color = get_field('color', $term);
|
|
?>
|
|
<div class="bloques-linea-item" style="<?php echo $color ? '--linea-color: ' . esc_attr($color) . ';' : ''; ?>">
|
|
<?php if ($icono): ?>
|
|
<div class="bloques-linea-icono">
|
|
<img src="<?php echo esc_url($icono); ?>" alt="<?php echo esc_attr($term->name); ?>">
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<h4 class="bloques-linea-titulo">
|
|
<a href="<?php echo esc_url(get_term_link($term)); ?>">
|
|
<?php echo esc_html($term->name); ?>
|
|
</a>
|
|
</h4>
|
|
|
|
<?php if ($show_desc && $term->description): ?>
|
|
<p class="bloques-linea-descripcion">
|
|
<?php echo esc_html($term->description); ?>
|
|
</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/**
|
|
* Handler AJAX para filtros
|
|
*/
|
|
public static function ajax_filter() {
|
|
check_ajax_referer('bloques_nonce', 'nonce');
|
|
|
|
$type = sanitize_text_field($_POST['type'] ?? 'recursos');
|
|
$iniciativa = sanitize_text_field($_POST['iniciativa'] ?? '');
|
|
$linea = sanitize_text_field($_POST['linea_trabajo'] ?? '');
|
|
$search = sanitize_text_field($_POST['search'] ?? '');
|
|
$widget = sanitize_text_field($_POST['widget'] ?? 'grid');
|
|
$upcoming = sanitize_text_field($_POST['upcoming'] ?? 'true');
|
|
|
|
$type_config = self::get_type_config($type);
|
|
$post_type = $type_config['post_type'];
|
|
|
|
$args = [
|
|
'post_type' => $post_type,
|
|
'posts_per_page' => -1,
|
|
'post_status' => 'publish',
|
|
];
|
|
|
|
// Búsqueda
|
|
if (!empty($search)) {
|
|
$args['s'] = $search;
|
|
}
|
|
|
|
// Eventos
|
|
if ($post_type === 'evento_bloques') {
|
|
$args['meta_key'] = 'fecha_inicio';
|
|
$args['orderby'] = 'meta_value';
|
|
$args['order'] = 'ASC';
|
|
|
|
if (filter_var($upcoming, FILTER_VALIDATE_BOOLEAN)) {
|
|
$args['meta_query'] = [
|
|
[
|
|
'key' => 'fecha_inicio',
|
|
'value' => date('Ymd'),
|
|
'compare' => '>=',
|
|
'type' => 'DATE',
|
|
],
|
|
];
|
|
}
|
|
}
|
|
|
|
// Construir tax_query
|
|
$args['tax_query'] = self::build_tax_query($type, $iniciativa, $linea);
|
|
|
|
$query = new WP_Query($args);
|
|
|
|
ob_start();
|
|
|
|
if ($query->have_posts()) {
|
|
while ($query->have_posts()) {
|
|
$query->the_post();
|
|
echo self::render_item(get_post(), $type, $widget);
|
|
}
|
|
wp_reset_postdata();
|
|
} else {
|
|
echo '<p class="bloques-no-results">' . __('No se encontraron resultados.', 'bloques-transicion') . '</p>';
|
|
}
|
|
|
|
$html = ob_get_clean();
|
|
|
|
wp_send_json_success([
|
|
'html' => $html,
|
|
'count' => $query->found_posts,
|
|
'label' => $query->found_posts === 1 ? $type_config['label_singular'] : $type_config['label_plural'],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Handler AJAX para cargar más
|
|
*/
|
|
public static function ajax_load_more() {
|
|
check_ajax_referer('bloques_nonce', 'nonce');
|
|
|
|
$type = sanitize_text_field($_POST['type'] ?? 'recursos');
|
|
$offset = intval($_POST['offset'] ?? 0);
|
|
$limit = intval($_POST['limit'] ?? 9);
|
|
$widget = sanitize_text_field($_POST['widget'] ?? 'grid');
|
|
$iniciativa = sanitize_text_field($_POST['iniciativa'] ?? '');
|
|
$linea = sanitize_text_field($_POST['linea_trabajo'] ?? '');
|
|
$upcoming = sanitize_text_field($_POST['upcoming'] ?? 'true');
|
|
|
|
$type_config = self::get_type_config($type);
|
|
$post_type = $type_config['post_type'];
|
|
|
|
$args = [
|
|
'post_type' => $post_type,
|
|
'posts_per_page' => $limit,
|
|
'offset' => $offset,
|
|
'post_status' => 'publish',
|
|
];
|
|
|
|
// Eventos
|
|
if ($post_type === 'evento_bloques') {
|
|
$args['meta_key'] = 'fecha_inicio';
|
|
$args['orderby'] = 'meta_value';
|
|
$args['order'] = 'ASC';
|
|
|
|
if (filter_var($upcoming, FILTER_VALIDATE_BOOLEAN)) {
|
|
$args['meta_query'] = [
|
|
[
|
|
'key' => 'fecha_inicio',
|
|
'value' => date('Ymd'),
|
|
'compare' => '>=',
|
|
'type' => 'DATE',
|
|
],
|
|
];
|
|
}
|
|
}
|
|
|
|
// Construir tax_query
|
|
$args['tax_query'] = self::build_tax_query($type, $iniciativa, $linea);
|
|
|
|
$query = new WP_Query($args);
|
|
|
|
ob_start();
|
|
|
|
if ($query->have_posts()) {
|
|
while ($query->have_posts()) {
|
|
$query->the_post();
|
|
echo self::render_item(get_post(), $type, $widget);
|
|
}
|
|
wp_reset_postdata();
|
|
}
|
|
|
|
$html = ob_get_clean();
|
|
|
|
// Calcular si hay más
|
|
$total_query = new WP_Query(array_merge($args, ['posts_per_page' => -1, 'offset' => 0, 'fields' => 'ids']));
|
|
$has_more = ($offset + $limit) < $total_query->found_posts;
|
|
|
|
wp_send_json_success([
|
|
'html' => $html,
|
|
'has_more' => $has_more,
|
|
'new_offset' => $offset + $query->post_count,
|
|
]);
|
|
}
|
|
}
|