Files
freepress-map/fp-geo-content/includes/class-data-provider.php
2026-02-13 13:14:41 +01:00

281 lines
8.7 KiB
PHP

<?php
/**
* Proveedor de datos para el mapa
*
* @package FP_Geo_Content
*/
if (!defined('ABSPATH')) {
exit;
}
class FP_Geo_Data_Provider {
/**
* Obtener marcadores para el mapa
*
* @param array $args Argumentos de configuración
* @return array
*/
public static function get_markers($args = []) {
$options = get_option('fp_geo_content_options', []);
$defaults = [
'post_types' => $options['post_types'] ?? [],
'lat_field' => $options['lat_field'] ?? 'latitud',
'lng_field' => $options['lng_field'] ?? 'longitud',
'taxonomies' => [],
'terms' => [],
'filter_combine' => $options['filter_combine'] ?? 'OR',
];
$args = wp_parse_args($args, $defaults);
if (empty($args['post_types'])) {
return [];
}
// Query args
$query_args = [
'post_type' => $args['post_types'],
'posts_per_page' => -1,
'post_status' => 'publish',
'meta_query' => [
'relation' => 'AND',
[
'key' => $args['lat_field'],
'compare' => 'EXISTS',
],
[
'key' => $args['lng_field'],
'compare' => 'EXISTS',
],
[
'key' => $args['lat_field'],
'value' => '',
'compare' => '!=',
],
[
'key' => $args['lng_field'],
'value' => '',
'compare' => '!=',
],
],
];
// Filtros por taxonomía
if (!empty($args['terms']) && is_array($args['terms'])) {
$tax_query = ['relation' => $args['filter_combine']];
foreach ($args['terms'] as $taxonomy => $term_slugs) {
if (!empty($term_slugs)) {
$tax_query[] = [
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => (array) $term_slugs,
];
}
}
if (count($tax_query) > 1) {
$query_args['tax_query'] = $tax_query;
}
}
$query = new WP_Query($query_args);
$markers = [];
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$post = get_post();
$marker = self::prepare_marker($post, $args);
if ($marker) {
$markers[] = $marker;
}
}
wp_reset_postdata();
}
return $markers;
}
/**
* Preparar datos de un marcador
*
* @param WP_Post $post
* @param array $args
* @return array|null
*/
private static function prepare_marker($post, $args) {
// Obtener coordenadas
$lat = get_field($args['lat_field'], $post->ID);
$lng = get_field($args['lng_field'], $post->ID);
// Si no hay coordenadas, intentar con get_post_meta
if (!$lat) {
$lat = get_post_meta($post->ID, $args['lat_field'], true);
}
if (!$lng) {
$lng = get_post_meta($post->ID, $args['lng_field'], true);
}
// Validar coordenadas
if (!$lat || !$lng || !is_numeric($lat) || !is_numeric($lng)) {
return null;
}
// Datos básicos
$marker = [
'id' => $post->ID,
'title' => html_entity_decode(get_the_title($post), ENT_QUOTES, 'UTF-8'),
'lat' => (float) $lat,
'lng' => (float) $lng,
'url' => get_permalink($post),
'post_type' => $post->post_type,
'excerpt' => wp_trim_words(get_the_excerpt($post), 20),
'thumbnail' => get_the_post_thumbnail_url($post, 'medium'),
];
// Obtener taxonomías
$options = get_option('fp_geo_content_options', []);
$filter_taxonomies = $options['filter_taxonomies'] ?? [];
$marker['taxonomies'] = [];
foreach ($filter_taxonomies as $taxonomy) {
$terms = wp_get_post_terms($post->ID, $taxonomy);
if (!is_wp_error($terms) && !empty($terms)) {
$marker['taxonomies'][$taxonomy] = [];
foreach ($terms as $term) {
$term_data = [
'id' => $term->term_id,
'name' => $term->name,
'slug' => $term->slug,
];
// Obtener campos ACF del término si existen (icono y color)
if (function_exists('get_field')) {
$icono = get_field('icono', $term);
$color = get_field('color', $term);
if ($icono) $term_data['icono'] = $icono;
if ($color) $term_data['color'] = $color;
}
$marker['taxonomies'][$taxonomy][] = $term_data;
}
}
}
// Campo es_piloto del post (para actuaciones)
$es_piloto = get_field('es_piloto', $post->ID);
if (!$es_piloto) {
$es_piloto = get_post_meta($post->ID, 'es_piloto', true);
}
if ($es_piloto) {
$marker['es_piloto'] = true;
}
// Campos adicionales comunes
$additional_fields = ['direccion', 'localidad', 'telefono', 'email', 'web'];
foreach ($additional_fields as $field) {
$value = get_field($field, $post->ID);
if (!$value) {
$value = get_post_meta($post->ID, $field, true);
}
if ($value) {
$marker[$field] = $value;
}
}
// Permitir filtrar los datos del marcador
return apply_filters('fp_geo_marker_data', $marker, $post);
}
/**
* Handler AJAX para obtener marcadores
*/
public static function ajax_get_markers() {
check_ajax_referer('fp_geo_nonce', 'nonce');
$post_types = isset($_POST['post_types']) ? array_map('sanitize_text_field', (array) $_POST['post_types']) : [];
$terms = isset($_POST['terms']) ? $_POST['terms'] : [];
// Sanitizar términos
$sanitized_terms = [];
if (is_array($terms)) {
foreach ($terms as $taxonomy => $slugs) {
$taxonomy = sanitize_text_field($taxonomy);
$sanitized_terms[$taxonomy] = array_map('sanitize_text_field', (array) $slugs);
}
}
$markers = self::get_markers([
'post_types' => $post_types,
'terms' => $sanitized_terms,
]);
wp_send_json_success(['markers' => $markers]);
}
/**
* Obtener términos disponibles para filtros
*
* @param array $post_types
* @param array $taxonomies
* @return array
*/
public static function get_filter_terms($post_types = [], $taxonomies = []) {
$result = [];
foreach ($taxonomies as $taxonomy) {
$tax_obj = get_taxonomy($taxonomy);
if (!$tax_obj) continue;
// Verificar que la taxonomía está asociada a alguno de los post types
$associated = false;
foreach ($post_types as $pt) {
if (in_array($pt, $tax_obj->object_type)) {
$associated = true;
break;
}
}
if (!$associated) continue;
$terms = get_terms([
'taxonomy' => $taxonomy,
'hide_empty' => true,
]);
if (!is_wp_error($terms) && !empty($terms)) {
$result[$taxonomy] = [
'label' => $tax_obj->label,
'terms' => [],
];
foreach ($terms as $term) {
$term_data = [
'id' => $term->term_id,
'name' => $term->name,
'slug' => $term->slug,
'count' => $term->count,
];
// Campos ACF del término (icono y color)
if (function_exists('get_field')) {
$icono = get_field('icono', $term);
$color = get_field('color', $term);
if ($icono) $term_data['icono'] = $icono;
if ($color) $term_data['color'] = $color;
}
$result[$taxonomy]['terms'][] = $term_data;
}
}
}
return $result;
}
}