$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; } }