# Análisis Profundo: Carpeta `admin/` **Fecha:** 2025-01-14 **Versión del Sistema:** 2.1.4 **Autor:** Análisis con Serena MCP + Claude Code --- ## 📋 Índice 1. [Resumen Ejecutivo](#resumen-ejecutivo) 2. [Estructura de Carpetas](#estructura-de-carpetas) 3. [Arquitectura del Sistema](#arquitectura-del-sistema) 4. [Componentes Principales](#componentes-principales) 5. [Flujo de Datos](#flujo-de-datos) 6. [Sistema de Base de Datos](#sistema-de-base-de-datos) 7. [Sistema de Migración](#sistema-de-migración) 8. [Sistema de Sanitización](#sistema-de-sanitización) 9. [Frontend del Admin Panel](#frontend-del-admin-panel) 10. [Problemas Identificados](#problemas-identificados) 11. [Recomendaciones](#recomendaciones) --- ## 🎯 Resumen Ejecutivo La carpeta `admin/` contiene **DOS sistemas administrativos consolidados**: 1. **Admin Panel** (Sistema Modular) - Panel de configuración por componentes del tema 2. **Theme Options** (Sistema Legacy) - Opciones generales del tema Ambos sistemas conviven en la misma carpeta pero funcionan de manera independiente, compartiendo: - Assets (CSS/JS) - Infraestructura de base de datos - Sistema de sanitización **Total de archivos:** 29 archivos PHP + 6 assets (CSS/JS) --- ## 📁 Estructura de Carpetas ``` admin/ ├── assets/ # Assets consolidados (Admin Panel + Theme Options) │ ├── css/ │ │ ├── admin-panel.css # Estilos core del panel modular │ │ ├── component-navbar.css # Estilos del componente Navbar │ │ └── theme-options.css # Estilos de Theme Options (legacy) │ └── js/ │ ├── admin-app.js # JavaScript core del panel modular │ ├── component-navbar.js # JavaScript del componente Navbar │ └── theme-options.js # JavaScript de Theme Options (legacy) │ ├── components/ # Componentes PHP del Admin Panel │ ├── component-top-bar.php # [ACTIVO] Formulario Top Bar (16KB, 475 líneas) │ ├── component-navbar.php # [INACTIVO] Formulario Navbar (31KB, 615 líneas) │ ├── component-lets-talk-button.php # [INACTIVO] Formulario Let's Talk (23KB) │ └── component-hero-section.php # [INACTIVO] Formulario Hero (36KB) │ ├── includes/ # Clases PHP del sistema │ ├── class-admin-menu.php # Registro de menú y carga de assets │ ├── class-db-manager.php # Gestor de base de datos (wp_apus_theme_components) │ ├── class-data-migrator.php # Migrador de datos (legacy → nueva estructura) │ ├── class-settings-manager.php # Gestor de configuraciones (AJAX handlers) │ ├── class-theme-options-migrator.php # Migrador de Theme Options │ ├── class-validator.php # Validador de datos │ └── sanitizers/ # Sanitizadores (Strategy Pattern) │ ├── class-sanitizer-helper.php # Helper DRY con métodos estáticos │ ├── class-topbar-sanitizer.php # Sanitizador Top Bar │ ├── class-navbar-sanitizer.php # Sanitizador Navbar │ ├── class-letstalkbutton-sanitizer.php # Sanitizador Let's Talk │ └── class-herosection-sanitizer.php # Sanitizador Hero Section │ ├── pages/ # Páginas del Admin Panel │ ├── main.php # Página principal (solo Tab Top Bar activo) │ └── migration.php # Página de migración de Theme Options │ ├── theme-options/ # Sistema Theme Options (Legacy) │ ├── options-api.php # API de opciones │ ├── options-page-template.php # Template HTML de la página │ ├── related-posts-options.php # Opciones de posts relacionados │ ├── theme-options.php # Registro de menú y handlers AJAX │ └── USAGE-EXAMPLES.php # Ejemplos de uso │ └── init.php # Punto de entrada del módulo ``` --- ## 🏗️ Arquitectura del Sistema ### Patrón de Diseño El sistema utiliza varios patrones: 1. **Singleton implícito**: `APUS_DB_Manager` se instancia una sola vez 2. **Strategy Pattern**: Sanitizadores específicos por componente 3. **Repository Pattern**: `APUS_DB_Manager` abstrae el acceso a datos 4. **Front Controller**: `init.php` carga todas las dependencias 5. **MVC parcial**: Separación vista (components) / lógica (includes) ### Diagrama de Dependencias ``` init.php ├── Constantes │ ├── APUS_ADMIN_PANEL_VERSION = '2.1.4' │ ├── APUS_ADMIN_PANEL_PATH = '/admin/' │ └── APUS_ADMIN_PANEL_URL = '/admin/' │ ├── Clases Core (orden de carga) │ ├── 1. APUS_Admin_Menu │ ├── 2. APUS_DB_Manager │ ├── 3. APUS_Data_Migrator │ ├── 4. APUS_Validator │ ├── 5. APUS_Theme_Options_Migrator │ ├── 6. APUS_Sanitizer_Helper │ ├── 7. Sanitizadores (TopBar, Navbar, LetsTalk, Hero) │ └── 8. APUS_Settings_Manager │ └── Hooks WordPress └── admin_init ├── APUS_Data_Migrator::maybe_migrate() └── APUS_Theme_Options_Migrator::migrate() ``` --- ## 🧩 Componentes Principales ### 1. `APUS_Admin_Menu` (class-admin-menu.php) **Responsabilidad:** Registro del menú admin y carga de assets **Métodos:** - `__construct()` - Registra hooks - `add_menu_page()` - Registra "Tema APUs" en menú Apariencia - `render_admin_page()` - Renderiza `pages/main.php` - `enqueue_assets($hook)` - Carga CSS/JS solo en página del panel **Assets cargados:** ```php // CSS - Bootstrap 5.3.2 - Bootstrap Icons 1.11.1 - admin-panel.css - component-navbar.css // JS - Bootstrap 5.3.2 - Axios 1.6.0 - component-navbar.js - admin-app.js (depende de jQuery, Axios, component-navbar.js) ``` **Ubicación en WordPress:** `Apariencia > Tema APUs` --- ### 2. `APUS_DB_Manager` (class-db-manager.php) **Responsabilidad:** Gestión de la tabla personalizada `wp_apus_theme_components` **Estructura de tabla:** ```sql CREATE TABLE wp_apus_theme_components ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, component_name VARCHAR(50) NOT NULL, -- Namespace (topbar, navbar, theme, etc.) config_key VARCHAR(100) NOT NULL, -- Clave de configuración config_value TEXT NOT NULL, -- Valor (serializado si es complejo) data_type ENUM('string','integer','boolean','array','json') DEFAULT 'string', version VARCHAR(20), -- Versión que guardó el dato created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY unique_config (component_name, config_key), INDEX idx_component (component_name), INDEX idx_updated (updated_at) ) ``` **Métodos principales:** | Método | Descripción | Uso | |--------|-------------|-----| | `save_config($component, $key, $value, $type, $version)` | Guarda/actualiza configuración | INSERT...ON DUPLICATE KEY | | `get_config($component, $key = null)` | Obtiene configuración completa o específica | SELECT WHERE component_name | | `parse_value($value, $type)` | Deserializa valores según tipo | Convierte string → tipo nativo | | `delete_config($component, $key = null)` | Elimina configuración | DELETE WHERE | | `list_components()` | Lista todos los componentes | SELECT DISTINCT component_name | **Ejemplo de uso:** ```php $db = new APUS_DB_Manager(); // Guardar $db->save_config('topbar', 'enabled', true, 'boolean', '2.1.4'); $db->save_config('topbar', 'bg_color', '#FF8600', 'string', '2.1.4'); // Obtener $config = $db->get_config('topbar'); // Array con todas las configs de topbar $enabled = $db->get_config('topbar', 'enabled'); // Solo el valor de 'enabled' ``` --- ### 3. `APUS_Settings_Manager` (class-settings-manager.php) **Responsabilidad:** Gestión de configuraciones con AJAX + sanitización **Constante:** ```php const OPTION_NAME = 'apus_admin_panel_settings'; // NOTA: No usado actualmente ``` **Métodos:** | Método | Hook AJAX | Acción | |--------|-----------|--------| | `get_settings()` | - | Obtiene configuraciones desde DB | | `save_settings($data)` | - | Sanitiza y guarda en DB | | `get_defaults()` | - | Retorna valores por defecto | | `sanitize_settings($data)` | - | Aplica sanitizadores por componente | | `ajax_get_settings()` | `wp_ajax_apus_get_settings` | Endpoint GET | | `ajax_save_settings()` | `wp_ajax_apus_save_settings` | Endpoint POST | **Flujo de sanitización:** ```php sanitize_settings($data) { // 1. Detectar componente $component = $data['component'] ?? ''; // 2. Aplicar sanitizador específico (Strategy Pattern) switch ($component) { case 'topbar': return APUS_TopBar_Sanitizer::sanitize($data); case 'navbar': return APUS_Navbar_Sanitizer::sanitize($data); case 'letstalkbutton': return APUS_LetsTalkButton_Sanitizer::sanitize($data); case 'herosection': return APUS_HeroSection_Sanitizer::sanitize($data); default: return array(); } } ``` --- ### 4. `APUS_Theme_Options_Migrator` (class-theme-options-migrator.php) **Responsabilidad:** Migrar Theme Options de `wp_options` → `wp_apus_theme_components` **Constantes:** ```php const OLD_OPTION_NAME = 'apus_theme_options'; // Ubicación antigua const COMPONENT_NAME = 'theme'; // Namespace en nueva tabla ``` **Métodos principales:** | Método | Descripción | |--------|-------------| | `is_migrated()` | Verifica si ya se migró | | `migrate()` | Ejecuta migración completa | | `create_backup($options)` | Guarda backup JSON en wp_options | | `rollback($backup_id)` | Restaura desde backup | | `list_backups()` | Lista backups disponibles | | `get_migration_stats()` | Estadísticas de migración | **Flujo de migración:** ``` 1. Verificar si ya migró → is_migrated() 2. Leer wp_options['apus_theme_options'] 3. Crear backup → create_backup() 4. Iterar cada opción: - Determinar tipo de dato → determine_data_type() - Normalizar valor → normalize_value() - Guardar en wp_apus_theme_components → save_config() 5. Eliminar de wp_options 6. Marcar como migrado ``` **Tipos de datos mapeados:** ```php get_data_types_map() { return [ // 8 integers 'site_logo' => 'integer', 'site_favicon' => 'integer', 'excerpt_length' => 'integer', 'related_posts_count' => 'integer', 'cta_icon_attachment_id' => 'integer', 'cta_box_icon_attachment_id' => 'integer', 'footer_logo_id' => 'integer', 'featured_image_height' => 'integer', // 17 booleans 'enable_breadcrumbs' => 'boolean', 'show_featured_image_single' => 'boolean', 'enable_toc' => 'boolean', // ... (14 más) // 11 strings (default, no listados) // site_name, site_tagline, copyright_text, etc. ]; } ``` --- ### 5. Sistema de Sanitización (sanitizers/) **Patrón Strategy:** Cada componente tiene su propio sanitizador #### `APUS_Sanitizer_Helper` (Helper estático DRY) **Métodos reutilizables:** ```php // Individuales sanitize_boolean($data, $key) sanitize_text($data, $key, $default = '') sanitize_color($data, $key, $default = '') sanitize_enum($data, $key, $allowed, $default) sanitize_int($data, $key, $default = 0) sanitize_float($data, $key, $default = 0.0) sanitize_url($data, $key, $default = '') // Múltiples (batch) sanitize_booleans($data, $keys) sanitize_texts($data, $keys, $default = '') sanitize_colors($data, $keys, $default = '') sanitize_enums($data, $config) sanitize_ints($data, $config) sanitize_floats($data, $config) // Grupos anidados sanitize_nested_group($data, $group_key, $rules) ``` **Ejemplo de uso:** ```php // En lugar de: $enabled = !empty($data['enabled']); $bg_color = sanitize_hex_color($data['bg_color'] ?? '#FF8600'); $text = sanitize_text_field($data['text'] ?? ''); // Usar: $booleans = APUS_Sanitizer_Helper::sanitize_booleans($data, ['enabled', 'show_mobile']); $colors = APUS_Sanitizer_Helper::sanitize_colors($data, ['bg_color', 'text_color'], '#FFFFFF'); $texts = APUS_Sanitizer_Helper::sanitize_texts($data, ['title', 'subtitle'], ''); ``` #### Sanitizadores específicos (Strategy) Cada uno implementa un método estático `sanitize($data)`: - `APUS_TopBar_Sanitizer` - 16 campos (5 bool, 5 color, 5 text, 1 enum) - `APUS_Navbar_Sanitizer` - 38 campos (grupos: activación, colores, tipografía, efectos, etc.) - `APUS_LetsTalkButton_Sanitizer` - ~15 campos - `APUS_HeroSection_Sanitizer` - ~20 campos --- ## 🔄 Flujo de Datos ### Flujo completo: Usuario → Guardar configuración ``` 1. Usuario modifica campo en admin panel ↓ 2. JavaScript detecta cambio (event listener) ↓ 3. admin-app.js recopila datos del formulario ↓ 4. Axios POST a /wp-admin/admin-ajax.php action: 'apus_save_settings' nonce: apusAdminData.nonce data: { component: 'topbar', ... } ↓ 5. WordPress enruta a APUS_Settings_Manager::ajax_save_settings() ↓ 6. Verifica nonce + permisos ↓ 7. Llama save_settings($data) ↓ 8. sanitize_settings($data) aplica sanitizador correcto ↓ 9. APUS_TopBar_Sanitizer::sanitize($data) limpia datos ↓ 10. APUS_DB_Manager::save_config() guarda en DB INSERT INTO wp_apus_theme_components (component_name, config_key, config_value, data_type, version) VALUES ('topbar', 'enabled', '1', 'boolean', '2.1.4') ON DUPLICATE KEY UPDATE config_value = '1', updated_at = NOW() ↓ 11. Retorna JSON success ↓ 12. JavaScript muestra notificación ``` ### Flujo: Cargar configuración al abrir panel ``` 1. Usuario navega a Apariencia > Tema APUs ↓ 2. APUS_Admin_Menu::render_admin_page() carga main.php ↓ 3. main.php renderiza HTML del formulario ↓ 4. admin-app.js se ejecuta (document.ready) ↓ 5. Axios GET a /wp-admin/admin-ajax.php action: 'apus_get_settings' component: 'topbar' ↓ 6. WordPress enruta a APUS_Settings_Manager::ajax_get_settings() ↓ 7. Llama get_settings('topbar') ↓ 8. APUS_DB_Manager::get_config('topbar') SELECT config_key, config_value, data_type FROM wp_apus_theme_components WHERE component_name = 'topbar' ↓ 9. parse_value() deserializa cada valor según data_type ↓ 10. Retorna JSON con configuración ↓ 11. JavaScript puebla formulario con valores ``` --- ## 💾 Sistema de Base de Datos ### Tabla: `wp_apus_theme_components` **Propósito:** Almacenar configuraciones de componentes del tema de forma estructurada **Ventajas vs wp_options:** - ✅ Versionado de configuraciones - ✅ Tipado fuerte (data_type) - ✅ Timestamps automáticos - ✅ Índices optimizados - ✅ Namespace por componente - ✅ Queries eficientes (1 query para todo el componente) **Ejemplo de datos:** ```sql -- Top Bar INSERT INTO wp_apus_theme_components VALUES (1, 'topbar', 'enabled', '1', 'boolean', '2.1.4', '2025-01-14 10:00:00', '2025-01-14 10:00:00'), (2, 'topbar', 'bg_color', '#FF8600', 'string', '2.1.4', '2025-01-14 10:00:00', '2025-01-14 10:00:00'), (3, 'topbar', 'text', '¡Oferta especial!', 'string', '2.1.4', '2025-01-14 10:00:00', '2025-01-14 10:00:00'), -- Navbar (4, 'navbar', 'enabled', '1', 'boolean', '2.1.4', '2025-01-14 10:00:00', '2025-01-14 10:00:00'), (5, 'navbar', 'sticky', '1', 'boolean', '2.1.4', '2025-01-14 10:00:00', '2025-01-14 10:00:00'), -- Theme Options (migradas) (6, 'theme', 'site_logo', '123', 'integer', '2.1.4', '2025-01-14 10:00:00', '2025-01-14 10:00:00'), (7, 'theme', 'enable_breadcrumbs', '1', 'boolean', '2.1.4', '2025-01-14 10:00:00', '2025-01-14 10:00:00'); ``` ### Estrategia de Queries ```php // ❌ Malo: 16 queries para 16 configs for ($i = 1; $i <= 16; $i++) { $value = get_option('topbar_field_' . $i); } // ✅ Bueno: 1 query para todo el componente $config = $db->get_config('topbar'); // Array con todas las 16 configs ``` --- ## 🔧 Sistema de Migración ### Migración automática en `admin_init` ```php // En init.php (líneas 54-68) add_action('admin_init', function() { $migrator = new APUS_Theme_Options_Migrator(); if (!$migrator->is_migrated()) { $result = $migrator->migrate(); if ($result['success']) { error_log('Migradas ' . $result['migrated'] . ' configuraciones'); } else { error_log('Error: ' . $result['message']); } } }); ``` ### Sistema de Backups **Formato del backup:** ```php // Guardado en wp_options $backup_key = 'apus_theme_options_backup_' . time(); $backup_data = [ 'timestamp' => time(), 'version' => APUS_ADMIN_PANEL_VERSION, 'options' => $old_options, // Array original 'count' => count($old_options) ]; update_option($backup_key, json_encode($backup_data)); ``` **Operaciones disponibles:** - `list_backups()` - Lista todos los backups - `rollback($backup_id)` - Restaura desde backup - `delete_backup($backup_id)` - Elimina backup --- ## 🎨 Frontend del Admin Panel ### Página Principal: `pages/main.php` **Estructura HTML:** ```html

APUs Theme Settings

``` ### Componente Top Bar: `components/component-top-bar.php` **Estructura (16KB, 475 líneas):** ```html

Configuración Top Bar

Activación y Visibilidad

Colores Personalizados

``` ### JavaScript: `assets/js/admin-app.js` **Responsabilidades:** - Event listeners para formularios - Validación client-side - Recopilación de datos - Requests AJAX (Axios) - Notificaciones (success/error) - Sincronización color picker ↔ hex input **Estructura:** ```javascript (function($) { 'use strict'; // 1. Cargar configuración al iniciar function loadSettings() { axios.post(apusAdminData.ajaxUrl, { action: 'apus_get_settings', component: 'topbar', nonce: apusAdminData.nonce }) .then(response => { populateForm(response.data.data); }); } // 2. Guardar al hacer clic $('#saveTopBarSettings').on('click', function() { const data = { action: 'apus_save_settings', nonce: apusAdminData.nonce, component: 'topbar', enabled: $('#topBarEnabled').is(':checked'), bg_color: $('#topBarBgColor').val(), // ... resto de campos }; axios.post(apusAdminData.ajaxUrl, data) .then(response => { showNotification('success', 'Guardado exitoso'); }); }); // 3. Sincronizar color pickers $('.color-picker-container input[type="color"]').on('change', function() { const hex = $(this).val(); $(this).siblings('.hex-value').val(hex); }); $(document).ready(function() { loadSettings(); }); })(jQuery); ``` --- ## ⚠️ Problemas Identificados ### 1. **Componentes INACTIVOS** (CRÍTICO) **Síntoma:** Solo el tab "Top Bar" está visible en `main.php` **Archivos PHP existentes pero NO utilizados:** - ❌ `components/component-navbar.php` (31KB, 615 líneas) - ❌ `components/component-lets-talk-button.php` (23KB) - ❌ `components/component-hero-section.php` (36KB) **Causa:** Nunca se agregaron los tabs correspondientes en `main.php` **Impacto:** - 90KB de código PHP inaccesible - Sanitizadores cargados pero no usados - Assets CSS/JS de navbar cargados innecesariamente - Usuarios no pueden configurar 3 de 4 componentes **Solución:** Agregar tabs en `main.php`: ```html ``` --- ### 2. **Assets CSS/JS FALTANTES** (CRÍTICO) **Assets esperados vs existentes:** | Componente | CSS | JS | Estado | |------------|-----|----|----| | Top Bar | ❌ Falta | ❌ Falta | No hay assets específicos | | Navbar | ✅ Existe | ✅ Existe | Único completo | | Let's Talk | ❌ Falta | ❌ Falta | No hay assets específicos | | Hero | ❌ Falta | ❌ Falta | No hay assets específicos | **Problema:** Los componentes usan CSS/JS genéricos pero necesitan handlers específicos **Evidencia en `class-admin-menu.php`:** ```php // Líneas 83-97 (ELIMINADO durante migración) // wp_enqueue_style('apus-component-top-bar-css', ...); ❌ No existe // wp_enqueue_script('apus-component-top-bar-js', ...); ❌ No existe ``` **Impacto:** - Funcionalidad reducida en componentes - JavaScript genérico en lugar de específico por componente --- ### 3. **Rutas duplicadas en constants** (MENOR) **Problema:** Constants en `init.php` apuntan correctamente: ```php define('APUS_ADMIN_PANEL_PATH', get_template_directory() . '/admin/'); define('APUS_ADMIN_PANEL_URL', get_template_directory_uri() . '/admin/'); ``` Pero se concatenaban con `/admin/` nuevamente: ```php // ❌ ANTES (generaba /admin/admin/pages/main.php) require_once APUS_ADMIN_PANEL_PATH . 'admin/pages/main.php'; // ✅ DESPUÉS (corregido) require_once APUS_ADMIN_PANEL_PATH . 'pages/main.php'; ``` **Estado:** ✅ CORREGIDO --- ### 4. **Theme Options sin migrar** (ADVERTENCIA) **Síntoma:** Error en debug.log: ``` APUS Theme: Error en migración de Theme Options - No hay opciones para migrar ``` **Causa:** No existe `apus_theme_options` en `wp_options` **Implicación:** - Primera instalación O - Ya se ejecutó la migración previamente O - Theme Options nunca se configuraron **Verificación necesaria:** ```sql -- Verificar si existen en nueva tabla SELECT * FROM wp_apus_theme_components WHERE component_name = 'theme'; -- Verificar si existen en wp_options SELECT * FROM wp_options WHERE option_name = 'apus_theme_options'; ``` --- ### 5. **Sanitizers cargados sin uso** (OPTIMIZACIÓN) **Problema:** Se cargan 4 sanitizadores pero solo 1 está activo: ```php // En init.php (líneas 32-36) require_once APUS_ADMIN_PANEL_PATH . 'includes/sanitizers/class-topbar-sanitizer.php'; // ✅ USADO require_once APUS_ADMIN_PANEL_PATH . 'includes/sanitizers/class-navbar-sanitizer.php'; // ❌ NO USADO require_once APUS_ADMIN_PANEL_PATH . 'includes/sanitizers/class-letstalkbutton-sanitizer.php'; // ❌ NO USADO require_once APUS_ADMIN_PANEL_PATH . 'includes/sanitizers/class-herosection-sanitizer.php'; // ❌ NO USADO ``` **Impacto:** Overhead mínimo pero innecesario **Solución:** Lazy loading o cargar solo cuando se usen --- ### 6. **Falta validación en AJAX endpoints** (SEGURIDAD) **Problema:** Validación básica pero falta sanitización profunda ```php // En class-settings-manager.php public function ajax_save_settings() { check_ajax_referer('apus_admin_nonce', 'nonce'); // ✅ OK if (!current_user_can('manage_options')) { // ✅ OK wp_send_json_error(...); } // ⚠️ FALTA: Validar estructura de $data antes de pasar a sanitize $sanitized = $this->sanitize_settings($_POST); // Potencial issue si $_POST está malformado } ``` **Recomendación:** Agregar validación de estructura: ```php if (!isset($_POST['component']) || !is_array($_POST)) { wp_send_json_error(['message' => 'Invalid data structure']); } ``` --- ## 💡 Recomendaciones ### 1. **URGENTE: Activar componentes inactivos** **Pasos:** 1. Editar `admin/pages/main.php` 2. Agregar 3 tabs nuevos (Navbar, Let's Talk, Hero) 3. Incluir archivos PHP correspondientes 4. Crear assets CSS/JS específicos si son necesarios **Impacto:** Desbloquear 75% de funcionalidad implementada pero inaccesible --- ### 2. **Crear assets faltantes** **Requerido:** - `admin/assets/css/component-top-bar.css` - `admin/assets/js/component-top-bar.js` - `admin/assets/css/component-lets-talk-button.css` - `admin/assets/js/component-lets-talk-button.js` - `admin/assets/css/component-hero-section.css` - `admin/assets/js/component-hero-section.js` **Contenido mínimo:** - CSS: Estilos específicos del tab (si necesarios) - JS: Event handlers + lógica específica del componente --- ### 3. **Optimizar carga de sanitizers** **Opción A: Lazy Loading** ```php // En init.php function apus_get_sanitizer($component) { static $sanitizers = []; if (!isset($sanitizers[$component])) { $file = "includes/sanitizers/class-{$component}-sanitizer.php"; require_once APUS_ADMIN_PANEL_PATH . $file; $sanitizers[$component] = true; } } ``` **Opción B: Autoloader** ```php spl_autoload_register(function($class) { if (strpos($class, 'APUS_') === 0 && strpos($class, '_Sanitizer') !== false) { $file = str_replace('_', '-', strtolower($class)); require_once APUS_ADMIN_PANEL_PATH . "includes/sanitizers/class-{$file}.php"; } }); ``` --- ### 4. **Mejorar validación AJAX** ```php public function ajax_save_settings() { // 1. Verificar nonce check_ajax_referer('apus_admin_nonce', 'nonce'); // 2. Verificar permisos if (!current_user_can('manage_options')) { wp_send_json_error(['message' => 'Insufficient permissions']); } // 3. Validar estructura de datos if (!isset($_POST['component']) || !is_string($_POST['component'])) { wp_send_json_error(['message' => 'Missing or invalid component']); } $allowed_components = ['topbar', 'navbar', 'letstalkbutton', 'herosection']; if (!in_array($_POST['component'], $allowed_components, true)) { wp_send_json_error(['message' => 'Invalid component name']); } // 4. Sanitizar y guardar $sanitized = $this->sanitize_settings($_POST); // ... } ``` --- ### 5. **Documentar API pública** **Crear:** `admin/API-DOCUMENTATION.md` **Contenido:** ```markdown # Admin Panel API ## Database Access ### Get component config $db = new APUS_DB_Manager(); $config = $db->get_config('topbar'); ### Save component config $db->save_config('topbar', 'enabled', true, 'boolean', '2.1.4'); ## AJAX Endpoints ### Get Settings POST /wp-admin/admin-ajax.php action: apus_get_settings component: topbar|navbar|letstalkbutton|herosection nonce: [required] ### Save Settings POST /wp-admin/admin-ajax.php action: apus_save_settings component: topbar|navbar|letstalkbutton|herosection nonce: [required] ... ``` --- ### 6. **Agregar tests automatizados** **Framework sugerido:** PHPUnit + WP_Mock **Tests críticos:** ```php // tests/test-db-manager.php class Test_APUS_DB_Manager extends WP_UnitTestCase { public function test_save_and_get_config() { $db = new APUS_DB_Manager(); $db->save_config('test', 'key', 'value', 'string', '1.0'); $value = $db->get_config('test', 'key'); $this->assertEquals('value', $value); } public function test_parse_value_boolean() { $db = new APUS_DB_Manager(); $result = $db->parse_value('1', 'boolean'); $this->assertTrue($result); } } // tests/test-sanitizers.php class Test_APUS_Sanitizers extends WP_UnitTestCase { public function test_topbar_sanitizer() { $input = ['enabled' => 'on', 'bg_color' => 'invalid', 'text' => '']; $output = APUS_TopBar_Sanitizer::sanitize($input); $this->assertTrue($output['enabled']); $this->assertEquals('', $output['bg_color']); // Invalid color = empty $this->assertStringNotContainsString('