358 lines
15 KiB
PHP
358 lines
15 KiB
PHP
<?php
|
||
|
||
/**
|
||
* Renderizador del mapa
|
||
*
|
||
* @package FP_Geo_Content
|
||
*/
|
||
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
class FP_Geo_Map_Renderer
|
||
{
|
||
|
||
/**
|
||
* Contador de instancias para IDs únicos
|
||
*/
|
||
private static $instance_count = 0;
|
||
|
||
/**
|
||
* Shortcode: [fp-geo-map]
|
||
*
|
||
* Atributos:
|
||
* - post_types: tipos de contenido separados por coma (usa config si no se especifica)
|
||
* - taxonomies: taxonomías para filtros separadas por coma
|
||
* - height: altura del mapa (default: 600px)
|
||
* - lat: latitud centro (usa config si no se especifica)
|
||
* - lng: longitud centro
|
||
* - zoom: nivel de zoom inicial
|
||
* - filters: true|false - mostrar filtros
|
||
* - detail: sidebar|modal - cómo mostrar el detalle
|
||
* - sidebar_position: left|right - posición del sidebar
|
||
* - legend: true|false - mostrar leyenda
|
||
* - show_detail_btn: true|false - mostrar botón de detalle
|
||
* - detail_btn_text: texto del botón
|
||
* - class: clases CSS adicionales
|
||
*/
|
||
public static function render_shortcode($atts)
|
||
{
|
||
$options = get_option('fp_geo_content_options', []);
|
||
|
||
$atts = shortcode_atts([
|
||
'post_types' => implode(',', $options['post_types'] ?? []),
|
||
'taxonomies' => implode(',', $options['filter_taxonomies'] ?? []),
|
||
'height' => '600px',
|
||
'lat' => $options['default_lat'] ?? '40.4168',
|
||
'lng' => $options['default_lng'] ?? '-3.7038',
|
||
'zoom' => $options['default_zoom'] ?? 12,
|
||
'filters' => 'true',
|
||
'detail' => $options['detail_display'] ?? 'sidebar',
|
||
'cluster' => $options['cluster_enabled'] ?? true,
|
||
'sidebar_position' => $options['sidebar_position'] ?? 'right',
|
||
'legend' => isset($options['show_legend']) ? ($options['show_legend'] ? 'true' : 'false') : 'false',
|
||
'show_detail_btn' => isset($options['show_detail_button']) ? ($options['show_detail_button'] ? 'true' : 'false') : 'true',
|
||
'detail_btn_text' => $options['detail_button_text'] ?? __('Ver detalle', 'fp-geo-content'),
|
||
'class' => '',
|
||
], $atts, 'fp-geo-map');
|
||
|
||
// Parsear valores
|
||
$post_types = array_filter(array_map('trim', explode(',', $atts['post_types'])));
|
||
$taxonomies = array_filter(array_map('trim', explode(',', $atts['taxonomies'])));
|
||
$show_filters = filter_var($atts['filters'], FILTER_VALIDATE_BOOLEAN);
|
||
$use_cluster = filter_var($atts['cluster'], FILTER_VALIDATE_BOOLEAN);
|
||
$show_legend = filter_var($atts['legend'], FILTER_VALIDATE_BOOLEAN);
|
||
$show_detail_btn = filter_var($atts['show_detail_btn'], FILTER_VALIDATE_BOOLEAN);
|
||
$sidebar_position = $atts['sidebar_position'];
|
||
|
||
if (empty($post_types)) {
|
||
return '<p class="fp-geo-error">' . __('No se han configurado tipos de contenido para el mapa.', 'fp-geo-content') . '</p>';
|
||
}
|
||
|
||
// Incrementar contador de instancias
|
||
self::$instance_count++;
|
||
$map_id = 'fp-geo-map-' . self::$instance_count;
|
||
|
||
// Cargar assets
|
||
wp_enqueue_style('fp-geo-content');
|
||
wp_enqueue_script('fp-geo-content');
|
||
|
||
// Obtener marcadores
|
||
$markers = FP_Geo_Data_Provider::get_markers([
|
||
'post_types' => $post_types,
|
||
]);
|
||
|
||
// Obtener términos para filtros
|
||
$filter_terms = [];
|
||
if ($show_filters && !empty($taxonomies)) {
|
||
$filter_terms = FP_Geo_Data_Provider::get_filter_terms($post_types, $taxonomies);
|
||
}
|
||
|
||
// Obtener configuración de tiles
|
||
$tile_provider = $options['tile_provider'] ?? 'carto_light';
|
||
$tile_providers = FP_Geo_Settings::get_tile_providers();
|
||
$tile_config = $tile_providers[$tile_provider] ?? $tile_providers['carto_light'];
|
||
|
||
// Obtener icono personalizado si existe
|
||
$marker_icon_id = $options['marker_icon'] ?? 0;
|
||
$marker_icon_url = $marker_icon_id ? wp_get_attachment_image_url($marker_icon_id, 'full') : '';
|
||
|
||
// Obtener etiquetas de los post types
|
||
$post_type_labels = [];
|
||
foreach ($post_types as $pt) {
|
||
$pt_obj = get_post_type_object($pt);
|
||
if ($pt_obj) {
|
||
$post_type_labels[$pt] = [
|
||
'singular' => $pt_obj->labels->singular_name,
|
||
'plural' => $pt_obj->labels->name,
|
||
];
|
||
}
|
||
}
|
||
|
||
// Obtener datos de leyenda si está habilitada
|
||
$legend_data = [];
|
||
$legend_taxonomy = $options['legend_taxonomy'] ?? '';
|
||
if ($show_legend && !empty($legend_taxonomy) && isset($filter_terms[$legend_taxonomy])) {
|
||
// Verificar si hay marcadores piloto (es_piloto está en los posts, no en los términos)
|
||
$has_pilot_markers = false;
|
||
foreach ($markers as $marker) {
|
||
if (isset($marker['es_piloto']) && $marker['es_piloto']) {
|
||
$has_pilot_markers = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
$legend_data = [
|
||
'taxonomy' => $legend_taxonomy,
|
||
'label' => $filter_terms[$legend_taxonomy]['label'],
|
||
'items' => $filter_terms[$legend_taxonomy]['terms'],
|
||
'has_pilots' => $has_pilot_markers,
|
||
];
|
||
}
|
||
|
||
// Configuración del mapa
|
||
$map_config = [
|
||
'mapId' => $map_id,
|
||
'center' => [(float) $atts['lat'], (float) $atts['lng']],
|
||
'zoom' => (int) $atts['zoom'],
|
||
'minZoom' => (int) ($options['min_zoom'] ?? 5),
|
||
'maxZoom' => (int) ($options['max_zoom'] ?? 18),
|
||
'markers' => $markers,
|
||
'filters' => $filter_terms,
|
||
'filterCombine' => $options['filter_combine'] ?? 'OR',
|
||
'detailDisplay' => $atts['detail'],
|
||
'clusterEnabled' => $use_cluster,
|
||
'tileUrl' => $tile_config['url'],
|
||
'tileAttribution' => $tile_config['attribution'],
|
||
'tileSubdomains' => $tile_config['subdomains'],
|
||
'defaultIcon' => FP_GEO_PLUGIN_URL . 'assets/img/marker-icon.png',
|
||
'ajaxUrl' => admin_url('admin-ajax.php'),
|
||
'nonce' => wp_create_nonce('fp_geo_nonce'),
|
||
'postTypes' => $post_types,
|
||
'postTypeLabels' => $post_type_labels,
|
||
// Nuevas opciones de marcadores
|
||
'markerIcon' => $marker_icon_url,
|
||
'markerDefaultColor' => $options['marker_default_color'] ?? '#F97316',
|
||
'useCategoryColors' => isset($options['use_category_colors']) && $options['use_category_colors'],
|
||
'legendTaxonomy' => $legend_taxonomy,
|
||
// Nuevas opciones de scroll
|
||
'scrollWheelZoom' => $options['scroll_wheel_zoom'] ?? 'ctrl',
|
||
// Nuevas opciones de display
|
||
'sidebarPosition' => $sidebar_position,
|
||
'showLegend' => $show_legend,
|
||
'legendData' => $legend_data,
|
||
'showDetailButton' => $show_detail_btn,
|
||
'detailButtonText' => $atts['detail_btn_text'],
|
||
'i18n' => [
|
||
'loading' => __('Cargando...', 'fp-geo-content'),
|
||
'noResults' => __('No se encontraron resultados', 'fp-geo-content'),
|
||
'viewMore' => $atts['detail_btn_text'],
|
||
'close' => __('Cerrar', 'fp-geo-content'),
|
||
'clearFilters' => __('Limpiar filtros', 'fp-geo-content'),
|
||
'scrollZoomHint' => __('Usa Ctrl + scroll para hacer zoom', 'fp-geo-content'),
|
||
],
|
||
];
|
||
|
||
// Pasar configuración al JS
|
||
wp_localize_script('fp-geo-content', 'fpGeoConfig_' . self::$instance_count, $map_config);
|
||
|
||
ob_start();
|
||
$wrapper_classes = [
|
||
'fp-geo-wrapper',
|
||
'fp-geo-detail-' . esc_attr($atts['detail']),
|
||
'fp-geo-sidebar-' . esc_attr($sidebar_position),
|
||
esc_attr($atts['class']),
|
||
];
|
||
?>
|
||
<div id="<?php echo esc_attr($map_id); ?>-wrapper"
|
||
class="<?php echo esc_attr(implode(' ', array_filter($wrapper_classes))); ?>"
|
||
data-instance="<?php echo esc_attr(self::$instance_count); ?>">
|
||
|
||
<?php if ($show_filters && !empty($filter_terms)): ?>
|
||
<?php echo self::render_filters($map_id, $filter_terms); ?>
|
||
<?php endif; ?>
|
||
|
||
<div class="fp-geo-map-container">
|
||
<div id="<?php echo esc_attr($map_id); ?>"
|
||
class="fp-geo-map"
|
||
style="height: <?php echo esc_attr($atts['height']); ?>;"></div>
|
||
|
||
<?php if ($show_legend && !empty($legend_data)): ?>
|
||
<?php echo self::render_legend($map_id, $legend_data); ?>
|
||
<?php endif; ?>
|
||
|
||
<?php echo self::render_detail_panel($map_id, $atts['detail'], $show_detail_btn, $atts['detail_btn_text']); ?>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
|
||
return ob_get_clean();
|
||
}
|
||
|
||
/**
|
||
* Renderizar panel de filtros
|
||
*/
|
||
private static function render_filters($map_id, $filter_terms)
|
||
{
|
||
ob_start();
|
||
?>
|
||
<div class="fp-geo-filters" data-map="<?php echo esc_attr($map_id); ?>">
|
||
<div class="fp-geo-filters-inner">
|
||
<?php foreach ($filter_terms as $taxonomy => $data): ?>
|
||
<div class="fp-geo-filter-group" data-taxonomy="<?php echo esc_attr($taxonomy); ?>">
|
||
<label class="fp-geo-filter-label"><?php echo esc_html($data['label']); ?>:</label>
|
||
<div class="fp-geo-filter-buttons">
|
||
<?php foreach ($data['terms'] as $term): ?>
|
||
<button type="button"
|
||
class="fp-geo-filter-btn"
|
||
data-slug="<?php echo esc_attr($term['slug']); ?>"
|
||
data-taxonomy="<?php echo esc_attr($taxonomy); ?>"
|
||
style="<?php echo isset($term['color']) ? '--filter-color: ' . esc_attr($term['color']) . ';' : ''; ?>">
|
||
<?php if (isset($term['icono'])): ?>
|
||
<img src="<?php echo esc_url($term['icono']); ?>" alt="" class="fp-geo-filter-icon">
|
||
<?php endif; ?>
|
||
<span><?php echo esc_html($term['name']); ?></span>
|
||
</button>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
|
||
<div class="fp-geo-filters-footer">
|
||
<span class="fp-geo-results-count">
|
||
<?php _e('Mostrando', 'fp-geo-content'); ?>
|
||
<strong class="fp-geo-results-number">0</strong>
|
||
<span class="fp-geo-results-label"><?php _e('resultados', 'fp-geo-content'); ?></span>
|
||
</span>
|
||
<button type="button" class="fp-geo-clear-filters">
|
||
<?php _e('Limpiar filtros', 'fp-geo-content'); ?>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
return ob_get_clean();
|
||
}
|
||
|
||
/**
|
||
* Renderizar leyenda
|
||
*/
|
||
private static function render_legend($map_id, $legend_data)
|
||
{
|
||
if (empty($legend_data['items'])) {
|
||
return '';
|
||
}
|
||
|
||
$has_pilots = isset($legend_data['has_pilots']) && $legend_data['has_pilots'];
|
||
|
||
ob_start();
|
||
?>
|
||
<div id="<?php echo esc_attr($map_id); ?>-legend" class="fp-geo-legend">
|
||
<div class="fp-geo-legend-title"><?php _e('Leyenda', 'fp-geo-content'); ?></div>
|
||
|
||
<div class="fp-geo-legend-section">
|
||
<div class="fp-geo-legend-section-title"><?php _e('Iniciativas', 'fp-geo-content'); ?></div>
|
||
<div class="fp-geo-legend-items">
|
||
<?php foreach ($legend_data['items'] as $item):
|
||
$color = isset($item['color']) ? $item['color'] : '#F97316';
|
||
?>
|
||
<div class="fp-geo-legend-item">
|
||
<span class="fp-geo-legend-marker" style="background-color: <?php echo esc_attr($color); ?>;"></span>
|
||
<span class="fp-geo-legend-label"><?php echo esc_html($item['name']); ?></span>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
|
||
<?php if ($has_pilots): ?>
|
||
<div class="fp-geo-legend-section fp-geo-legend-pilot-section">
|
||
<div class="fp-geo-legend-items">
|
||
<div class="fp-geo-legend-item fp-geo-legend-pilot">
|
||
<span class="fp-geo-legend-marker-pilot" aria-hidden="true">
|
||
<svg width="22" height="28" viewBox="0 0 36 48">
|
||
<circle cx="18" cy="18" r="15" fill="#888" stroke="white" stroke-width="3"/>
|
||
<polygon points="18,42 24,30 12,30" fill="#888" stroke="white" stroke-width="2" stroke-linejoin="round"/>
|
||
<text x="18" y="22" text-anchor="middle" fill="white" font-size="14" font-weight="bold">★</text>
|
||
</svg>
|
||
</span>
|
||
<span class="fp-geo-legend-label"><?php _e('Bloque Piloto', 'fp-geo-content'); ?></span>
|
||
</div>
|
||
<p class="fp-geo-legend-pilot-desc">
|
||
<?php _e('Actuación piloto (transversal a cualquier iniciativa)', 'fp-geo-content'); ?>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php
|
||
return ob_get_clean();
|
||
}
|
||
|
||
/**
|
||
* Renderizar panel de detalle
|
||
*/
|
||
private static function render_detail_panel($map_id, $display_type, $show_button = true, $button_text = '')
|
||
{
|
||
$class = $display_type === 'modal' ? 'fp-geo-modal' : 'fp-geo-sidebar';
|
||
$button_text = $button_text ?: __('Ver más', 'fp-geo-content');
|
||
|
||
ob_start();
|
||
?>
|
||
<div id="<?php echo esc_attr($map_id); ?>-detail" class="fp-geo-detail <?php echo esc_attr($class); ?>">
|
||
<button class="fp-geo-detail-close" aria-label="<?php _e('Cerrar', 'fp-geo-content'); ?>">×</button>
|
||
|
||
<div class="fp-geo-detail-content">
|
||
<div class="fp-geo-detail-header">
|
||
<div class="fp-geo-detail-taxonomies"></div>
|
||
</div>
|
||
|
||
<div class="fp-geo-detail-thumbnail"></div>
|
||
|
||
<h2 class="fp-geo-detail-title"></h2>
|
||
|
||
<div class="fp-geo-detail-excerpt"></div>
|
||
|
||
<div class="fp-geo-detail-meta">
|
||
<div class="fp-geo-detail-location"></div>
|
||
<div class="fp-geo-detail-contact"></div>
|
||
</div>
|
||
|
||
<?php if ($show_button): ?>
|
||
<div class="fp-geo-detail-footer">
|
||
<a href="#" class="fp-geo-detail-link fp-geo-btn" target="_blank">
|
||
<?php echo esc_html($button_text); ?>
|
||
</a>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
|
||
<?php if ($display_type === 'modal'): ?>
|
||
<div id="<?php echo esc_attr($map_id); ?>-overlay" class="fp-geo-overlay"></div>
|
||
<?php endif; ?>
|
||
<?php
|
||
return ob_get_clean();
|
||
}
|
||
}
|