- Add roi_output_hero_critical_css() function to inject CSS in <head>
- CSS now loads BEFORE hero HTML renders, preventing CLS
- Update min_height from 120px to 260px to match actual content height
- Update title_min_height from 3rem to 3.5rem
- Add responsive breakpoints for mobile (200px min-height)
This fixes CLS in Lighthouse Lab tests (was 0.265, now should be ~0.01)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Cambiar '/schemas' a '/Schemas' en MigrationCommand.php
- Permite que wp roi-theme sync_component funcione en servidores Linux
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Leer campos min_height, title_min_height, badge_min_height del schema
- Aplicar min-height a .hero-section (120px)
- Aplicar min-height a .hero-section__title (3rem)
- Aplicar min-height a .hero-section__badge (32px)
Fase 1 del plan de optimización PageSpeed (99-pagespeed-optimization-plan.md)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
PROBLEMA:
- El modal de contacto no se mostraba en producción (Linux)
- Funcionaba en local (Windows) porque filesystem es case-insensitive
- Carpeta: `WordPress` (con P mayúscula)
- Namespaces: `Wordpress` (con p minúscula)
SOLUCION:
- Corregir todos los namespaces de `Wordpress` a `WordPress`
- También corregir paths incorrectos `ROITheme\Component\...` a `ROITheme\Shared\...`
ARCHIVOS CORREGIDOS (14):
- functions.php
- Admin/Infrastructure/Api/WordPress/AdminMenuRegistrar.php
- Admin/Shared/Infrastructure/Api/WordPress/AdminAjaxHandler.php
- Public/ContactForm/Infrastructure/Api/WordPress/ContactFormAjaxHandler.php
- Public/Footer/Infrastructure/Api/WordPress/NewsletterAjaxHandler.php
- Shared/Infrastructure/Api/WordPress/AjaxController.php
- Shared/Infrastructure/Api/WordPress/MigrationCommand.php
- Shared/Infrastructure/Di/DIContainer.php
- Shared/Infrastructure/Persistence/WordPress/WordPressComponentRepository.php
- Shared/Infrastructure/Persistence/WordPress/WordPressComponentSettingsRepository.php
- Shared/Infrastructure/Persistence/WordPress/WordPressDefaultsRepository.php
- Shared/Infrastructure/Services/CleanupService.php
- Shared/Infrastructure/Services/SchemaSyncService.php
- Shared/Infrastructure/Services/WordPressValidationService.php
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Forces browsers to fetch updated adsense-loader.js with the
typo fix (roidsenseDelayed → roiAdsenseDelayed).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The loader was checking for window.roidsenseDelayed but PHP sets
window.roiAdsenseDelayed, causing the loader to never initialize
and AdSense scripts to remain dormant.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The AdSense delay system was stripping the ?client=ca-pub-XXXXXX
parameter from script URLs during the regex replacement, causing
ads to fail loading silently.
Changed regex patterns to use capture groups ($1) to preserve the
complete URL including query parameters.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Apply same fix to NavbarRenderer's walker class
- Only add data-bs-toggle=dropdown for items without real URL
- Fixes Buscador General link navigation
- Only add data-bs-toggle=dropdown for items without real URL
- CSS hover handles dropdown display on desktop
- Enables Buscador General link to navigate to /buscar-apus/
Added capture: true and stopImmediatePropagation() to ensure
the click handler runs before Bootstrap's dropdown handlers.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added JavaScript to handle click on dropdown-toggle links:
- On desktop (>= 992px): navigates to the href URL
- On mobile: allows Bootstrap dropdown toggle to work
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added CSS rule .no-sidebar .content-wrapper { grid-template-columns: 1fr }
to make content full-width when no sidebar is present.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Assets/Vendor/Bootstrap/ (CSS and JS)
- Add Assets/Vendor/Fonts/ (Bootstrap Icons fonts)
- Fix path references in enqueue-scripts.php to use PascalCase
- Remove vendor/ from .gitignore (not using Composer)
Fixes CSS 404 errors on Linux production server.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Rename folders to match PHP PSR-4 autoloading conventions:
- schemas → Schemas
- shared → Shared
- Wordpress → WordPress (in all locations)
Fixes deployment issues on Linux servers where filesystem is case-sensitive.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Disable lazy loading by default for featured images (LCP element)
- Add fetchpriority="high" attribute for faster loading
- Remove fetchpriority when lazy loading is enabled
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add WOFF2 font files for Poppins (400, 500, 600, 700 weights)
- Create @font-face declarations in css-global-fonts.css
- Remove Google Fonts dependency from enqueue-scripts.php
- Remove preconnect hints for fonts.googleapis.com from seo.php
Benefits:
- Eliminates 36.2 kB external transfer from Google Fonts
- Improves GDPR compliance (no Google tracking)
- Reduces render-blocking requests
- Faster font loading from local server
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add adsense group to theme-settings.json schema (v1.2.0)
- Add adsense_publisher_id and adsense_auto_ads fields
- Add AdSense card UI in ThemeSettingsFormBuilder
- Add field mappings in ThemeSettingsFieldMapper
- Add renderAdSenseAutoAds() method in ThemeSettingsRenderer
- Inject AdSense script in wp_head when configured
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Injection components (like theme-settings) are special components that:
- Don't render visual HTML (inject code into wp_head/wp_footer)
- Don't need visibility group (always enabled)
- Don't need CSSGeneratorInterface (output user-provided CSS)
- Don't need getVisibilityClasses (not responsive visual elements)
- Update Phase01Validator to skip visibility check for injection components
- Update Phase03Validator to skip CSS/visibility validations for injection components
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Script to migrate data from wp_options (roi_theme_settings)
to normalized table wp_roi_theme_component_settings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Schemas/theme-settings.json with analytics and custom_code groups
- Add ThemeSettingsFormBuilder for Admin Panel UI
- Add ThemeSettingsFieldMapper for AJAX field mapping
- Add ThemeSettingsRenderer for injecting GA/CSS/JS
- Add ThemeSettingsInjector for wp_head/wp_footer hooks
- Register component in AdminDashboardRenderer::getComponents()
- Register FieldMapper in FieldMapperProvider
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This feature was not part of the current development phase.
Deleted files:
- Inc/cta-ab-testing.php (A/B testing implementation)
- Inc/customizer-cta.php (WordPress Customizer settings + Google Analytics)
- TemplateParts/content-cta.php (CTA template part)
- Assets/Js/cta-tracking.js (GA4 tracking script)
Modified files:
- functions.php: Remove require_once for deleted files
- functions-addon.php: Remove CTA loading references
- Inc/enqueue-scripts.php: Remove roi_enqueue_cta_assets() function
Note: CTA components in Admin Panel (CtaBoxSidebar, CtaLetsTalk, CtaPost)
are NOT affected - they are part of the Clean Architecture system.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Namespace corregido de `DI` (mayúsculas) a `Di` (PascalCase)
- Consistencia con PSR-4 y convenciones del proyecto
- Detectado durante revisión del plan de refactorización
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Cambios incluidos:
- Actualización de copy/textos en 7 schemas JSON
- Mejoras en AdminAjaxHandler con mapeos adicionales
- Refactorización de FormBuilders y Renderers
- Correcciones en dashboard admin JS
- Nuevo ContactFormRenderer funcional
NOTA: Este commit sirve como respaldo antes de corregir
inconsistencias de case en namespaces (API→Api, WordPress→Wordpress)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Verificación de entorno XAMPP (PHP 8.0.30, Composer 2.9.1, WP-CLI 2.12.0)
- Configuración de Composer con PSR-4 para 24 namespaces
- Configuración de PHPUnit con 140 tests preparados
- Configuración de PHPCS con WordPress Coding Standards
- Scripts de backup y rollback con mejoras de seguridad
- Estructura de contextos (admin/, public/, shared/)
- Schemas JSON para 11 componentes del sistema
- Código fuente inicial con arquitectura limpia en src/
- Documentación de procedimientos de emergencia
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Configuración de Composer con PSR-4 en _testing-suite/
- Configuración de PHPUnit en _testing-suite/phpunit.xml
- Configuración de PHPCS en _testing-suite/phpcs.xml
- WordPress Test Suite integrado en bootstrap-integration.php
- Scripts de backup automatizado (backup-database.php, backup-files.bat)
- Procedimientos de rollback documentados (RESTORE-PROCEDURE.md)
- Estrategia de Git branching documentada (GIT-BRANCHING-STRATEGY.md)
- .gitignore actualizado para excluir _testing-suite/ y _planeacion/
- Limpieza de estructura anterior de Clean Architecture
- Documentación completa en _planeacion/roi-theme/_MIGRACION-CLEAN-ARCHITECTURE/Fase-00/
Archivos de configuración movidos a _testing-suite/:
- composer.json (PSR-4 autoloading, dev dependencies)
- phpunit.xml (3 suites: Unit, Integration, E2E)
- phpcs.xml (WordPress Coding Standards)
- bootstrap-unit.php y bootstrap-integration.php
Sistema de backup implementado con 4 mejoras críticas:
- Password protegido con --defaults-file
- Verificación de espacio en disco
- Lock files para prevenir ejecuciones concurrentes
- Detección automática de rutas
Procedimientos de rollback documentados:
- Rollback de base de datos (5-10 min)
- Rollback de archivos (10-15 min)
- Rollback de Git (5 min)
- Rollback completo (20-30 min)
Preparación del entorno completa. Listo para comenzar Fase-1.
COMPLETADO: Fase 2 de la migración a Clean Architecture + POO
## DatabaseMigrator
- ✓ Clase DatabaseMigrator con estrategia completa de migración
- ✓ Creación de tablas v2 con nueva estructura (config_group)
- ✓ Migración de datos con transformación automática
- ✓ Validación de integridad de datos migrados
- ✓ Swap seguro de tablas (legacy → _backup, v2 → producción)
- ✓ Rollback automático en caso de error
- ✓ Logging detallado de todas las operaciones
## Transformaciones de BD
- ✓ Nueva columna config_group (visibility, content, styles, general)
- ✓ Renombrado: version → schema_version
- ✓ UNIQUE KEY actualizada: (component_name, config_group, config_key)
- ✓ Nuevos índices: idx_group, idx_schema_version
- ✓ Timestamps con DEFAULT CURRENT_TIMESTAMP
## MigrationCommand (WP-CLI)
- ✓ Comando: wp roi-theme migrate
- ✓ Opción --dry-run para simulación segura
- ✓ Comando: wp roi-theme cleanup-backup
- ✓ Output formateado y detallado
- ✓ Confirmación para operaciones destructivas
- ✓ Estadísticas de migración completas
## Tests de Integración
- ✓ 6 tests de integración implementados
- ✓ Test: Creación de tablas v2
- ✓ Test: Preservación de cantidad de registros
- ✓ Test: Inferencia correcta de grupos
- ✓ Test: Creación de backup
- ✓ Test: Rollback en error
- ✓ Test: Cleanup de backup
## Heurística de Inferencia de Grupos
- enabled, visible_* → visibility
- message_*, cta_*, title_* → content
- *_color, *_height, *_width, *_size, *_font → styles
- Resto → general
## Integración
- ✓ Comando WP-CLI registrado en functions.php
- ✓ Autoloader actualizado
- ✓ Strict types en todos los archivos
- ✓ PHPDoc completo
## Validación
- ✓ Script validate-phase-2.php (26/26 checks pasados)
- ✓ Sintaxis PHP válida en todos los archivos
- ✓ 100% de validaciones exitosas
## Seguridad
- ✓ Backup automático de tablas legacy (_backup)
- ✓ Rollback automático si falla validación
- ✓ Validación de integridad antes de swap
- ✓ Logging completo para auditoría
IMPORTANTE: La migración está lista pero NO ejecutada. Ejecutar con:
1. wp db export backup-antes-migracion.sql
2. wp roi-theme migrate --dry-run
3. wp roi-theme migrate
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Configuración de Composer con PSR-4
- Configuración de PHPUnit
- Configuración de PHPCS
- Scripts de backup y rollback
- Estructura de carpetas inicial
- Documentación de procedimientos
- Agregar remove_submenu_page() para eliminar entrada duplicada
- WordPress crea automáticamente primer submenú con nombre del padre
- Ahora solo aparece submenú 'Theme Options'
- Cambiar menu slug principal a 'apus-theme-menu' (contenedor)
- Menú principal sin callback (solo contenedor del submenú)
- Submenú 'Theme Options' con slug 'apus-theme-settings' (página real)
- Actualizar hook en enqueue_assets a 'apus-theme_page_apus-theme-settings'
- Limpiar logs de debug
Ahora el menú 'Apus Theme' muestra correctamente el submenú desplegable con 'Theme Options'
- Comentar carga de admin/theme-options/theme-options.php
- Comentar carga de admin/theme-options/options-api.php
- El nuevo Admin Panel (admin/init.php) ya se carga en línea 272
- Esto elimina conflicto entre sistema viejo y nuevo
- Comentar add_theme_page() en inc/admin/theme-options.php
- Comentar add_theme_page() en admin/theme-options/theme-options.php
- Estos archivos viejos estaban registrando 'Theme Options' en menú Apariencia
- Ahora solo se usa el nuevo registro en admin/includes/class-admin-menu.php
- Elimina conflicto que mostraba el menú en dos lugares
- Cambiar de 'appearance_page_apus-theme-settings' a 'toplevel_page_apus-theme-settings'
- Necesario para que assets se carguen correctamente en menú de nivel superior
- Sin esto, el CSS/JS no se cargaba en la página de configuración
- Diagrama de arquitectura final implementada
- Estructura de tablas (defaults y components)
- Flujo de datos completo (escritura/lectura)
- Decisión arquitectónica: Opción A (wp_options para personalizaciones)
- Responsabilidades de cada clase
- Estado actual y próximos pasos
- Checklist de verificación
Completa documentación requerida por FASE 6 del plan
- Cambiar de add_theme_page() a add_menu_page()
- Posición 61 (después de Appearance, antes de Plugins)
- Ícono dashicons-admin-generic
- Menú ahora aparece al mismo nivel que Dashboard, Settings, etc.
- NO dentro del menú Apariencia
Completa PASO 2.0 del PLAN-PREPARACION-TEMA-BD.md
- Agregar constante TABLE_DEFAULTS para tabla de valores por defecto
- Modificar get_table_name() para aceptar parámetro table_type
- Actualizar create_tables() para crear ambas tablas con estructura idéntica
- Modificar todos los métodos (get_config, save_config, delete_config, list_components) para aceptar table_type
- Actualizar Settings Manager get_defaults() para leer desde tabla defaults usando DB Manager
- Mantener compatibilidad hacia atrás con valor por defecto 'components'
Arquitectura final:
- wp_apus_theme_components_defaults = Valores por defecto del tema (escritura algoritmo)
- wp_apus_theme_components = Personalizaciones del usuario (escritura admin panel)
- Una sola clase (APUS_DB_Manager) maneja ambas tablas con misma estructura
- Cambiar posición de 59 a 61
- Aclarar que debe estar AL MISMO NIVEL que Settings, Dashboard, etc.
- NO debe estar dentro de Settings ni ningún otro menú
- Agregar tabla de posiciones de menús WordPress
- Posición 61 = entre Appearance (60) y Plugins (65)