Feat: Implementar Top Bar configurable - Issue #143
Implementación completa del componente Top Bar con 15 campos configurables desde el admin panel, siguiendo el algoritmo universal v2.0. ## Cambios Realizados ### Backend (PHP) - Agregados defaults del Top Bar a class-settings-manager.php - Implementada validación completa en class-validator.php (15 campos) - Implementada sanitización con sanitize_text_field, esc_url_raw y sanitize_hex_color - Modificado header.php con código 100% configurable usando wp_parse_args() ### Frontend (Admin Panel) - Creado tab HTML completo con 3 secciones: Activación, Contenido y Estilos - Implementado JavaScript para renderizado y recolección de datos - 15 campos configurables: enabled, visibility, icon, content, link, custom styles ### Infraestructura - Creado admin-panel/init.php para carga del módulo - Creada class-admin-menu.php con enqueue de Bootstrap 5 y assets - Creada estructura base CSS y JavaScript del admin - Ya cargado en functions.php línea 276 ## Características - Responsive: Control independiente mobile/desktop - Estilos personalizables: 4 colores + tamaño de fuente - Validación robusta: Límites de caracteres, URLs, colores hex - Defaults inteligentes: Valores seguros si no hay configuración 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
183
admin-panel/includes/class-settings-manager.php
Normal file
183
admin-panel/includes/class-settings-manager.php
Normal file
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
/**
|
||||
* Settings Manager Class
|
||||
*
|
||||
* CRUD de configuraciones por componentes
|
||||
*
|
||||
* @package Apus_Theme
|
||||
* @since 2.0.0
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class APUS_Settings_Manager {
|
||||
|
||||
const OPTION_NAME = 'apus_theme_settings';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action('wp_ajax_apus_get_settings', array($this, 'ajax_get_settings'));
|
||||
add_action('wp_ajax_apus_save_settings', array($this, 'ajax_save_settings'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtener configuraciones
|
||||
*/
|
||||
public function get_settings() {
|
||||
$settings = get_option(self::OPTION_NAME, array());
|
||||
$defaults = $this->get_defaults();
|
||||
|
||||
return wp_parse_args($settings, $defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Guardar configuraciones
|
||||
*/
|
||||
public function save_settings($data) {
|
||||
// Validar
|
||||
$validator = new APUS_Validator();
|
||||
$validation = $validator->validate($data);
|
||||
|
||||
if (!$validation['valid']) {
|
||||
return array(
|
||||
'success' => false,
|
||||
'message' => 'Error de validación',
|
||||
'errors' => $validation['errors']
|
||||
);
|
||||
}
|
||||
|
||||
// Sanitizar
|
||||
$sanitized = $this->sanitize_settings($data);
|
||||
|
||||
// Agregar metadata
|
||||
$sanitized['version'] = APUS_ADMIN_PANEL_VERSION;
|
||||
$sanitized['updated_at'] = current_time('mysql');
|
||||
|
||||
// Guardar
|
||||
update_option(self::OPTION_NAME, $sanitized, false);
|
||||
|
||||
return array(
|
||||
'success' => true,
|
||||
'message' => 'Configuración guardada correctamente'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Valores por defecto
|
||||
* NOTA: Aquí se agregan los defaults de cada componente
|
||||
*/
|
||||
public function get_defaults() {
|
||||
return array(
|
||||
'version' => APUS_ADMIN_PANEL_VERSION,
|
||||
'components' => array(
|
||||
'top_bar' => array(
|
||||
'enabled' => true,
|
||||
'show_on_mobile' => true,
|
||||
'show_on_desktop' => true,
|
||||
'icon_class' => 'bi bi-megaphone-fill',
|
||||
'show_icon' => true,
|
||||
'highlight_text' => 'Nuevo:',
|
||||
'message_text' => 'Accede a más de 200,000 Análisis de Precios Unitarios actualizados para 2025.',
|
||||
'link_text' => 'Ver Catálogo',
|
||||
'link_url' => '/catalogo',
|
||||
'link_target' => '_self',
|
||||
'show_link' => true,
|
||||
'custom_styles' => array(
|
||||
'background_color' => '',
|
||||
'text_color' => '',
|
||||
'highlight_color' => '',
|
||||
'link_hover_color' => '',
|
||||
'font_size' => 'normal'
|
||||
)
|
||||
)
|
||||
// Navbar - Pendiente
|
||||
// Hero - Pendiente
|
||||
// Footer - Pendiente
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizar configuraciones
|
||||
* NOTA: Aquí se agrega sanitización de cada componente
|
||||
*/
|
||||
public function sanitize_settings($data) {
|
||||
$sanitized = array(
|
||||
'components' => array()
|
||||
);
|
||||
|
||||
// Sanitizar Top Bar
|
||||
if (isset($data['components']['top_bar'])) {
|
||||
$top_bar = $data['components']['top_bar'];
|
||||
|
||||
$sanitized['components']['top_bar'] = array(
|
||||
'enabled' => !empty($top_bar['enabled']),
|
||||
'show_on_mobile' => !empty($top_bar['show_on_mobile']),
|
||||
'show_on_desktop' => !empty($top_bar['show_on_desktop']),
|
||||
'icon_class' => sanitize_text_field($top_bar['icon_class'] ?? ''),
|
||||
'show_icon' => !empty($top_bar['show_icon']),
|
||||
'highlight_text' => sanitize_text_field($top_bar['highlight_text'] ?? ''),
|
||||
'message_text' => sanitize_text_field($top_bar['message_text'] ?? ''),
|
||||
'link_text' => sanitize_text_field($top_bar['link_text'] ?? ''),
|
||||
'link_url' => esc_url_raw($top_bar['link_url'] ?? ''),
|
||||
'link_target' => in_array($top_bar['link_target'] ?? '', array('_self', '_blank')) ? $top_bar['link_target'] : '_self',
|
||||
'show_link' => !empty($top_bar['show_link']),
|
||||
'custom_styles' => array(
|
||||
'background_color' => sanitize_hex_color($top_bar['custom_styles']['background_color'] ?? ''),
|
||||
'text_color' => sanitize_hex_color($top_bar['custom_styles']['text_color'] ?? ''),
|
||||
'highlight_color' => sanitize_hex_color($top_bar['custom_styles']['highlight_color'] ?? ''),
|
||||
'link_hover_color' => sanitize_hex_color($top_bar['custom_styles']['link_hover_color'] ?? ''),
|
||||
'font_size' => in_array($top_bar['custom_styles']['font_size'] ?? '', array('small', 'normal', 'large')) ? $top_bar['custom_styles']['font_size'] : 'normal'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: Obtener configuraciones
|
||||
*/
|
||||
public function ajax_get_settings() {
|
||||
check_ajax_referer('apus_admin_nonce', 'nonce');
|
||||
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error('Permisos insuficientes');
|
||||
}
|
||||
|
||||
$settings = $this->get_settings();
|
||||
wp_send_json_success($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: Guardar configuraciones
|
||||
*/
|
||||
public function ajax_save_settings() {
|
||||
check_ajax_referer('apus_admin_nonce', 'nonce');
|
||||
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error('Permisos insuficientes');
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (!$data) {
|
||||
wp_send_json_error('Datos inválidos');
|
||||
}
|
||||
|
||||
$result = $this->save_settings($data);
|
||||
|
||||
if ($result['success']) {
|
||||
wp_send_json_success($result);
|
||||
} else {
|
||||
wp_send_json_error($result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Instanciar clase
|
||||
new APUS_Settings_Manager();
|
||||
Reference in New Issue
Block a user