[__CLASS__, 'sanitize_options'], ]); // Sección: Tipos de contenido add_settings_section( 'fp_geo_content_types', __('Tipos de Contenido', 'fp-geo-content'), [__CLASS__, 'section_content_types'], 'fp-geo-content' ); add_settings_field( 'post_types', __('Tipos de contenido a mostrar', 'fp-geo-content'), [__CLASS__, 'field_post_types'], 'fp-geo-content', 'fp_geo_content_types' ); add_settings_field( 'lat_field', __('Campo de Latitud', 'fp-geo-content'), [__CLASS__, 'field_lat'], 'fp-geo-content', 'fp_geo_content_types' ); add_settings_field( 'lng_field', __('Campo de Longitud', 'fp-geo-content'), [__CLASS__, 'field_lng'], 'fp-geo-content', 'fp_geo_content_types' ); // Sección: Configuración del mapa add_settings_section( 'fp_geo_map_settings', __('Configuración del Mapa', 'fp-geo-content'), [__CLASS__, 'section_map_settings'], 'fp-geo-content' ); add_settings_field( 'default_center', __('Centro por defecto', 'fp-geo-content'), [__CLASS__, 'field_default_center'], 'fp-geo-content', 'fp_geo_map_settings' ); add_settings_field( 'zoom_levels', __('Niveles de zoom', 'fp-geo-content'), [__CLASS__, 'field_zoom_levels'], 'fp-geo-content', 'fp_geo_map_settings' ); add_settings_field( 'tile_provider', __('Proveedor de tiles', 'fp-geo-content'), [__CLASS__, 'field_tile_provider'], 'fp-geo-content', 'fp_geo_map_settings' ); add_settings_field( 'cluster_enabled', __('Agrupar marcadores', 'fp-geo-content'), [__CLASS__, 'field_cluster'], 'fp-geo-content', 'fp_geo_map_settings' ); add_settings_field( 'scroll_wheel_zoom', __('Zoom con scroll', 'fp-geo-content'), [__CLASS__, 'field_scroll_wheel_zoom'], 'fp-geo-content', 'fp_geo_map_settings' ); // Sección: Marcadores add_settings_section( 'fp_geo_markers', __('Marcadores', 'fp-geo-content'), [__CLASS__, 'section_markers'], 'fp-geo-content' ); add_settings_field( 'marker_icon', __('Icono personalizado', 'fp-geo-content'), [__CLASS__, 'field_marker_icon'], 'fp-geo-content', 'fp_geo_markers' ); add_settings_field( 'marker_default_color', __('Color por defecto', 'fp-geo-content'), [__CLASS__, 'field_marker_default_color'], 'fp-geo-content', 'fp_geo_markers' ); add_settings_field( 'use_category_colors', __('Colores por categoría', 'fp-geo-content'), [__CLASS__, 'field_use_category_colors'], 'fp-geo-content', 'fp_geo_markers' ); add_settings_field( 'show_legend', __('Mostrar leyenda', 'fp-geo-content'), [__CLASS__, 'field_show_legend'], 'fp-geo-content', 'fp_geo_markers' ); // Sección: Filtros add_settings_section( 'fp_geo_filters', __('Filtros', 'fp-geo-content'), [__CLASS__, 'section_filters'], 'fp-geo-content' ); add_settings_field( 'filter_taxonomies', __('Taxonomías para filtrar', 'fp-geo-content'), [__CLASS__, 'field_filter_taxonomies'], 'fp-geo-content', 'fp_geo_filters' ); add_settings_field( 'filter_combine', __('Combinación de filtros', 'fp-geo-content'), [__CLASS__, 'field_filter_combine'], 'fp-geo-content', 'fp_geo_filters' ); // Sección: Visualización add_settings_section( 'fp_geo_display', __('Visualización', 'fp-geo-content'), [__CLASS__, 'section_display'], 'fp-geo-content' ); add_settings_field( 'detail_display', __('Mostrar detalle en', 'fp-geo-content'), [__CLASS__, 'field_detail_display'], 'fp-geo-content', 'fp_geo_display' ); add_settings_field( 'sidebar_position', __('Posición del panel lateral', 'fp-geo-content'), [__CLASS__, 'field_sidebar_position'], 'fp-geo-content', 'fp_geo_display' ); add_settings_field( 'show_detail_button', __('Botón "Ver detalle"', 'fp-geo-content'), [__CLASS__, 'field_show_detail_button'], 'fp-geo-content', 'fp_geo_display' ); add_settings_field( 'detail_button_text', __('Texto del botón', 'fp-geo-content'), [__CLASS__, 'field_detail_button_text'], 'fp-geo-content', 'fp_geo_display' ); // Sección: CSS Personalizado add_settings_section( 'fp_geo_custom_css', __('CSS Personalizado', 'fp-geo-content'), [__CLASS__, 'section_custom_css'], 'fp-geo-content' ); add_settings_field( 'custom_css', __('Estilos CSS', 'fp-geo-content'), [__CLASS__, 'field_custom_css'], 'fp-geo-content', 'fp_geo_custom_css' ); } /** * Sanitizar opciones */ public static function sanitize_options($input) { $sanitized = []; // Post types $sanitized['post_types'] = isset($input['post_types']) && is_array($input['post_types']) ? array_map('sanitize_text_field', $input['post_types']) : []; // Campos de lat/lng $sanitized['lat_field'] = sanitize_text_field($input['lat_field'] ?? 'latitud'); $sanitized['lng_field'] = sanitize_text_field($input['lng_field'] ?? 'longitud'); // Centro por defecto $sanitized['default_lat'] = floatval($input['default_lat'] ?? 40.4168); $sanitized['default_lng'] = floatval($input['default_lng'] ?? -3.7038); // Zoom $sanitized['default_zoom'] = intval($input['default_zoom'] ?? 12); $sanitized['min_zoom'] = intval($input['min_zoom'] ?? 5); $sanitized['max_zoom'] = intval($input['max_zoom'] ?? 18); // Cluster $sanitized['cluster_enabled'] = isset($input['cluster_enabled']); // Tile provider $sanitized['tile_provider'] = sanitize_text_field($input['tile_provider'] ?? 'carto_light'); // Filtros $sanitized['filter_taxonomies'] = isset($input['filter_taxonomies']) && is_array($input['filter_taxonomies']) ? array_map('sanitize_text_field', $input['filter_taxonomies']) : []; $sanitized['filter_combine'] = in_array($input['filter_combine'] ?? 'OR', ['OR', 'AND']) ? $input['filter_combine'] : 'OR'; // Display $sanitized['detail_display'] = in_array($input['detail_display'] ?? 'sidebar', ['sidebar', 'modal']) ? $input['detail_display'] : 'sidebar'; // Scroll wheel zoom $sanitized['scroll_wheel_zoom'] = sanitize_text_field($input['scroll_wheel_zoom'] ?? 'ctrl'); // Marcadores $sanitized['marker_icon'] = isset($input['marker_icon']) ? absint($input['marker_icon']) : 0; $sanitized['marker_default_color'] = sanitize_hex_color($input['marker_default_color'] ?? '#F97316'); $sanitized['use_category_colors'] = isset($input['use_category_colors']); $sanitized['show_legend'] = isset($input['show_legend']); $sanitized['legend_taxonomy'] = sanitize_text_field($input['legend_taxonomy'] ?? ''); // Sidebar position $sanitized['sidebar_position'] = in_array($input['sidebar_position'] ?? 'right', ['left', 'right']) ? $input['sidebar_position'] : 'right'; // Detail button $sanitized['show_detail_button'] = isset($input['show_detail_button']); $sanitized['detail_button_text'] = sanitize_text_field($input['detail_button_text'] ?? __('Ver detalle', 'fp-geo-content')); // Custom CSS - sanitizar pero permitir CSS válido $sanitized['custom_css'] = isset($input['custom_css']) ? wp_strip_all_tags($input['custom_css']) : ''; return $sanitized; } /** * Sección: Tipos de contenido */ public static function section_content_types() { echo '
' . __('Selecciona los tipos de contenido que tienen campos de geolocalización y que quieres mostrar en el mapa.', 'fp-geo-content') . '
'; } /** * Campo: Post types */ public static function field_post_types() { $options = get_option('fp_geo_content_options', []); $selected = $options['post_types'] ?? []; // Obtener todos los post types públicos $post_types = get_post_types(['public' => true], 'objects'); echo ''; echo '' . __('Solo se mostrarán los posts que tengan coordenadas de latitud y longitud.', 'fp-geo-content') . '
'; } /** * Campo: Latitud */ public static function field_lat() { $options = get_option('fp_geo_content_options', []); $value = $options['lat_field'] ?? 'latitud'; printf( '', esc_attr($value) ); echo '' . __('Nombre del campo ACF o meta que contiene la latitud.', 'fp-geo-content') . '
'; } /** * Campo: Longitud */ public static function field_lng() { $options = get_option('fp_geo_content_options', []); $value = $options['lng_field'] ?? 'longitud'; printf( '', esc_attr($value) ); echo '' . __('Nombre del campo ACF o meta que contiene la longitud.', 'fp-geo-content') . '
'; } /** * Sección: Configuración del mapa */ public static function section_map_settings() { echo '' . __('Configura el comportamiento y apariencia del mapa.', 'fp-geo-content') . '
'; } /** * Campo: Centro por defecto */ public static function field_default_center() { $options = get_option('fp_geo_content_options', []); $lat = $options['default_lat'] ?? '40.4168'; $lng = $options['default_lng'] ?? '-3.7038'; printf( ' ', esc_attr($lat) ); printf( '', esc_attr($lng) ); echo '' . __('Coordenadas del centro inicial del mapa (por defecto: Madrid).', 'fp-geo-content') . '
'; } /** * Campo: Niveles de zoom */ public static function field_zoom_levels() { $options = get_option('fp_geo_content_options', []); $default = $options['default_zoom'] ?? 12; $min = $options['min_zoom'] ?? 5; $max = $options['max_zoom'] ?? 18; printf( ' ', esc_attr($default) ); printf( ' ', esc_attr($min) ); printf( '', esc_attr($max) ); } /** * Campo: Proveedor de tiles */ public static function field_tile_provider() { $options = get_option('fp_geo_content_options', []); $value = $options['tile_provider'] ?? 'carto_light'; $providers = [ 'osm' => 'OpenStreetMap (estándar)', 'carto_light' => 'CartoDB Positron (claro)', 'carto_dark' => 'CartoDB Dark Matter (oscuro)', 'carto_voyager' => 'CartoDB Voyager (colores)', 'stamen_toner' => 'Stamen Toner (B/N)', 'stamen_watercolor' => 'Stamen Watercolor (acuarela)', ]; echo ''; } /** * Campo: Cluster */ public static function field_cluster() { $options = get_option('fp_geo_content_options', []); $checked = isset($options['cluster_enabled']) && $options['cluster_enabled'] ? 'checked' : ''; printf( '', $checked, __('Agrupar marcadores cercanos en clusters', 'fp-geo-content') ); } /** * Sección: Filtros */ public static function section_filters() { echo '' . __('Configura qué taxonomías se pueden usar como filtros en el mapa.', 'fp-geo-content') . '
'; } /** * Campo: Taxonomías para filtrar */ public static function field_filter_taxonomies() { $options = get_option('fp_geo_content_options', []); $selected = $options['filter_taxonomies'] ?? []; // Obtener todas las taxonomías públicas $taxonomies = get_taxonomies(['public' => true], 'objects'); echo ''; } /** * Campo: Combinación de filtros */ public static function field_filter_combine() { $options = get_option('fp_geo_content_options', []); $value = $options['filter_combine'] ?? 'OR'; echo ''; } /** * Sección: Visualización */ public static function section_display() { echo '' . __('Configura cómo se muestra la información de cada marcador.', 'fp-geo-content') . '
'; } /** * Campo: Mostrar detalle */ public static function field_detail_display() { $options = get_option('fp_geo_content_options', []); $value = $options['detail_display'] ?? 'sidebar'; echo ''; echo '' . __('Cómo mostrar la ficha de detalle al hacer clic en un marcador.', 'fp-geo-content') . '
'; } /** * Campo: Scroll wheel zoom */ public static function field_scroll_wheel_zoom() { $options = get_option('fp_geo_content_options', []); $value = $options['scroll_wheel_zoom'] ?? 'ctrl'; echo ''; echo '' . __('Controla si el scroll del ratón hace zoom en el mapa. "Solo con Ctrl" permite hacer scroll en la página sin hacer zoom accidentalmente.', 'fp-geo-content') . '
'; } /** * Sección: Marcadores */ public static function section_markers() { echo '' . __('Personaliza la apariencia de los marcadores en el mapa.', 'fp-geo-content') . '
'; } /** * Campo: Icono personalizado */ public static function field_marker_icon() { $options = get_option('fp_geo_content_options', []); $image_id = $options['marker_icon'] ?? 0; $image_url = $image_id ? wp_get_attachment_image_url($image_id, 'thumbnail') : ''; echo '' . __('Opcional: Sube un icono personalizado para los marcadores. Si no se sube, se usarán círculos de color. Tamaño recomendado: 40x50px.', 'fp-geo-content') . '
'; } /** * Campo: Color por defecto */ public static function field_marker_default_color() { $options = get_option('fp_geo_content_options', []); $value = $options['marker_default_color'] ?? '#F97316'; printf( '', esc_attr($value) ); echo '' . __('Color por defecto para los marcadores cuando no tienen color de categoría asignado.', 'fp-geo-content') . '
'; } /** * Campo: Usar colores por categoría */ public static function field_use_category_colors() { $options = get_option('fp_geo_content_options', []); $checked = isset($options['use_category_colors']) && $options['use_category_colors'] ? 'checked' : ''; $legend_taxonomy = $options['legend_taxonomy'] ?? ''; printf( '', $checked, __('Usar colores de las categorías de los filtros (si tienen campo ACF "color")', 'fp-geo-content') ); // Selector de taxonomía para los colores $taxonomies = get_taxonomies(['public' => true], 'objects'); echo ''; } /** * Campo: Mostrar leyenda */ public static function field_show_legend() { $options = get_option('fp_geo_content_options', []); $checked = isset($options['show_legend']) && $options['show_legend'] ? 'checked' : ''; printf( '', $checked, __('Mostrar leyenda de colores sobre el mapa', 'fp-geo-content') ); echo '' . __('Muestra una leyenda con los colores de las categorías en la esquina del mapa.', 'fp-geo-content') . '
'; } /** * Campo: Posición del sidebar */ public static function field_sidebar_position() { $options = get_option('fp_geo_content_options', []); $value = $options['sidebar_position'] ?? 'right'; echo ''; echo '' . __('Posición del panel lateral cuando se muestra el detalle (solo aplica al modo sidebar).', 'fp-geo-content') . '
'; } /** * Campo: Mostrar botón detalle */ public static function field_show_detail_button() { $options = get_option('fp_geo_content_options', []); // Por defecto activado si no existe la opción $checked = !isset($options['show_detail_button']) || $options['show_detail_button'] ? 'checked' : ''; printf( '', $checked, __('Mostrar botón para ir al detalle del contenido', 'fp-geo-content') ); } /** * Campo: Texto del botón */ public static function field_detail_button_text() { $options = get_option('fp_geo_content_options', []); $value = $options['detail_button_text'] ?? __('Ver detalle', 'fp-geo-content'); printf( '', esc_attr($value) ); echo '' . __('Texto del botón que enlaza al contenido completo. Ejemplos: "Ver detalle", "Ver más", "Ir al contenido"...', 'fp-geo-content') . '
'; } /** * Sección: CSS Personalizado */ public static function section_custom_css() { echo '' . __('Añade CSS personalizado para sobreescribir los estilos base del mapa. Estos estilos se cargarán después de los estilos base del plugin.', 'fp-geo-content') . '
'; } /** * Campo: CSS Personalizado */ public static function field_custom_css() { $options = get_option('fp_geo_content_options', []); $value = $options['custom_css'] ?? ''; printf( '', esc_textarea($value) ); echo '' . __('Introduce CSS válido para personalizar el aspecto del mapa. No incluyas etiquetas <style>.', 'fp-geo-content') . '
'; // Mostrar clases disponibles echo '.fp-geo-wrapper - Contenedor principal.fp-geo-filters - Barra de filtros.fp-geo-filter-group - Grupo de filtros.fp-geo-filter-label - Etiqueta del grupo.fp-geo-filter-btn - Botón de filtro.fp-geo-filter-btn.active - Botón activo.fp-geo-clear-filters - Botón limpiar.fp-geo-map - Contenedor del mapa.fp-geo-legend - Leyenda.fp-geo-legend-item - Item de leyenda.fp-geo-legend-marker - Marcador en leyenda.fp-geo-detail - Panel de detalle.fp-geo-sidebar - Panel lateral.fp-geo-modal - Modal.fp-geo-detail-header - Cabecera del detalle.fp-geo-detail-title - Título.fp-geo-detail-excerpt - Extracto.fp-geo-btn - Botones.fp-geo-circle-marker - Marcadores circulares.marker-cluster - Clusters