1089 lines
32 KiB
Markdown
1089 lines
32 KiB
Markdown
# 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
|
|
<div class="wrap apus-admin-panel">
|
|
<h1>APUs Theme Settings</h1>
|
|
|
|
<!-- Tabs Bootstrap -->
|
|
<ul class="nav nav-tabs">
|
|
<li class="nav-item">
|
|
<a class="nav-link active" data-bs-toggle="tab" href="#topBarTab">
|
|
Top Bar
|
|
</a>
|
|
</li>
|
|
<!-- FALTA: Tabs para Navbar, Let's Talk, Hero -->
|
|
</ul>
|
|
|
|
<!-- Tab Content -->
|
|
<div class="tab-content">
|
|
<!-- Tab Top Bar (ÚNICO ACTIVO) -->
|
|
<div id="topBarTab" class="tab-pane fade show active">
|
|
<?php include 'component-top-bar.php'; ?>
|
|
</div>
|
|
|
|
<!-- FALTA: Tab panes para otros componentes -->
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
### Componente Top Bar: `components/component-top-bar.php`
|
|
|
|
**Estructura (16KB, 475 líneas):**
|
|
|
|
```html
|
|
<!-- Header con gradiente Navy + borde naranja -->
|
|
<div class="tab-header">
|
|
<h3>Configuración Top Bar</h3>
|
|
</div>
|
|
|
|
<!-- Grid 2 columnas responsive -->
|
|
<div class="row">
|
|
<!-- Grupo 1: Activación (col-md-6) -->
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<h4>Activación y Visibilidad</h4>
|
|
|
|
<!-- Toggle: Enabled -->
|
|
<div class="form-check form-switch">
|
|
<input type="checkbox" id="topBarEnabled">
|
|
<label>Activar Top Bar</label>
|
|
</div>
|
|
|
|
<!-- Toggle: Show on Mobile -->
|
|
<div class="form-check form-switch">
|
|
<input type="checkbox" id="topBarShowMobile">
|
|
<label>Mostrar en móvil</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Grupo 2: Colores (col-md-6) -->
|
|
<div class="col-md-6">
|
|
<div class="card">
|
|
<h4>Colores Personalizados</h4>
|
|
|
|
<!-- Color Picker: Background -->
|
|
<div class="color-picker-container">
|
|
<label>Color de fondo</label>
|
|
<input type="color" id="topBarBgColor" value="#FF8600">
|
|
<input type="text" class="hex-value" value="#FF8600">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ... más grupos (Texto, Estilos, etc.) -->
|
|
</div>
|
|
|
|
<!-- Botón guardar sticky -->
|
|
<div class="sticky-save-bar">
|
|
<button class="btn btn-primary" id="saveTopBarSettings">
|
|
Guardar cambios
|
|
</button>
|
|
</div>
|
|
```
|
|
|
|
### 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
|
|
<li class="nav-item">
|
|
<a class="nav-link" data-bs-toggle="tab" href="#navbarTab">Navbar</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" data-bs-toggle="tab" href="#letsTalkTab">Let's Talk</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" data-bs-toggle="tab" href="#heroTab">Hero Section</a>
|
|
</li>
|
|
```
|
|
|
|
---
|
|
|
|
### 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' => '<script>alert(1)</script>'];
|
|
$output = APUS_TopBar_Sanitizer::sanitize($input);
|
|
$this->assertTrue($output['enabled']);
|
|
$this->assertEquals('', $output['bg_color']); // Invalid color = empty
|
|
$this->assertStringNotContainsString('<script>', $output['text']);
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 7. **Migrar Theme Options a componentes**
|
|
|
|
**Análisis:** Theme Options actuales son configuraciones generales (logo, breadcrumbs, etc.)
|
|
|
|
**Sugerencia:** Mover a un tab dedicado "Configuración General"
|
|
|
|
**Beneficios:**
|
|
- Interfaz consistente
|
|
- Misma arquitectura DB
|
|
- Centralizar administración
|
|
|
|
**Implementación:**
|
|
```html
|
|
<!-- En main.php -->
|
|
<li class="nav-item">
|
|
<a class="nav-link" data-bs-toggle="tab" href="#generalTab">
|
|
Configuración General
|
|
</a>
|
|
</li>
|
|
|
|
<!-- Tab pane -->
|
|
<div id="generalTab" class="tab-pane fade">
|
|
<?php include APUS_ADMIN_PANEL_PATH . 'theme-options/options-page-template.php'; ?>
|
|
</div>
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Estadísticas del Código
|
|
|
|
### Distribución de archivos
|
|
|
|
| Tipo | Cantidad | Total KB |
|
|
|------|----------|----------|
|
|
| PHP (includes) | 11 | ~120 KB |
|
|
| PHP (components) | 4 | ~106 KB |
|
|
| PHP (pages) | 2 | ~20 KB |
|
|
| PHP (theme-options) | 5 | ~40 KB |
|
|
| PHP (sanitizers) | 5 | ~30 KB |
|
|
| CSS | 3 | ~25 KB |
|
|
| JS | 3 | ~39 KB |
|
|
| **TOTAL** | **33** | **~380 KB** |
|
|
|
|
### Líneas de código (estimado)
|
|
|
|
| Categoría | LOC |
|
|
|-----------|-----|
|
|
| Clases core | ~1,200 |
|
|
| Sanitizadores | ~500 |
|
|
| Componentes PHP | ~2,000 |
|
|
| Pages | ~600 |
|
|
| Theme Options | ~800 |
|
|
| JavaScript | ~600 |
|
|
| **TOTAL** | **~5,700** |
|
|
|
|
---
|
|
|
|
## 🔍 Conclusiones
|
|
|
|
### Fortalezas
|
|
|
|
✅ **Arquitectura sólida:** Separación de responsabilidades clara
|
|
✅ **Patrones modernos:** Strategy, Repository, DRY
|
|
✅ **Base de datos optimizada:** Tabla custom con versionado y tipos
|
|
✅ **Sistema de sanitización robusto:** Helper + sanitizadores específicos
|
|
✅ **Migración automática:** Proceso transparente y con backups
|
|
✅ **Frontend Bootstrap 5:** Interfaz moderna y responsive
|
|
|
|
### Debilidades
|
|
|
|
❌ **75% de código inaccesible:** 3 de 4 componentes no tienen tabs
|
|
❌ **Assets faltantes:** No hay CSS/JS específicos para 3 componentes
|
|
❌ **Optimización:** Sanitizers cargados innecesariamente
|
|
❌ **Documentación:** Sin API docs ni ejemplos de uso
|
|
❌ **Tests:** Sin cobertura automatizada
|
|
|
|
### Prioridades
|
|
|
|
1. **ALTA:** Activar tabs de Navbar, Let's Talk, Hero → Desbloquear funcionalidad
|
|
2. **ALTA:** Crear assets CSS/JS faltantes → Completar implementación
|
|
3. **MEDIA:** Mejorar validación AJAX → Seguridad
|
|
4. **MEDIA:** Documentar API → Mantenibilidad
|
|
5. **BAJA:** Optimizar carga de sanitizers → Performance marginal
|
|
6. **BAJA:** Agregar tests → Calidad a largo plazo
|
|
|
|
---
|
|
|
|
## 📝 Siguiente Paso Recomendado
|
|
|
|
**Activar componentes inactivos creando los 3 tabs faltantes en `main.php`**
|
|
|
|
Esto desbloqueará:
|
|
- 106 KB de código PHP ya implementado
|
|
- 3 formularios completos y funcionales
|
|
- Sanitizadores ya listos
|
|
- Sistema de guardado ya operativo
|
|
|
|
**Esfuerzo estimado:** 30 minutos
|
|
**Impacto:** +300% de funcionalidad disponible
|
|
|
|
---
|
|
|
|
*Documento generado automáticamente por Serena MCP + Claude Code*
|
|
*Última actualización: 2025-01-14*
|