diff --git a/404.php b/404.php index ecc45d46..21614d67 100644 --- a/404.php +++ b/404.php @@ -7,7 +7,7 @@ * * @link https://developer.wordpress.org/themes/basics/template-hierarchy/#404-not-found * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -23,7 +23,7 @@ get_header(); @@ -31,25 +31,25 @@ get_header();

- +

-

+

@@ -65,7 +65,7 @@ get_header(); if ( ! empty( $recent_posts ) ) : ?>
-

+

  • @@ -95,7 +95,7 @@ get_header(); if ( ! empty( $categories ) ) : ?>
    -

    +

    • diff --git a/admin/ANALISIS-ESTRUCTURA-ADMIN.md b/admin/ANALISIS-ESTRUCTURA-ADMIN.md deleted file mode 100644 index 4b2605ab..00000000 --- a/admin/ANALISIS-ESTRUCTURA-ADMIN.md +++ /dev/null @@ -1,1088 +0,0 @@ -# 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('\n"; - } -} -add_action('wp_head', 'example_add_custom_js_header', 100); - -/** - * EXAMPLE 12: Custom JS in footer - */ -function example_add_custom_js_footer() { - $custom_js = apus_get_custom_js_footer(); - - if ($custom_js) { - echo '\n"; - } -} -add_action('wp_footer', 'example_add_custom_js_footer', 100); - -/** - * EXAMPLE 13: Posts per page for archives - */ -function example_set_archive_posts_per_page($query) { - if ($query->is_archive() && !is_admin() && $query->is_main_query()) { - $posts_per_page = apus_get_archive_posts_per_page(); - $query->set('posts_per_page', $posts_per_page); - } -} -add_action('pre_get_posts', 'example_set_archive_posts_per_page'); - -/** - * EXAMPLE 14: Performance optimizations - */ -function example_apply_performance_settings() { - // Remove emoji scripts - if (apus_is_performance_enabled('remove_emoji')) { - remove_action('wp_head', 'print_emoji_detection_script', 7); - remove_action('wp_print_styles', 'print_emoji_styles'); - } - - // Remove embeds - if (apus_is_performance_enabled('remove_embeds')) { - wp_deregister_script('wp-embed'); - } - - // Remove Dashicons for non-logged users - if (apus_is_performance_enabled('remove_dashicons') && !is_user_logged_in()) { - wp_deregister_style('dashicons'); - } -} -add_action('wp_enqueue_scripts', 'example_apply_performance_settings', 100); - -/** - * EXAMPLE 15: Lazy loading images - */ -function example_add_lazy_loading($attr, $attachment, $size) { - if (apus_is_lazy_loading_enabled()) { - $attr['loading'] = 'lazy'; - } - return $attr; -} -add_filter('wp_get_attachment_image_attributes', 'example_add_lazy_loading', 10, 3); - -/** - * EXAMPLE 16: Layout classes based on settings - */ -function example_get_layout_class() { - $layout = 'right-sidebar'; // default - - if (is_single()) { - $layout = apus_get_default_post_layout(); - } elseif (is_page()) { - $layout = apus_get_default_page_layout(); - } - - return 'layout-' . $layout; -} - -/** - * EXAMPLE 17: Display post meta conditionally - */ -function example_display_post_meta() { - if (!apus_get_option('show_post_meta', true)) { - return; - } - - ?> - - ', ', ', '
    '); - } -} - -/** - * EXAMPLE 19: Get all options (for debugging) - */ -function example_debug_all_options() { - if (current_user_can('manage_options') && isset($_GET['debug_options'])) { - $all_options = apus_get_all_options(); - echo '
    ';
    -        print_r($all_options);
    -        echo '
    '; - } -} -add_action('wp_footer', 'example_debug_all_options'); - -/** - * EXAMPLE 20: Check if specific feature is enabled - */ -function example_check_feature() { - // Multiple ways to check boolean options - - // Method 1: Using helper function - if (apus_is_option_enabled('enable_breadcrumbs')) { - // Breadcrumbs are enabled - } - - // Method 2: Using get_option with default - if (apus_get_option('enable_related_posts', true)) { - // Related posts are enabled - } - - // Method 3: Direct check - $options = apus_get_all_options(); - if (isset($options['enable_lazy_loading']) && $options['enable_lazy_loading']) { - // Lazy loading is enabled - } -} diff --git a/inc/admin/options-api.php b/inc/admin/options-api.php deleted file mode 100644 index b46f95aa..00000000 --- a/inc/admin/options-api.php +++ /dev/null @@ -1,237 +0,0 @@ - 'apus_sanitize_options', - 'default' => apus_get_default_options(), - ) - ); - - // General Settings Section - add_settings_section( - 'apus_general_section', - __('General Settings', 'apus-theme'), - 'apus_general_section_callback', - 'apus-theme-options' - ); - - // Content Settings Section - add_settings_section( - 'apus_content_section', - __('Content Settings', 'apus-theme'), - 'apus_content_section_callback', - 'apus-theme-options' - ); - - // Performance Settings Section - add_settings_section( - 'apus_performance_section', - __('Performance Settings', 'apus-theme'), - 'apus_performance_section_callback', - 'apus-theme-options' - ); - - // Related Posts Settings Section - add_settings_section( - 'apus_related_posts_section', - __('Related Posts Settings', 'apus-theme'), - 'apus_related_posts_section_callback', - 'apus-theme-options' - ); - - // Social Share Settings Section - add_settings_section( - 'apus_social_share_section', - __('Social Share Buttons', 'apus-theme'), - 'apus_social_share_section_callback', - 'apus-theme-options' - ); -} -add_action('admin_init', 'apus_register_settings'); - -/** - * Get default options - * - * @return array - */ -function apus_get_default_options() { - return array( - // General - 'site_logo' => 0, - 'site_favicon' => 0, - 'enable_breadcrumbs' => true, - 'breadcrumb_separator' => '>', - 'date_format' => 'd/m/Y', - 'time_format' => 'H:i', - 'copyright_text' => sprintf(__('© %s %s. All rights reserved.', 'apus-theme'), date('Y'), get_bloginfo('name')), - 'social_facebook' => '', - 'social_twitter' => '', - 'social_instagram' => '', - 'social_linkedin' => '', - 'social_youtube' => '', - - // Content - 'excerpt_length' => 55, - 'excerpt_more' => '...', - 'default_post_layout' => 'right-sidebar', - 'default_page_layout' => 'right-sidebar', - 'archive_posts_per_page' => 10, - 'show_featured_image_single' => true, - 'show_author_box' => true, - 'enable_comments_posts' => true, - 'enable_comments_pages' => false, - 'show_post_meta' => true, - 'show_post_tags' => true, - 'show_post_categories' => true, - - // Performance - 'enable_lazy_loading' => true, - 'performance_remove_emoji' => true, - 'performance_remove_embeds' => false, - 'performance_remove_dashicons' => true, - 'performance_defer_js' => false, - 'performance_minify_html' => false, - 'performance_disable_gutenberg' => false, - - // Related Posts - 'enable_related_posts' => true, - 'related_posts_count' => 3, - 'related_posts_taxonomy' => 'category', - 'related_posts_title' => __('Related Posts', 'apus-theme'), - 'related_posts_columns' => 3, - - // Social Share Buttons - 'apus_enable_share_buttons' => '1', - 'apus_share_text' => __('Compartir:', 'apus-theme'), - - // Advanced - 'custom_css' => '', - 'custom_js_header' => '', - 'custom_js_footer' => '', - ); -} - -/** - * Section Callbacks - */ -function apus_general_section_callback() { - echo '

    ' . __('Configure general theme settings including logo, branding, and social media.', 'apus-theme') . '

    '; -} - -function apus_content_section_callback() { - echo '

    ' . __('Configure content display settings for posts, pages, and archives.', 'apus-theme') . '

    '; -} - -function apus_performance_section_callback() { - echo '

    ' . __('Optimize your site performance with these settings.', 'apus-theme') . '

    '; -} - -function apus_related_posts_section_callback() { - echo '

    ' . __('Configure related posts display on single post pages.', 'apus-theme') . '

    '; -} - -function apus_social_share_section_callback() { - echo '

    ' . __('Configure social share buttons display on single post pages.', 'apus-theme') . '

    '; -} - -/** - * Sanitize all options - * - * @param array $input The input array - * @return array The sanitized array - */ -function apus_sanitize_options($input) { - $sanitized = array(); - - if (!is_array($input)) { - return $sanitized; - } - - // General Settings - $sanitized['site_logo'] = isset($input['site_logo']) ? absint($input['site_logo']) : 0; - $sanitized['site_favicon'] = isset($input['site_favicon']) ? absint($input['site_favicon']) : 0; - $sanitized['enable_breadcrumbs'] = isset($input['enable_breadcrumbs']) ? (bool) $input['enable_breadcrumbs'] : false; - $sanitized['breadcrumb_separator'] = isset($input['breadcrumb_separator']) ? sanitize_text_field($input['breadcrumb_separator']) : '>'; - $sanitized['date_format'] = isset($input['date_format']) ? sanitize_text_field($input['date_format']) : 'd/m/Y'; - $sanitized['time_format'] = isset($input['time_format']) ? sanitize_text_field($input['time_format']) : 'H:i'; - $sanitized['copyright_text'] = isset($input['copyright_text']) ? wp_kses_post($input['copyright_text']) : ''; - - // Social Media - $social_fields = array('facebook', 'twitter', 'instagram', 'linkedin', 'youtube'); - foreach ($social_fields as $social) { - $key = 'social_' . $social; - $sanitized[$key] = isset($input[$key]) ? esc_url_raw($input[$key]) : ''; - } - - // Content Settings - $sanitized['excerpt_length'] = isset($input['excerpt_length']) ? absint($input['excerpt_length']) : 55; - $sanitized['excerpt_more'] = isset($input['excerpt_more']) ? sanitize_text_field($input['excerpt_more']) : '...'; - $sanitized['default_post_layout'] = isset($input['default_post_layout']) ? sanitize_text_field($input['default_post_layout']) : 'right-sidebar'; - $sanitized['default_page_layout'] = isset($input['default_page_layout']) ? sanitize_text_field($input['default_page_layout']) : 'right-sidebar'; - $sanitized['archive_posts_per_page'] = isset($input['archive_posts_per_page']) ? absint($input['archive_posts_per_page']) : 10; - $sanitized['show_featured_image_single'] = isset($input['show_featured_image_single']) ? (bool) $input['show_featured_image_single'] : false; - $sanitized['show_author_box'] = isset($input['show_author_box']) ? (bool) $input['show_author_box'] : false; - $sanitized['enable_comments_posts'] = isset($input['enable_comments_posts']) ? (bool) $input['enable_comments_posts'] : false; - $sanitized['enable_comments_pages'] = isset($input['enable_comments_pages']) ? (bool) $input['enable_comments_pages'] : false; - $sanitized['show_post_meta'] = isset($input['show_post_meta']) ? (bool) $input['show_post_meta'] : false; - $sanitized['show_post_tags'] = isset($input['show_post_tags']) ? (bool) $input['show_post_tags'] : false; - $sanitized['show_post_categories'] = isset($input['show_post_categories']) ? (bool) $input['show_post_categories'] : false; - - // Performance Settings - $sanitized['enable_lazy_loading'] = isset($input['enable_lazy_loading']) ? (bool) $input['enable_lazy_loading'] : false; - $sanitized['performance_remove_emoji'] = isset($input['performance_remove_emoji']) ? (bool) $input['performance_remove_emoji'] : false; - $sanitized['performance_remove_embeds'] = isset($input['performance_remove_embeds']) ? (bool) $input['performance_remove_embeds'] : false; - $sanitized['performance_remove_dashicons'] = isset($input['performance_remove_dashicons']) ? (bool) $input['performance_remove_dashicons'] : false; - $sanitized['performance_defer_js'] = isset($input['performance_defer_js']) ? (bool) $input['performance_defer_js'] : false; - $sanitized['performance_minify_html'] = isset($input['performance_minify_html']) ? (bool) $input['performance_minify_html'] : false; - $sanitized['performance_disable_gutenberg'] = isset($input['performance_disable_gutenberg']) ? (bool) $input['performance_disable_gutenberg'] : false; - - // Related Posts - $sanitized['enable_related_posts'] = isset($input['enable_related_posts']) ? (bool) $input['enable_related_posts'] : false; - $sanitized['related_posts_count'] = isset($input['related_posts_count']) ? absint($input['related_posts_count']) : 3; - $sanitized['related_posts_taxonomy'] = isset($input['related_posts_taxonomy']) ? sanitize_text_field($input['related_posts_taxonomy']) : 'category'; - $sanitized['related_posts_title'] = isset($input['related_posts_title']) ? sanitize_text_field($input['related_posts_title']) : __('Related Posts', 'apus-theme'); - $sanitized['related_posts_columns'] = isset($input['related_posts_columns']) ? absint($input['related_posts_columns']) : 3; - - // Social Share Buttons - $sanitized['apus_enable_share_buttons'] = isset($input['apus_enable_share_buttons']) ? sanitize_text_field($input['apus_enable_share_buttons']) : '1'; - $sanitized['apus_share_text'] = isset($input['apus_share_text']) ? sanitize_text_field($input['apus_share_text']) : __('Compartir:', 'apus-theme'); - - // Advanced Settings - $sanitized['custom_css'] = isset($input['custom_css']) ? apus_sanitize_css($input['custom_css']) : ''; - $sanitized['custom_js_header'] = isset($input['custom_js_header']) ? apus_sanitize_js($input['custom_js_header']) : ''; - $sanitized['custom_js_footer'] = isset($input['custom_js_footer']) ? apus_sanitize_js($input['custom_js_footer']) : ''; - - return $sanitized; -} - -/** - * NOTE: All sanitization functions have been moved to inc/sanitize-functions.php - * to avoid function redeclaration errors. This includes: - * - apus_sanitize_css() - * - apus_sanitize_js() - * - apus_sanitize_integer() - * - apus_sanitize_text() - * - apus_sanitize_url() - * - apus_sanitize_html() - * - apus_sanitize_checkbox() - * - apus_sanitize_select() - */ diff --git a/inc/admin/options-page-template.php b/inc/admin/options-page-template.php deleted file mode 100644 index 325748a9..00000000 --- a/inc/admin/options-page-template.php +++ /dev/null @@ -1,661 +0,0 @@ - - -
    -

    - -
    - -
    - - - -
    -
    - -
    - - -
    - -
    - -
    - - -
    - - -
    -

    -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - -
    - -
    - 'apus-preview-image')); - } - ?> -
    - - -

    -
    -
    - - -
    - -
    - 'apus-preview-image')); - } - ?> -
    - - -

    -
    -
    - - - -

    -
    - - - -

    , /, »)', 'apus-theme'); ?>

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - -
    - - - -
    - - - -
    - - - -
    - - - -
    -
    - - -
    -

    -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    -
    - - -
    -

    -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    -
    - - - - - -
    -

    -

    - - - - - - - - - - - - - - - - - - - -
    - - - -

    -
    - - - -

    -
    - - - -

    -
    -
    - -
    -
    - - -
    -
    - - - diff --git a/inc/admin/related-posts-options.php b/inc/admin/related-posts-options.php deleted file mode 100644 index 40de6637..00000000 --- a/inc/admin/related-posts-options.php +++ /dev/null @@ -1,272 +0,0 @@ - array( - 'key' => 'apus_related_posts_enabled', - 'value' => get_option('apus_related_posts_enabled', true), - 'type' => 'boolean', - 'default' => true, - 'label' => __('Enable Related Posts', 'apus-theme'), - 'description' => __('Show related posts section at the end of single posts', 'apus-theme'), - ), - 'title' => array( - 'key' => 'apus_related_posts_title', - 'value' => get_option('apus_related_posts_title', __('Related Posts', 'apus-theme')), - 'type' => 'text', - 'default' => __('Related Posts', 'apus-theme'), - 'label' => __('Section Title', 'apus-theme'), - 'description' => __('Title displayed above related posts', 'apus-theme'), - ), - 'count' => array( - 'key' => 'apus_related_posts_count', - 'value' => get_option('apus_related_posts_count', 3), - 'type' => 'number', - 'default' => 3, - 'min' => 1, - 'max' => 12, - 'label' => __('Number of Posts', 'apus-theme'), - 'description' => __('Maximum number of related posts to display', 'apus-theme'), - ), - 'columns' => array( - 'key' => 'apus_related_posts_columns', - 'value' => get_option('apus_related_posts_columns', 3), - 'type' => 'select', - 'default' => 3, - 'options' => array( - 1 => __('1 Column', 'apus-theme'), - 2 => __('2 Columns', 'apus-theme'), - 3 => __('3 Columns', 'apus-theme'), - 4 => __('4 Columns', 'apus-theme'), - ), - 'label' => __('Grid Columns', 'apus-theme'), - 'description' => __('Number of columns in the grid layout (responsive)', 'apus-theme'), - ), - 'show_excerpt' => array( - 'key' => 'apus_related_posts_show_excerpt', - 'value' => get_option('apus_related_posts_show_excerpt', true), - 'type' => 'boolean', - 'default' => true, - 'label' => __('Show Excerpt', 'apus-theme'), - 'description' => __('Display post excerpt in related posts cards', 'apus-theme'), - ), - 'excerpt_length' => array( - 'key' => 'apus_related_posts_excerpt_length', - 'value' => get_option('apus_related_posts_excerpt_length', 20), - 'type' => 'number', - 'default' => 20, - 'min' => 5, - 'max' => 100, - 'label' => __('Excerpt Length', 'apus-theme'), - 'description' => __('Number of words in the excerpt', 'apus-theme'), - ), - 'show_date' => array( - 'key' => 'apus_related_posts_show_date', - 'value' => get_option('apus_related_posts_show_date', true), - 'type' => 'boolean', - 'default' => true, - 'label' => __('Show Date', 'apus-theme'), - 'description' => __('Display publication date in related posts', 'apus-theme'), - ), - 'show_category' => array( - 'key' => 'apus_related_posts_show_category', - 'value' => get_option('apus_related_posts_show_category', true), - 'type' => 'boolean', - 'default' => true, - 'label' => __('Show Category', 'apus-theme'), - 'description' => __('Display category badge on related posts', 'apus-theme'), - ), - 'bg_colors' => array( - 'key' => 'apus_related_posts_bg_colors', - 'value' => get_option('apus_related_posts_bg_colors', array( - '#1a73e8', '#e91e63', '#4caf50', '#ff9800', '#9c27b0', '#00bcd4', - )), - 'type' => 'color_array', - 'default' => array( - '#1a73e8', // Blue - '#e91e63', // Pink - '#4caf50', // Green - '#ff9800', // Orange - '#9c27b0', // Purple - '#00bcd4', // Cyan - ), - 'label' => __('Background Colors', 'apus-theme'), - 'description' => __('Colors used for posts without featured images', 'apus-theme'), - ), - ); -} - -/** - * Update a related posts option - * - * @param string $option_key The option key (without 'apus_related_posts_' prefix) - * @param mixed $value The new value - * @return bool True if updated successfully - */ -function apus_update_related_posts_option($option_key, $value) { - $full_key = 'apus_related_posts_' . $option_key; - return update_option($full_key, $value); -} - -/** - * Reset related posts options to defaults - * - * @return bool True if reset successfully - */ -function apus_reset_related_posts_options() { - $options = apus_get_related_posts_options(); - $success = true; - - foreach ($options as $option) { - if (!update_option($option['key'], $option['default'])) { - $success = false; - } - } - - return $success; -} - -/** - * Example: Programmatically configure related posts - * - * This function shows how to configure related posts options programmatically. - * You can call this from your functions.php or a plugin. - * - * @return void - */ -function apus_example_configure_related_posts() { - // Example usage - uncomment to use: - - // Enable related posts - // update_option('apus_related_posts_enabled', true); - - // Set custom title - // update_option('apus_related_posts_title', __('You Might Also Like', 'apus-theme')); - - // Show 4 related posts - // update_option('apus_related_posts_count', 4); - - // Use 2 columns layout - // update_option('apus_related_posts_columns', 2); - - // Show excerpt with 30 words - // update_option('apus_related_posts_show_excerpt', true); - // update_option('apus_related_posts_excerpt_length', 30); - - // Show date and category - // update_option('apus_related_posts_show_date', true); - // update_option('apus_related_posts_show_category', true); - - // Custom background colors for posts without images - // update_option('apus_related_posts_bg_colors', array( - // '#FF6B6B', // Red - // '#4ECDC4', // Teal - // '#45B7D1', // Blue - // '#FFA07A', // Coral - // '#98D8C8', // Mint - // '#F7DC6F', // Yellow - // )); -} - -/** - * Filter hook example: Modify related posts query - * - * This example shows how to customize the related posts query. - * Add this to your functions.php or child theme. - */ -function apus_example_modify_related_posts_query($args, $post_id) { - // Example: Order by date instead of random - // $args['orderby'] = 'date'; - // $args['order'] = 'DESC'; - - // Example: Only show posts from the last 6 months - // $args['date_query'] = array( - // array( - // 'after' => '6 months ago', - // ), - // ); - - // Example: Exclude specific category - // $args['category__not_in'] = array(5); // Replace 5 with category ID - - return $args; -} -// add_filter('apus_related_posts_args', 'apus_example_modify_related_posts_query', 10, 2); - -/** - * Get documentation for related posts configuration - * - * @return array Documentation array - */ -function apus_get_related_posts_documentation() { - return array( - 'overview' => array( - 'title' => __('Related Posts Overview', 'apus-theme'), - 'content' => __( - 'The related posts feature automatically displays relevant posts at the end of each blog post. ' . - 'Posts are related based on shared categories and displayed in a responsive Bootstrap grid.', - 'apus-theme' - ), - ), - 'features' => array( - 'title' => __('Key Features', 'apus-theme'), - 'items' => array( - __('Automatic category-based matching', 'apus-theme'), - __('Responsive Bootstrap 5 grid layout', 'apus-theme'), - __('Configurable number of posts and columns', 'apus-theme'), - __('Support for posts with and without featured images', 'apus-theme'), - __('Beautiful color backgrounds for posts without images', 'apus-theme'), - __('Customizable excerpt length', 'apus-theme'), - __('Optional display of dates and categories', 'apus-theme'), - __('Smooth hover animations', 'apus-theme'), - __('Print-friendly styles', 'apus-theme'), - __('Dark mode support', 'apus-theme'), - ), - ), - 'configuration' => array( - 'title' => __('How to Configure', 'apus-theme'), - 'methods' => array( - 'database' => array( - 'title' => __('Via WordPress Options API', 'apus-theme'), - 'code' => "update_option('apus_related_posts_enabled', true);\nupdate_option('apus_related_posts_count', 4);", - ), - 'filter' => array( - 'title' => __('Via Filter Hook', 'apus-theme'), - 'code' => "add_filter('apus_related_posts_args', function(\$args, \$post_id) {\n \$args['posts_per_page'] = 6;\n return \$args;\n}, 10, 2);", - ), - ), - ), - 'customization' => array( - 'title' => __('Customization Examples', 'apus-theme'), - 'examples' => array( - array( - 'title' => __('Change title and layout', 'apus-theme'), - 'code' => "update_option('apus_related_posts_title', 'También te puede interesar');\nupdate_option('apus_related_posts_columns', 4);", - ), - array( - 'title' => __('Customize colors', 'apus-theme'), - 'code' => "update_option('apus_related_posts_bg_colors', array(\n '#FF6B6B',\n '#4ECDC4',\n '#45B7D1'\n));", - ), - ), - ), - ); -} diff --git a/inc/admin/theme-options.php b/inc/admin/theme-options.php deleted file mode 100644 index de75cd82..00000000 --- a/inc/admin/theme-options.php +++ /dev/null @@ -1,217 +0,0 @@ - admin_url('admin-ajax.php'), - 'nonce' => wp_create_nonce('apus_admin_nonce'), - 'strings' => array( - 'selectImage' => __('Select Image', 'apus-theme'), - 'useImage' => __('Use Image', 'apus-theme'), - 'removeImage' => __('Remove Image', 'apus-theme'), - 'confirmReset' => __('Are you sure you want to reset all options to default values? This cannot be undone.', 'apus-theme'), - 'saved' => __('Settings saved successfully!', 'apus-theme'), - 'error' => __('An error occurred while saving settings.', 'apus-theme'), - ), - )); -} -add_action('admin_enqueue_scripts', 'apus_enqueue_admin_scripts'); - -/** - * Add settings link to theme actions - */ -function apus_add_settings_link($links) { - $settings_link = '' . __('Settings', 'apus-theme') . ''; - array_unshift($links, $settings_link); - return $links; -} -add_filter('theme_action_links_' . get_template(), 'apus_add_settings_link'); - -/** - * AJAX handler for resetting options - */ -function apus_reset_options_ajax() { - check_ajax_referer('apus_admin_nonce', 'nonce'); - - if (!current_user_can('manage_options')) { - wp_send_json_error(array('message' => __('Insufficient permissions.', 'apus-theme'))); - } - - // Delete options to reset to defaults - delete_option('apus_theme_options'); - - wp_send_json_success(array('message' => __('Options reset to defaults successfully.', 'apus-theme'))); -} -add_action('wp_ajax_apus_reset_options', 'apus_reset_options_ajax'); - -/** - * AJAX handler for exporting options - */ -function apus_export_options_ajax() { - check_ajax_referer('apus_admin_nonce', 'nonce'); - - if (!current_user_can('manage_options')) { - wp_send_json_error(array('message' => __('Insufficient permissions.', 'apus-theme'))); - } - - $options = get_option('apus_theme_options', array()); - - wp_send_json_success(array( - 'data' => json_encode($options, JSON_PRETTY_PRINT), - 'filename' => 'apus-theme-options-' . date('Y-m-d') . '.json' - )); -} -add_action('wp_ajax_apus_export_options', 'apus_export_options_ajax'); - -/** - * AJAX handler for importing options - */ -function apus_import_options_ajax() { - check_ajax_referer('apus_admin_nonce', 'nonce'); - - if (!current_user_can('manage_options')) { - wp_send_json_error(array('message' => __('Insufficient permissions.', 'apus-theme'))); - } - - if (!isset($_POST['import_data'])) { - wp_send_json_error(array('message' => __('No import data provided.', 'apus-theme'))); - } - - $import_data = json_decode(stripslashes($_POST['import_data']), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - wp_send_json_error(array('message' => __('Invalid JSON data.', 'apus-theme'))); - } - - // Sanitize imported data - $sanitized_data = apus_sanitize_options($import_data); - - // Update options - update_option('apus_theme_options', $sanitized_data); - - wp_send_json_success(array('message' => __('Options imported successfully.', 'apus-theme'))); -} -add_action('wp_ajax_apus_import_options', 'apus_import_options_ajax'); - -/** - * Add admin notices - */ -function apus_admin_notices() { - $screen = get_current_screen(); - if ($screen->id !== 'appearance_page_apus-theme-options') { - return; - } - - // Check if settings were updated - if (isset($_GET['settings-updated']) && $_GET['settings-updated'] === 'true') { - ?> -
    -

    -
    - add_panel('apus_theme_options', array( - 'title' => __('Apus Theme Options', 'apus-theme'), - 'description' => __('Configure theme options (Also available in Theme Options page)', 'apus-theme'), - 'priority' => 10, - )); - - // General Section - $wp_customize->add_section('apus_general', array( - 'title' => __('General Settings', 'apus-theme'), - 'panel' => 'apus_theme_options', - 'priority' => 10, - )); - - // Enable breadcrumbs - $wp_customize->add_setting('apus_theme_options[enable_breadcrumbs]', array( - 'default' => true, - 'type' => 'option', - 'sanitize_callback' => 'apus_sanitize_checkbox', - )); - - $wp_customize->add_control('apus_theme_options[enable_breadcrumbs]', array( - 'label' => __('Enable Breadcrumbs', 'apus-theme'), - 'section' => 'apus_general', - 'type' => 'checkbox', - )); -} -add_action('customize_register', 'apus_customize_register'); diff --git a/inc/adsense-delay.php b/inc/adsense-delay.php index f7a3974b..7a125fb9 100644 --- a/inc/adsense-delay.php +++ b/inc/adsense-delay.php @@ -5,7 +5,7 @@ * Delays the loading of AdSense scripts until user interaction or timeout * to improve initial page load performance. * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -20,23 +20,23 @@ if (!defined('ABSPATH')) { * Esta función inicia el output buffering y reemplaza los scripts de AdSense * con versiones retrasadas cuando se renderiza la página. */ -function apus_delay_adsense_scripts() { +function roi_delay_adsense_scripts() { // Solo ejecutar en frontend if (is_admin()) { return; } // Verificar si el retardo de AdSense está habilitado en las opciones del tema - $delay_enabled = apus_get_option('apus_adsense_delay_enabled', '1'); + $delay_enabled = roi_get_option('roi_adsense_delay_enabled', '1'); if ($delay_enabled !== '1') { return; } // Iniciar output buffering - ob_start('apus_replace_adsense_scripts'); + ob_start('roi_replace_adsense_scripts'); } -add_action('template_redirect', 'apus_delay_adsense_scripts', 1); +add_action('template_redirect', 'roi_delay_adsense_scripts', 1); /** * Reemplaza scripts de AdSense con versiones retrasadas @@ -47,7 +47,7 @@ add_action('template_redirect', 'apus_delay_adsense_scripts', 1); * @param string $html El contenido HTML a procesar * @return string HTML modificado con scripts de AdSense retrasados */ -function apus_replace_adsense_scripts($html) { +function roi_replace_adsense_scripts($html) { // Solo procesar si hay contenido real de AdSense if (strpos($html, 'pagead2.googlesyndication.com') === false && strpos($html, 'adsbygoogle.js') === false) { @@ -93,7 +93,7 @@ function apus_replace_adsense_scripts($html) { // Agregar comentario para indicar que se procesó (solo en modo debug) if (defined('WP_DEBUG') && WP_DEBUG) { - $html = str_replace('', '', $html); + $html = str_replace('', '', $html); } return $html; @@ -105,8 +105,8 @@ function apus_replace_adsense_scripts($html) { * Esto agrega un pequeño script inline que marca AdSense como listo para cargar * después de que adsense-loader.js ha sido enqueued. */ -function apus_add_adsense_init_script() { - $delay_enabled = apus_get_option('apus_adsense_delay_enabled', '1'); +function roi_add_adsense_init_script() { + $delay_enabled = roi_get_option('roi_adsense_delay_enabled', '1'); if ($delay_enabled !== '1' || is_admin()) { return; @@ -115,17 +115,17 @@ function apus_add_adsense_init_script() { ?> Apus Theme Options) + * 1. Ir al panel de opciones del tema (Dashboard > ROI Theme Options) * 2. En la sección "Performance", activar la opción "Delay AdSense Loading" * 3. Guardar cambios * diff --git a/inc/apu-tables.php b/inc/apu-tables.php index 7140f9ed..f26b5d7e 100644 --- a/inc/apu-tables.php +++ b/inc/apu-tables.php @@ -21,7 +21,7 @@ if (!defined('ABSPATH')) { * @param string $content El contenido del post * @return string El contenido procesado */ -function apus_process_apu_tables($content) { +function roi_process_apu_tables($content) { // Verificar que haya contenido if (empty($content)) { return $content; @@ -45,7 +45,7 @@ function apus_process_apu_tables($content) { return $content; } -add_filter('the_content', 'apus_process_apu_tables', 20); +add_filter('the_content', 'roi_process_apu_tables', 20); /** * Shortcode: [apu_table] @@ -63,7 +63,7 @@ add_filter('the_content', 'apus_process_apu_tables', 20); * @param string $content Contenido del shortcode * @return string HTML procesado */ -function apus_apu_table_shortcode($atts, $content = null) { +function roi_apu_table_shortcode($atts, $content = null) { // Verificar que haya contenido if (empty($content)) { return ''; @@ -75,7 +75,7 @@ function apus_apu_table_shortcode($atts, $content = null) { // Envolver con la clase .analisis return '
    ' . $content . '
    '; } -add_shortcode('apu_table', 'apus_apu_table_shortcode'); +add_shortcode('apu_table', 'roi_apu_table_shortcode'); /** * Shortcode: [apu_row type="tipo"] @@ -100,7 +100,7 @@ add_shortcode('apu_table', 'apus_apu_table_shortcode'); * @param string $content Contenido del shortcode * @return string HTML procesado */ -function apus_apu_row_shortcode($atts, $content = null) { +function roi_apu_row_shortcode($atts, $content = null) { // Atributos por defecto $atts = shortcode_atts( array( @@ -141,7 +141,7 @@ function apus_apu_row_shortcode($atts, $content = null) { return '' . $content . ''; } } -add_shortcode('apu_row', 'apus_apu_row_shortcode'); +add_shortcode('apu_row', 'roi_apu_row_shortcode'); /** * Función helper para generar una tabla APU completa @@ -175,7 +175,7 @@ add_shortcode('apu_row', 'apus_apu_row_shortcode'); * 'total' => '$3,283.52' * ) */ -function apus_generate_apu_table($data) { +function roi_generate_apu_table($data) { // Validar datos mínimos if (empty($data) || !isset($data['sections'])) { return ''; @@ -268,7 +268,7 @@ function apus_generate_apu_table($data) { * @param array $classes Array de clases del body * @return array Array modificado de clases */ -function apus_add_apu_body_class($classes) { +function roi_add_apu_body_class($classes) { // Solo en posts individuales if (is_single()) { global $post; @@ -283,7 +283,7 @@ function apus_add_apu_body_class($classes) { return $classes; } -add_filter('body_class', 'apus_add_apu_body_class'); +add_filter('body_class', 'roi_add_apu_body_class'); /** * Permitir ciertos atributos HTML en tablas para el editor @@ -295,7 +295,7 @@ add_filter('body_class', 'apus_add_apu_body_class'); * @param string $context Contexto de uso * @return array Array modificado de tags permitidos */ -function apus_allow_apu_table_attributes($allowed_tags, $context) { +function roi_allow_apu_table_attributes($allowed_tags, $context) { if ($context === 'post') { // Permitir atributo data-apu en tablas if (isset($allowed_tags['table'])) { @@ -313,4 +313,4 @@ function apus_allow_apu_table_attributes($allowed_tags, $context) { return $allowed_tags; } -add_filter('wp_kses_allowed_html', 'apus_allow_apu_table_attributes', 10, 2); +add_filter('wp_kses_allowed_html', 'roi_allow_apu_table_attributes', 10, 2); diff --git a/inc/category-badge.php b/inc/category-badge.php index 009ddf28..7e8be8f2 100644 --- a/inc/category-badge.php +++ b/inc/category-badge.php @@ -5,7 +5,7 @@ * Funciones para mostrar badge de categoría sobre el H1 en single posts. * Utiliza clases de Bootstrap para el estilo del badge. * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -23,9 +23,9 @@ if (!defined('ABSPATH')) { * * @return string HTML del badge de categoría o string vacío */ -function apus_get_category_badge() { +function roi_get_category_badge() { // Verificar si la función está habilitada en las opciones del tema - $enabled = apus_get_option('show_category_badge', true); + $enabled = roi_get_option('show_category_badge', true); if (!$enabled) { return ''; } @@ -72,10 +72,10 @@ function apus_get_category_badge() { * Muestra el badge de categoría * * Template tag para imprimir directamente el badge de categoría. - * Uso en templates: + * Uso en templates: * * @return void */ -function apus_display_category_badge() { - echo apus_get_category_badge(); +function roi_display_category_badge() { + echo roi_get_category_badge(); } diff --git a/inc/comments-disable.php b/inc/comments-disable.php index a4800f13..aa7a3583 100644 --- a/inc/comments-disable.php +++ b/inc/comments-disable.php @@ -5,7 +5,7 @@ * Este archivo desactiva completamente los comentarios en WordPress, * tanto en el frontend como en el área de administración. * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 * @link https://github.com/prime-leads-app/analisisdepreciosunitarios.com/issues/4 */ @@ -24,11 +24,11 @@ if (!defined('ABSPATH')) { * @param bool $open Si los comentarios están abiertos o no. * @return bool Siempre retorna false. */ -function apus_disable_comments_status() { +function roi_disable_comments_status() { return false; } -add_filter('comments_open', 'apus_disable_comments_status', 20, 2); -add_filter('pings_open', 'apus_disable_comments_status', 20, 2); +add_filter('comments_open', 'roi_disable_comments_status', 20, 2); +add_filter('pings_open', 'roi_disable_comments_status', 20, 2); /** * Ocultar comentarios existentes @@ -39,10 +39,10 @@ add_filter('pings_open', 'apus_disable_comments_status', 20, 2); * @param array $comments Array de comentarios. * @return array Array vacío. */ -function apus_hide_existing_comments($comments) { +function roi_hide_existing_comments($comments) { return array(); } -add_filter('comments_array', 'apus_hide_existing_comments', 10, 2); +add_filter('comments_array', 'roi_hide_existing_comments', 10, 2); /** * Desactivar feeds de comentarios @@ -51,25 +51,25 @@ add_filter('comments_array', 'apus_hide_existing_comments', 10, 2); * * @since 1.0.0 */ -function apus_disable_comment_feeds() { +function roi_disable_comment_feeds() { // Remover enlaces de feeds de comentarios remove_action('wp_head', 'feed_links_extra', 3); // Desactivar feeds de comentarios - add_action('do_feed_rss2_comments', 'apus_disable_feed_comments'); - add_action('do_feed_atom_comments', 'apus_disable_feed_comments'); + add_action('do_feed_rss2_comments', 'roi_disable_feed_comments'); + add_action('do_feed_atom_comments', 'roi_disable_feed_comments'); } -add_action('init', 'apus_disable_comment_feeds'); +add_action('init', 'roi_disable_comment_feeds'); /** * Retornar error en feeds de comentarios * * @since 1.0.0 */ -function apus_disable_feed_comments() { +function roi_disable_feed_comments() { wp_die( - esc_html__('Los comentarios están desactivados en este sitio.', 'apus-theme'), - esc_html__('Comentarios no disponibles', 'apus-theme'), + esc_html__('Los comentarios están desactivados en este sitio.', 'roi-theme'), + esc_html__('Comentarios no disponibles', 'roi-theme'), array( 'response' => 404, 'back_link' => true, @@ -84,10 +84,10 @@ function apus_disable_feed_comments() { * * @since 1.0.0 */ -function apus_disable_comment_reply_script() { +function roi_disable_comment_reply_script() { wp_deregister_script('comment-reply'); } -add_action('wp_enqueue_scripts', 'apus_disable_comment_reply_script', 100); +add_action('wp_enqueue_scripts', 'roi_disable_comment_reply_script', 100); /** * Remover menú de comentarios del admin @@ -96,10 +96,10 @@ add_action('wp_enqueue_scripts', 'apus_disable_comment_reply_script', 100); * * @since 1.0.0 */ -function apus_remove_comments_admin_menu() { +function roi_remove_comments_admin_menu() { remove_menu_page('edit-comments.php'); } -add_action('admin_menu', 'apus_remove_comments_admin_menu'); +add_action('admin_menu', 'roi_remove_comments_admin_menu'); /** * Remover comentarios de la admin bar @@ -109,10 +109,10 @@ add_action('admin_menu', 'apus_remove_comments_admin_menu'); * @since 1.0.0 * @param WP_Admin_Bar $wp_admin_bar Instancia de WP_Admin_Bar. */ -function apus_remove_comments_admin_bar($wp_admin_bar) { +function roi_remove_comments_admin_bar($wp_admin_bar) { $wp_admin_bar->remove_menu('comments'); } -add_action('admin_bar_menu', 'apus_remove_comments_admin_bar', 60); +add_action('admin_bar_menu', 'roi_remove_comments_admin_bar', 60); /** * Remover metabox de comentarios del editor @@ -121,7 +121,7 @@ add_action('admin_bar_menu', 'apus_remove_comments_admin_bar', 60); * * @since 1.0.0 */ -function apus_remove_comments_metabox() { +function roi_remove_comments_metabox() { // Post types por defecto remove_meta_box('commentstatusdiv', 'post', 'normal'); remove_meta_box('commentstatusdiv', 'page', 'normal'); @@ -139,7 +139,7 @@ function apus_remove_comments_metabox() { } } } -add_action('admin_init', 'apus_remove_comments_metabox'); +add_action('admin_init', 'roi_remove_comments_metabox'); /** * Ocultar columna de comentarios en listados del admin @@ -150,14 +150,14 @@ add_action('admin_init', 'apus_remove_comments_metabox'); * @param array $columns Columnas actuales. * @return array Columnas modificadas sin comentarios. */ -function apus_remove_comments_column($columns) { +function roi_remove_comments_column($columns) { unset($columns['comments']); return $columns; } // Aplicar a posts y páginas -add_filter('manage_posts_columns', 'apus_remove_comments_column'); -add_filter('manage_pages_columns', 'apus_remove_comments_column'); +add_filter('manage_posts_columns', 'roi_remove_comments_column'); +add_filter('manage_pages_columns', 'roi_remove_comments_column'); /** * Desactivar widgets de comentarios @@ -166,10 +166,10 @@ add_filter('manage_pages_columns', 'apus_remove_comments_column'); * * @since 1.0.0 */ -function apus_disable_comments_widgets() { +function roi_disable_comments_widgets() { unregister_widget('WP_Widget_Recent_Comments'); } -add_action('widgets_init', 'apus_disable_comments_widgets'); +add_action('widgets_init', 'roi_disable_comments_widgets'); /** * Remover estilos CSS de comentarios recientes @@ -178,7 +178,7 @@ add_action('widgets_init', 'apus_disable_comments_widgets'); * * @since 1.0.0 */ -function apus_remove_recent_comments_style() { +function roi_remove_recent_comments_style() { global $wp_widget_factory; if (isset($wp_widget_factory->widgets['WP_Widget_Recent_Comments'])) { @@ -188,7 +188,7 @@ function apus_remove_recent_comments_style() { )); } } -add_action('widgets_init', 'apus_remove_recent_comments_style'); +add_action('widgets_init', 'roi_remove_recent_comments_style'); /** * Redireccionar URLs de comentarios (opcional) @@ -198,13 +198,13 @@ add_action('widgets_init', 'apus_remove_recent_comments_style'); * * @since 1.0.0 */ -function apus_redirect_comment_urls() { +function roi_redirect_comment_urls() { if (is_comment_feed()) { wp_safe_redirect(home_url(), 301); exit; } } -add_action('template_redirect', 'apus_redirect_comment_urls'); +add_action('template_redirect', 'roi_redirect_comment_urls'); /** * Prevenir nuevos comentarios via REST API @@ -215,7 +215,7 @@ add_action('template_redirect', 'apus_redirect_comment_urls'); * @param array $endpoints Endpoints disponibles. * @return array Endpoints sin comentarios. */ -function apus_disable_comments_rest_api($endpoints) { +function roi_disable_comments_rest_api($endpoints) { if (isset($endpoints['/wp/v2/comments'])) { unset($endpoints['/wp/v2/comments']); } @@ -224,7 +224,7 @@ function apus_disable_comments_rest_api($endpoints) { } return $endpoints; } -add_filter('rest_endpoints', 'apus_disable_comments_rest_api'); +add_filter('rest_endpoints', 'roi_disable_comments_rest_api'); /** * Ocultar opciones de comentarios en el dashboard @@ -233,10 +233,10 @@ add_filter('rest_endpoints', 'apus_disable_comments_rest_api'); * * @since 1.0.0 */ -function apus_remove_dashboard_comments() { +function roi_remove_dashboard_comments() { remove_meta_box('dashboard_recent_comments', 'dashboard', 'normal'); } -add_action('admin_init', 'apus_remove_dashboard_comments'); +add_action('admin_init', 'roi_remove_dashboard_comments'); /** * Desactivar notificaciones de comentarios @@ -246,8 +246,8 @@ add_action('admin_init', 'apus_remove_dashboard_comments'); * @since 1.0.0 * @return bool Siempre retorna false. */ -function apus_disable_comment_emails() { +function roi_disable_comment_emails() { return false; } -add_filter('notify_post_author', 'apus_disable_comment_emails', 10, 2); -add_filter('notify_moderator', 'apus_disable_comment_emails', 10, 2); +add_filter('notify_post_author', 'roi_disable_comment_emails', 10, 2); +add_filter('notify_moderator', 'roi_disable_comment_emails', 10, 2); diff --git a/inc/critical-css.php b/inc/critical-css.php index a20502e9..c77ddb7b 100644 --- a/inc/critical-css.php +++ b/inc/critical-css.php @@ -12,7 +12,7 @@ * 2. Main stylesheet is loaded asynchronously after page load * 3. Improves Core Web Vitals by reducing render-blocking CSS * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -27,8 +27,8 @@ if ( ! defined( 'ABSPATH' ) ) { * @since 1.0.0 * @return bool */ -function apus_is_critical_css_enabled() { - return get_theme_mod( 'apus_enable_critical_css', false ); +function roi_is_critical_css_enabled() { + return get_theme_mod( 'roi_enable_critical_css', false ); } /** @@ -40,12 +40,12 @@ function apus_is_critical_css_enabled() { * @since 1.0.0 * @return string Critical CSS content */ -function apus_get_critical_css() { +function roi_get_critical_css() { // Define critical CSS based on page type $critical_css = ''; // Get transient to cache critical CSS - $transient_key = 'apus_critical_css_' . apus_get_page_type(); + $transient_key = 'roi_critical_css_' . roi_get_page_type(); $cached_css = get_transient( $transient_key ); if ( false !== $cached_css ) { @@ -54,13 +54,13 @@ function apus_get_critical_css() { // Generate critical CSS based on page type if ( is_front_page() || is_home() ) { - $critical_css = apus_get_home_critical_css(); + $critical_css = roi_get_home_critical_css(); } elseif ( is_single() ) { - $critical_css = apus_get_single_critical_css(); + $critical_css = roi_get_single_critical_css(); } elseif ( is_archive() || is_category() || is_tag() ) { - $critical_css = apus_get_archive_critical_css(); + $critical_css = roi_get_archive_critical_css(); } else { - $critical_css = apus_get_default_critical_css(); + $critical_css = roi_get_default_critical_css(); } // Cache for 24 hours @@ -75,7 +75,7 @@ function apus_get_critical_css() { * @since 1.0.0 * @return string Page type identifier */ -function apus_get_page_type() { +function roi_get_page_type() { if ( is_front_page() ) { return 'home'; } elseif ( is_single() ) { @@ -97,7 +97,7 @@ function apus_get_page_type() { * @since 1.0.0 * @return string */ -function apus_get_home_critical_css() { +function roi_get_home_critical_css() { return ' /* Reset and Base */ *,*::before,*::after{box-sizing:border-box} @@ -136,7 +136,7 @@ function apus_get_home_critical_css() { * @since 1.0.0 * @return string */ -function apus_get_single_critical_css() { +function roi_get_single_critical_css() { return ' /* Reset and Base */ *,*::before,*::after{box-sizing:border-box} @@ -175,7 +175,7 @@ function apus_get_single_critical_css() { * @since 1.0.0 * @return string */ -function apus_get_archive_critical_css() { +function roi_get_archive_critical_css() { return ' /* Reset and Base */ *,*::before,*::after{box-sizing:border-box} @@ -211,7 +211,7 @@ function apus_get_archive_critical_css() { * @since 1.0.0 * @return string */ -function apus_get_default_critical_css() { +function roi_get_default_critical_css() { return ' /* Reset and Base */ *,*::before,*::after{box-sizing:border-box} @@ -240,12 +240,12 @@ function apus_get_default_critical_css() { * * @since 1.0.0 */ -function apus_output_critical_css() { - if ( ! apus_is_critical_css_enabled() ) { +function roi_output_critical_css() { + if ( ! roi_is_critical_css_enabled() ) { return; } - $critical_css = apus_get_critical_css(); + $critical_css = roi_get_critical_css(); if ( empty( $critical_css ) ) { return; @@ -256,36 +256,36 @@ function apus_output_critical_css() { $critical_css = trim( $critical_css ); // Output inline critical CSS - echo '' . "\n"; + echo '' . "\n"; } -add_action( 'wp_head', 'apus_output_critical_css', 1 ); +add_action( 'wp_head', 'roi_output_critical_css', 1 ); /** * Load main stylesheet asynchronously when critical CSS is enabled * * @since 1.0.0 */ -function apus_async_main_stylesheet() { - if ( ! apus_is_critical_css_enabled() ) { +function roi_async_main_stylesheet() { + if ( ! roi_is_critical_css_enabled() ) { return; } // Dequeue main stylesheet to prevent render-blocking - wp_dequeue_style( 'apus-theme-style' ); + wp_dequeue_style( 'roi-theme-style' ); // Enqueue with media="print" and onload to load asynchronously wp_enqueue_style( - 'apus-theme-style-async', + 'roi-theme-style-async', get_stylesheet_uri(), array(), - APUS_VERSION, + ROI_VERSION, 'print' ); // Add onload attribute to switch media to "all" - add_filter( 'style_loader_tag', 'apus_add_async_attribute', 10, 2 ); + add_filter( 'style_loader_tag', 'roi_add_async_attribute', 10, 2 ); } -add_action( 'wp_enqueue_scripts', 'apus_async_main_stylesheet', 999 ); +add_action( 'wp_enqueue_scripts', 'roi_async_main_stylesheet', 999 ); /** * Add async loading attributes to stylesheet @@ -295,8 +295,8 @@ add_action( 'wp_enqueue_scripts', 'apus_async_main_stylesheet', 999 ); * @param string $handle The style's registered handle. * @return string Modified link tag */ -function apus_add_async_attribute( $html, $handle ) { - if ( 'apus-theme-style-async' !== $handle ) { +function roi_add_async_attribute( $html, $handle ) { + if ( 'roi-theme-style-async' !== $handle ) { return $html; } @@ -319,49 +319,49 @@ function apus_add_async_attribute( $html, $handle ) { * @since 1.0.0 * @param WP_Customize_Manager $wp_customize Theme Customizer object. */ -function apus_critical_css_customizer( $wp_customize ) { +function roi_critical_css_customizer( $wp_customize ) { // Add Performance section $wp_customize->add_section( - 'apus_performance', + 'roi_performance', array( - 'title' => __( 'Performance Optimization', 'apus-theme' ), + 'title' => __( 'Performance Optimization', 'roi-theme' ), 'priority' => 130, ) ); // Critical CSS Enable/Disable $wp_customize->add_setting( - 'apus_enable_critical_css', + 'roi_enable_critical_css', array( 'default' => false, - 'sanitize_callback' => 'apus_sanitize_checkbox', + 'sanitize_callback' => 'roi_sanitize_checkbox', 'transport' => 'refresh', ) ); $wp_customize->add_control( - 'apus_enable_critical_css', + 'roi_enable_critical_css', array( - 'label' => __( 'Enable Critical CSS', 'apus-theme' ), - 'description' => __( 'Inline critical CSS and load main stylesheet asynchronously. This can improve Core Web Vitals but may cause a flash of unstyled content (FOUC). Test thoroughly before enabling in production.', 'apus-theme' ), - 'section' => 'apus_performance', + 'label' => __( 'Enable Critical CSS', 'roi-theme' ), + 'description' => __( 'Inline critical CSS and load main stylesheet asynchronously. This can improve Core Web Vitals but may cause a flash of unstyled content (FOUC). Test thoroughly before enabling in production.', 'roi-theme' ), + 'section' => 'roi_performance', 'type' => 'checkbox', ) ); } -add_action( 'customize_register', 'apus_critical_css_customizer' ); +add_action( 'customize_register', 'roi_critical_css_customizer' ); /** * Clear critical CSS cache when theme is updated * * @since 1.0.0 */ -function apus_clear_critical_css_cache() { +function roi_clear_critical_css_cache() { $page_types = array( 'home', 'single', 'archive', 'search', '404', 'page' ); foreach ( $page_types as $type ) { - delete_transient( 'apus_critical_css_' . $type ); + delete_transient( 'roi_critical_css_' . $type ); } } -add_action( 'after_switch_theme', 'apus_clear_critical_css_cache' ); -add_action( 'customize_save_after', 'apus_clear_critical_css_cache' ); +add_action( 'after_switch_theme', 'roi_clear_critical_css_cache' ); +add_action( 'customize_save_after', 'roi_clear_critical_css_cache' ); diff --git a/inc/cta-ab-testing.php b/inc/cta-ab-testing.php index e9f22b53..d45698ba 100644 --- a/inc/cta-ab-testing.php +++ b/inc/cta-ab-testing.php @@ -8,10 +8,10 @@ * Características: * - Rotación 50/50 entre variante A (Catálogo) y B (Membresía) * - Cookie persistence para mantener la misma variante por usuario - * - Template tag: apus_display_cta() + * - Template tag: roi_display_cta() * - Tracking de conversiones con Google Analytics 4 * - * @package APUS_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -28,8 +28,8 @@ if (!defined('ABSPATH')) { * * @return string 'A' o 'B' */ -function apus_get_cta_variant() { - $cookie_name = 'apus_cta_variant'; +function roi_get_cta_variant() { + $cookie_name = 'roi_cta_variant'; // Verificar si ya existe una variante asignada if (isset($_COOKIE[$cookie_name]) && in_array($_COOKIE[$cookie_name], array('A', 'B'))) { @@ -48,14 +48,14 @@ function apus_get_cta_variant() { /** * Template tag para mostrar el CTA * - * Uso: + * Uso: * * @param array $args Argumentos opcionales para personalizar el CTA * @return void */ -function apus_display_cta($args = array()) { +function roi_display_cta($args = array()) { // Verificar si el CTA está habilitado - $enable_cta = get_theme_mod('apus_enable_cta', true); + $enable_cta = get_theme_mod('roi_enable_cta', true); if (!$enable_cta) { return; } @@ -68,13 +68,13 @@ function apus_display_cta($args = array()) { } // Obtener la variante del usuario - $variant = apus_get_cta_variant(); + $variant = roi_get_cta_variant(); // Obtener configuración desde el Customizer - $cta_config = apus_get_cta_config($variant); + $cta_config = roi_get_cta_config($variant); // Renderizar el CTA - apus_render_cta($variant, $cta_config); + roi_render_cta($variant, $cta_config); } /** @@ -83,21 +83,21 @@ function apus_display_cta($args = array()) { * @param string $variant 'A' o 'B' * @return array Configuración del CTA */ -function apus_get_cta_config($variant) { +function roi_get_cta_config($variant) { if ($variant === 'A') { return array( - 'title' => get_theme_mod('apus_cta_a_title', __('Accede a 200,000+ Análisis de Precios Unitarios', 'apus-theme')), - 'text' => get_theme_mod('apus_cta_a_text', __('Consulta estructuras completas, insumos y dosificaciones de los APUs más utilizados en construcción en México.', 'apus-theme')), - 'button_text' => get_theme_mod('apus_cta_a_button', __('Ver Catálogo Completo', 'apus-theme')), - 'button_url' => get_theme_mod('apus_cta_a_url', home_url('/catalogo')), + 'title' => get_theme_mod('roi_cta_a_title', __('Accede a 200,000+ Análisis de Precios Unitarios', 'roi-theme')), + 'text' => get_theme_mod('roi_cta_a_text', __('Consulta estructuras completas, insumos y dosificaciones de los APUs más utilizados en construcción en México.', 'roi-theme')), + 'button_text' => get_theme_mod('roi_cta_a_button', __('Ver Catálogo Completo', 'roi-theme')), + 'button_url' => get_theme_mod('roi_cta_a_url', home_url('/catalogo')), 'variant' => 'A', ); } else { return array( - 'title' => get_theme_mod('apus_cta_b_title', __('¿Necesitas Consultar Más APUs?', 'apus-theme')), - 'text' => get_theme_mod('apus_cta_b_text', __('Accede a nuestra biblioteca de 200,000 análisis de precios unitarios con estructuras detalladas y listados de insumos.', 'apus-theme')), - 'button_text' => get_theme_mod('apus_cta_b_button', __('Conocer Planes de Membresía', 'apus-theme')), - 'button_url' => get_theme_mod('apus_cta_b_url', home_url('/planes')), + 'title' => get_theme_mod('roi_cta_b_title', __('¿Necesitas Consultar Más APUs?', 'roi-theme')), + 'text' => get_theme_mod('roi_cta_b_text', __('Accede a nuestra biblioteca de 200,000 análisis de precios unitarios con estructuras detalladas y listados de insumos.', 'roi-theme')), + 'button_text' => get_theme_mod('roi_cta_b_button', __('Conocer Planes de Membresía', 'roi-theme')), + 'button_url' => get_theme_mod('roi_cta_b_url', home_url('/planes')), 'variant' => 'B', ); } @@ -110,7 +110,7 @@ function apus_get_cta_config($variant) { * @param array $config Configuración del CTA * @return void */ -function apus_render_cta($variant, $config) { +function roi_render_cta($variant, $config) { ?>
    $variant, - 'ga_enabled' => !empty(get_theme_mod('apus_ga_tracking_id', '')), - 'ga_id' => get_theme_mod('apus_ga_tracking_id', ''), + 'ga_enabled' => !empty(get_theme_mod('roi_ga_tracking_id', '')), + 'ga_id' => get_theme_mod('roi_ga_tracking_id', ''), 'debug_mode' => defined('WP_DEBUG') && WP_DEBUG, ); - wp_localize_script('apus-cta-tracking', 'apusCTA', $cta_data); + wp_localize_script('roicta-tracking', 'rroiA', $cta_data); } -add_action('wp_enqueue_scripts', 'apus_cta_localize_script', 20); +add_action('wp_enqueue_scripts', 'roi_cta_localize_script', 20); diff --git a/inc/customizer-cta.php b/inc/customizer-cta.php index 62b21442..bc37718f 100644 --- a/inc/customizer-cta.php +++ b/inc/customizer-cta.php @@ -5,7 +5,7 @@ * Opciones del panel de personalización para configurar * las dos variantes del CTA (A y B). * - * @package APUS_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -17,11 +17,11 @@ if (!defined('ABSPATH')) { /** * Registrar configuraciones del CTA en el Customizer */ -function apus_customize_cta($wp_customize) { +function roi_customize_cta($wp_customize) { // Agregar sección para CTA A/B Testing - $wp_customize->add_section('apus_cta', array( - 'title' => __('CTA A/B Testing', 'apus-theme'), - 'description' => __('Configura las dos variantes del Call-to-Action que se mostrarán aleatoriamente. El sistema asignará automáticamente una variante a cada usuario (50/50).', 'apus-theme'), + $wp_customize->add_section('roi_cta', array( + 'title' => __('CTA A/B Testing', 'roi-theme'), + 'description' => __('Configura las dos variantes del Call-to-Action que se mostrarán aleatoriamente. El sistema asignará automáticamente una variante a cada usuario (50/50).', 'roi-theme'), 'priority' => 132, )); @@ -30,28 +30,28 @@ function apus_customize_cta($wp_customize) { // ===================================================== // Habilitar/Deshabilitar CTA - $wp_customize->add_setting('apus_enable_cta', array( + $wp_customize->add_setting('roi_enable_cta', array( 'default' => true, - 'sanitize_callback' => 'apus_sanitize_checkbox', + 'sanitize_callback' => 'roi_sanitize_checkbox', 'transport' => 'refresh', )); - $wp_customize->add_control('apus_enable_cta', array( - 'label' => __('Habilitar CTA con A/B Testing', 'apus-theme'), - 'description' => __('Muestra un Call-to-Action en los posts individuales con dos variantes aleatorias.', 'apus-theme'), - 'section' => 'apus_cta', + $wp_customize->add_control('roi_enable_cta', array( + 'label' => __('Habilitar CTA con A/B Testing', 'roi-theme'), + 'description' => __('Muestra un Call-to-Action en los posts individuales con dos variantes aleatorias.', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'checkbox', )); // Auto-insertar CTA (opcional, por defecto usar template tag) - $wp_customize->add_setting('apus_cta_auto_insert', array( + $wp_customize->add_setting('roi_cta_auto_insert', array( 'default' => false, - 'sanitize_callback' => 'apus_sanitize_checkbox', + 'sanitize_callback' => 'roi_sanitize_checkbox', 'transport' => 'refresh', )); - $wp_customize->add_control('apus_cta_auto_insert', array( - 'label' => __('Auto-insertar CTA después del contenido', 'apus-theme'), - 'description' => __('Si está desactivado, usa el template tag apus_display_cta() manualmente.', 'apus-theme'), - 'section' => 'apus_cta', + $wp_customize->add_control('roi_cta_auto_insert', array( + 'label' => __('Auto-insertar CTA después del contenido', 'roi-theme'), + 'description' => __('Si está desactivado, usa el template tag roi_display_cta() manualmente.', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'checkbox', )); @@ -60,66 +60,66 @@ function apus_customize_cta($wp_customize) { // ===================================================== // Separador visual - $wp_customize->add_setting('apus_cta_a_separator', array( + $wp_customize->add_setting('roi_cta_a_separator', array( 'sanitize_callback' => 'sanitize_text_field', )); $wp_customize->add_control(new WP_Customize_Control( $wp_customize, - 'apus_cta_a_separator', + 'roi_cta_a_separator', array( - 'label' => __('━━━ Variante A: Catálogo ━━━', 'apus-theme'), - 'description' => __('Enfoque en acceso al catálogo de 200,000+ APUs', 'apus-theme'), - 'section' => 'apus_cta', + 'label' => __('━━━ Variante A: Catálogo ━━━', 'roi-theme'), + 'description' => __('Enfoque en acceso al catálogo de 200,000+ APUs', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'hidden', ) )); // Título Variante A - $wp_customize->add_setting('apus_cta_a_title', array( - 'default' => __('Accede a 200,000+ Análisis de Precios Unitarios', 'apus-theme'), + $wp_customize->add_setting('roi_cta_a_title', array( + 'default' => __('Accede a 200,000+ Análisis de Precios Unitarios', 'roi-theme'), 'sanitize_callback' => 'sanitize_text_field', 'transport' => 'postMessage', )); - $wp_customize->add_control('apus_cta_a_title', array( - 'label' => __('Título', 'apus-theme'), - 'section' => 'apus_cta', + $wp_customize->add_control('roi_cta_a_title', array( + 'label' => __('Título', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'text', )); // Texto Variante A - $wp_customize->add_setting('apus_cta_a_text', array( - 'default' => __('Consulta estructuras completas, insumos y dosificaciones de los APUs más utilizados en construcción en México.', 'apus-theme'), + $wp_customize->add_setting('roi_cta_a_text', array( + 'default' => __('Consulta estructuras completas, insumos y dosificaciones de los APUs más utilizados en construcción en México.', 'roi-theme'), 'sanitize_callback' => 'sanitize_textarea_field', 'transport' => 'postMessage', )); - $wp_customize->add_control('apus_cta_a_text', array( - 'label' => __('Texto descriptivo', 'apus-theme'), - 'section' => 'apus_cta', + $wp_customize->add_control('roi_cta_a_text', array( + 'label' => __('Texto descriptivo', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'textarea', )); // Botón Variante A - $wp_customize->add_setting('apus_cta_a_button', array( - 'default' => __('Ver Catálogo Completo', 'apus-theme'), + $wp_customize->add_setting('roi_cta_a_button', array( + 'default' => __('Ver Catálogo Completo', 'roi-theme'), 'sanitize_callback' => 'sanitize_text_field', 'transport' => 'postMessage', )); - $wp_customize->add_control('apus_cta_a_button', array( - 'label' => __('Texto del botón', 'apus-theme'), - 'section' => 'apus_cta', + $wp_customize->add_control('roi_cta_a_button', array( + 'label' => __('Texto del botón', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'text', )); // URL Variante A - $wp_customize->add_setting('apus_cta_a_url', array( + $wp_customize->add_setting('roi_cta_a_url', array( 'default' => '#', 'sanitize_callback' => 'esc_url_raw', 'transport' => 'postMessage', )); - $wp_customize->add_control('apus_cta_a_url', array( - 'label' => __('URL del botón', 'apus-theme'), - 'description' => __('Ejemplo: /catalogo-completo/ o una URL completa', 'apus-theme'), - 'section' => 'apus_cta', + $wp_customize->add_control('roi_cta_a_url', array( + 'label' => __('URL del botón', 'roi-theme'), + 'description' => __('Ejemplo: /catalogo-completo/ o una URL completa', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'url', )); @@ -128,66 +128,66 @@ function apus_customize_cta($wp_customize) { // ===================================================== // Separador visual - $wp_customize->add_setting('apus_cta_b_separator', array( + $wp_customize->add_setting('roi_cta_b_separator', array( 'sanitize_callback' => 'sanitize_text_field', )); $wp_customize->add_control(new WP_Customize_Control( $wp_customize, - 'apus_cta_b_separator', + 'roi_cta_b_separator', array( - 'label' => __('━━━ Variante B: Membresía ━━━', 'apus-theme'), - 'description' => __('Enfoque en planes de membresía y acceso premium', 'apus-theme'), - 'section' => 'apus_cta', + 'label' => __('━━━ Variante B: Membresía ━━━', 'roi-theme'), + 'description' => __('Enfoque en planes de membresía y acceso premium', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'hidden', ) )); // Título Variante B - $wp_customize->add_setting('apus_cta_b_title', array( - 'default' => __('¿Necesitas Consultar Más APUs?', 'apus-theme'), + $wp_customize->add_setting('roi_cta_b_title', array( + 'default' => __('¿Necesitas Consultar Más APUs?', 'roi-theme'), 'sanitize_callback' => 'sanitize_text_field', 'transport' => 'postMessage', )); - $wp_customize->add_control('apus_cta_b_title', array( - 'label' => __('Título', 'apus-theme'), - 'section' => 'apus_cta', + $wp_customize->add_control('roi_cta_b_title', array( + 'label' => __('Título', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'text', )); // Texto Variante B - $wp_customize->add_setting('apus_cta_b_text', array( - 'default' => __('Accede a nuestra biblioteca de 200,000 análisis de precios unitarios con estructuras detalladas y listados de insumos.', 'apus-theme'), + $wp_customize->add_setting('roi_cta_b_text', array( + 'default' => __('Accede a nuestra biblioteca de 200,000 análisis de precios unitarios con estructuras detalladas y listados de insumos.', 'roi-theme'), 'sanitize_callback' => 'sanitize_textarea_field', 'transport' => 'postMessage', )); - $wp_customize->add_control('apus_cta_b_text', array( - 'label' => __('Texto descriptivo', 'apus-theme'), - 'section' => 'apus_cta', + $wp_customize->add_control('roi_cta_b_text', array( + 'label' => __('Texto descriptivo', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'textarea', )); // Botón Variante B - $wp_customize->add_setting('apus_cta_b_button', array( - 'default' => __('Conocer Planes de Membresía', 'apus-theme'), + $wp_customize->add_setting('roi_cta_b_button', array( + 'default' => __('Conocer Planes de Membresía', 'roi-theme'), 'sanitize_callback' => 'sanitize_text_field', 'transport' => 'postMessage', )); - $wp_customize->add_control('apus_cta_b_button', array( - 'label' => __('Texto del botón', 'apus-theme'), - 'section' => 'apus_cta', + $wp_customize->add_control('roi_cta_b_button', array( + 'label' => __('Texto del botón', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'text', )); // URL Variante B - $wp_customize->add_setting('apus_cta_b_url', array( + $wp_customize->add_setting('roi_cta_b_url', array( 'default' => '#', 'sanitize_callback' => 'esc_url_raw', 'transport' => 'postMessage', )); - $wp_customize->add_control('apus_cta_b_url', array( - 'label' => __('URL del botón', 'apus-theme'), - 'description' => __('Ejemplo: /planes-de-membresia/ o una URL completa', 'apus-theme'), - 'section' => 'apus_cta', + $wp_customize->add_control('roi_cta_b_url', array( + 'label' => __('URL del botón', 'roi-theme'), + 'description' => __('Ejemplo: /planes-de-membresia/ o una URL completa', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'url', )); @@ -196,40 +196,40 @@ function apus_customize_cta($wp_customize) { // ===================================================== // Separador visual - $wp_customize->add_setting('apus_cta_ga_separator', array( + $wp_customize->add_setting('roi_cta_ga_separator', array( 'sanitize_callback' => 'sanitize_text_field', )); $wp_customize->add_control(new WP_Customize_Control( $wp_customize, - 'apus_cta_ga_separator', + 'roi_cta_ga_separator', array( - 'label' => __('━━━ Google Analytics ━━━', 'apus-theme'), - 'description' => __('Configuración para tracking de conversiones', 'apus-theme'), - 'section' => 'apus_cta', + 'label' => __('━━━ Google Analytics ━━━', 'roi-theme'), + 'description' => __('Configuración para tracking de conversiones', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'hidden', ) )); // Google Analytics Tracking ID - $wp_customize->add_setting('apus_ga_tracking_id', array( + $wp_customize->add_setting('roi_ga_tracking_id', array( 'default' => '', 'sanitize_callback' => 'sanitize_text_field', 'transport' => 'refresh', )); - $wp_customize->add_control('apus_ga_tracking_id', array( - 'label' => __('Google Analytics Tracking ID', 'apus-theme'), - 'description' => __('Formato: G-XXXXXXXXXX (GA4) o UA-XXXXXXXXX-X (Universal Analytics). Déjalo vacío si ya tienes GA instalado mediante plugin.', 'apus-theme'), - 'section' => 'apus_cta', + $wp_customize->add_control('roi_ga_tracking_id', array( + 'label' => __('Google Analytics Tracking ID', 'roi-theme'), + 'description' => __('Formato: G-XXXXXXXXXX (GA4) o UA-XXXXXXXXX-X (Universal Analytics). Déjalo vacío si ya tienes GA instalado mediante plugin.', 'roi-theme'), + 'section' => 'roi_cta', 'type' => 'text', )); } -add_action('customize_register', 'apus_customize_cta'); +add_action('customize_register', 'roi_customize_cta'); /** * Agregar script de Google Analytics en el header si está configurado */ -function apus_output_google_analytics() { - $tracking_id = get_theme_mod('apus_ga_tracking_id', ''); +function roi_output_google_analytics() { + $tracking_id = get_theme_mod('roi_ga_tracking_id', ''); // No mostrar si está vacío o si estamos en el admin if (empty($tracking_id) || is_admin()) { @@ -254,4 +254,4 @@ function apus_output_google_analytics() { add_section('apus_typography', array( - 'title' => __('Typography', 'apus-theme'), - 'description' => __('Configure font settings for your site.', 'apus-theme'), + $wp_customize->add_section('roi_typography', array( + 'title' => __('Typography', 'roi-theme'), + 'description' => __('Configure font settings for your site.', 'roi-theme'), 'priority' => 30, )); // Setting: Use Custom Fonts - $wp_customize->add_setting('apus_use_custom_fonts', array( + $wp_customize->add_setting('roi_use_custom_fonts', array( 'default' => false, - 'sanitize_callback' => 'apus_sanitize_checkbox', + 'sanitize_callback' => 'roi_sanitize_checkbox', 'transport' => 'refresh', )); - $wp_customize->add_control('apus_use_custom_fonts', array( - 'label' => __('Use Custom Fonts', 'apus-theme'), - 'description' => __('Enable custom fonts instead of system fonts. System fonts load faster and improve Core Web Vitals.', 'apus-theme'), - 'section' => 'apus_typography', + $wp_customize->add_control('roi_use_custom_fonts', array( + 'label' => __('Use Custom Fonts', 'roi-theme'), + 'description' => __('Enable custom fonts instead of system fonts. System fonts load faster and improve Core Web Vitals.', 'roi-theme'), + 'section' => 'roi_typography', 'type' => 'checkbox', )); // Setting: Font Loading Strategy (only if custom fonts enabled) - $wp_customize->add_setting('apus_font_display', array( + $wp_customize->add_setting('roi_font_display', array( 'default' => 'swap', - 'sanitize_callback' => 'apus_sanitize_select', + 'sanitize_callback' => 'roi_sanitize_select', 'transport' => 'refresh', )); - $wp_customize->add_control('apus_font_display', array( - 'label' => __('Font Display Strategy', 'apus-theme'), - 'description' => __('Controls how fonts are displayed during loading. "swap" is recommended for best performance.', 'apus-theme'), - 'section' => 'apus_typography', + $wp_customize->add_control('roi_font_display', array( + 'label' => __('Font Display Strategy', 'roi-theme'), + 'description' => __('Controls how fonts are displayed during loading. "swap" is recommended for best performance.', 'roi-theme'), + 'section' => 'roi_typography', 'type' => 'select', 'choices' => array( - 'auto' => __('Auto', 'apus-theme'), - 'block' => __('Block', 'apus-theme'), - 'swap' => __('Swap (Recommended)', 'apus-theme'), - 'fallback' => __('Fallback', 'apus-theme'), - 'optional' => __('Optional', 'apus-theme'), + 'auto' => __('Auto', 'roi-theme'), + 'block' => __('Block', 'roi-theme'), + 'swap' => __('Swap (Recommended)', 'roi-theme'), + 'fallback' => __('Fallback', 'roi-theme'), + 'optional' => __('Optional', 'roi-theme'), ), - 'active_callback' => 'apus_is_custom_fonts_enabled', + 'active_callback' => 'roi_is_custom_fonts_enabled', )); // Setting: Preload Fonts - $wp_customize->add_setting('apus_preload_fonts', array( + $wp_customize->add_setting('roi_preload_fonts', array( 'default' => true, - 'sanitize_callback' => 'apus_sanitize_checkbox', + 'sanitize_callback' => 'roi_sanitize_checkbox', 'transport' => 'refresh', )); - $wp_customize->add_control('apus_preload_fonts', array( - 'label' => __('Preload Font Files', 'apus-theme'), - 'description' => __('Preload critical font files for faster rendering. Recommended for better LCP scores.', 'apus-theme'), - 'section' => 'apus_typography', + $wp_customize->add_control('roi_preload_fonts', array( + 'label' => __('Preload Font Files', 'roi-theme'), + 'description' => __('Preload critical font files for faster rendering. Recommended for better LCP scores.', 'roi-theme'), + 'section' => 'roi_typography', 'type' => 'checkbox', - 'active_callback' => 'apus_is_custom_fonts_enabled', + 'active_callback' => 'roi_is_custom_fonts_enabled', )); } -add_action('customize_register', 'apus_customize_register_fonts'); +add_action('customize_register', 'roi_customize_register_fonts'); /** * Check if custom fonts are enabled */ -function apus_is_custom_fonts_enabled() { - return get_theme_mod('apus_use_custom_fonts', false); +function roi_is_custom_fonts_enabled() { + return get_theme_mod('roi_use_custom_fonts', false); } /** * Add body class based on font settings */ -function apus_font_body_class($classes) { - if (apus_is_custom_fonts_enabled()) { +function roi_font_body_class($classes) { + if (roi_is_custom_fonts_enabled()) { $classes[] = 'use-custom-fonts'; } else { $classes[] = 'use-system-fonts'; @@ -96,18 +96,18 @@ function apus_font_body_class($classes) { return $classes; } -add_filter('body_class', 'apus_font_body_class'); +add_filter('body_class', 'roi_font_body_class'); /** * Add preload links for custom fonts */ -function apus_preload_custom_fonts() { +function roi_preload_custom_fonts() { // Only preload if custom fonts are enabled and preload is enabled - if (!apus_is_custom_fonts_enabled()) { + if (!roi_is_custom_fonts_enabled()) { return; } - if (!get_theme_mod('apus_preload_fonts', true)) { + if (!get_theme_mod('roi_preload_fonts', true)) { return; } @@ -120,26 +120,26 @@ function apus_preload_custom_fonts() { */ } -add_action('wp_head', 'apus_preload_custom_fonts', 1); +add_action('wp_head', 'roi_preload_custom_fonts', 1); /** * Output inline CSS for font display strategy */ -function apus_output_font_display_css() { - if (!apus_is_custom_fonts_enabled()) { +function roi_output_font_display_css() { + if (!roi_is_custom_fonts_enabled()) { return; } - $font_display = get_theme_mod('apus_font_display', 'swap'); + $font_display = get_theme_mod('roi_font_display', 'swap'); // This would be used if you have actual @font-face declarations // For now, it's just a placeholder for future implementation ?> - get_template_directory_uri(), 'ajaxUrl' => admin_url('admin-ajax.php'), @@ -301,25 +301,25 @@ function apus_enqueue_main_javascript() { ); } -add_action('wp_enqueue_scripts', 'apus_enqueue_main_javascript', 11); +add_action('wp_enqueue_scripts', 'roi_enqueue_main_javascript', 11); /** - * Remove defer from apus-main-js to make wp_localize_script work + * Remove defer from roi-main-js to make wp_localize_script work * WordPress 6.3+ adds defer automatically to footer scripts with dependencies * but wp_localize_script requires synchronous execution */ -function apus_remove_defer_from_main_js($tag, $handle) { - if ('apus-main-js' === $handle) { +function roi_remove_defer_from_main_js($tag, $handle) { + if ('roi-main-js' === $handle) { // Remove defer and data-wp-strategy attributes $tag = str_replace(' defer', '', $tag); $tag = str_replace(' data-wp-strategy="defer"', '', $tag); } return $tag; } -add_filter('script_loader_tag', 'apus_remove_defer_from_main_js', 20, 2); +add_filter('script_loader_tag', 'roi_remove_defer_from_main_js', 20, 2); /** - * ELIMINADO: apus_enqueue_footer_styles + * ELIMINADO: roi_enqueue_footer_styles * Motivo: footer.css NO está documentado - CSS debe estar en style.css * Ver: theme-documentation/16-componente-footer-contact-form/CSS-ESPECIFICO.md */ @@ -327,22 +327,22 @@ add_filter('script_loader_tag', 'apus_remove_defer_from_main_js', 20, 2); /** * Enqueue accessibility styles and scripts */ -function apus_enqueue_accessibility() { +function roi_enqueue_accessibility() { // Accessibility CSS wp_enqueue_style( - 'apus-accessibility', + 'roi-accessibility', get_template_directory_uri() . '/assets/css/css-global-accessibility.css', - array('apus-theme-style'), - APUS_VERSION, + array('roi-theme-style'), + ROI_VERSION, 'all' ); // Accessibility JavaScript wp_enqueue_script( - 'apus-accessibility-js', + 'roi-accessibility-js', get_template_directory_uri() . '/assets/js/accessibility.js', - array('apus-bootstrap-js'), - APUS_VERSION, + array('roi-bootstrap-js'), + ROI_VERSION, array( 'in_footer' => true, 'strategy' => 'defer', @@ -350,7 +350,7 @@ function apus_enqueue_accessibility() { ); } -add_action('wp_enqueue_scripts', 'apus_enqueue_accessibility', 15); +add_action('wp_enqueue_scripts', 'roi_enqueue_accessibility', 15); /** * Enqueue del script de carga retrasada de AdSense @@ -359,14 +359,14 @@ add_action('wp_enqueue_scripts', 'apus_enqueue_accessibility', 15); * (scroll, click, touch, etc.) y cargar los scripts de AdSense solo * en ese momento, mejorando significativamente el rendimiento inicial. */ -function apus_enqueue_adsense_loader() { +function roi_enqueue_adsense_loader() { // Solo ejecutar en frontend if (is_admin()) { return; } // Verificar si el retardo de AdSense está habilitado - $delay_enabled = apus_get_option('apus_adsense_delay_enabled', '1'); + $delay_enabled = roi_get_option('roi_adsense_delay_enabled', '1'); if ($delay_enabled !== '1') { return; @@ -374,10 +374,10 @@ function apus_enqueue_adsense_loader() { // Enqueue del script de carga de AdSense wp_enqueue_script( - 'apus-adsense-loader', + 'roi-adsense-loader', get_template_directory_uri() . '/assets/js/adsense-loader.js', array(), - APUS_VERSION, + ROI_VERSION, array( 'in_footer' => true, 'strategy' => 'defer', @@ -385,7 +385,7 @@ function apus_enqueue_adsense_loader() { ); } -add_action('wp_enqueue_scripts', 'apus_enqueue_adsense_loader', 10); +add_action('wp_enqueue_scripts', 'roi_enqueue_adsense_loader', 10); /** * Enqueue theme core styles @@ -395,46 +395,46 @@ add_action('wp_enqueue_scripts', 'apus_enqueue_adsense_loader', 10); * Resultado: 638 líneas eliminadas - TODO el CSS documentado va en style.css * Fecha: 2025-01-07 */ -function apus_enqueue_theme_styles() { +function roi_enqueue_theme_styles() { // Theme Core Styles - ELIMINADO theme.css // wp_enqueue_style( - // 'apus-theme', + // 'roi-theme', // get_template_directory_uri() . '/assets/css/theme.css', - // array('apus-bootstrap'), + // array('roi-bootstrap'), // '1.0.0', // 'all' // ); // Theme Animations wp_enqueue_style( - 'apus-animations', + 'roi-animations', get_template_directory_uri() . '/assets/css/css-global-animations.css', - array('apus-bootstrap'), // Cambiado de 'apus-theme' a 'apus-bootstrap' + array('roi-bootstrap'), // Cambiado de 'roi-theme' a 'roi-bootstrap' '1.0.0', 'all' ); // Theme Responsive Styles wp_enqueue_style( - 'apus-responsive', + 'roi-responsive', get_template_directory_uri() . '/assets/css/css-global-responsive.css', - array('apus-bootstrap'), // Cambiado de 'apus-theme' a 'apus-bootstrap' + array('roi-bootstrap'), // Cambiado de 'roi-theme' a 'roi-bootstrap' '1.0.0', 'all' ); // Theme Utilities wp_enqueue_style( - 'apus-utilities', + 'roi-utilities', get_template_directory_uri() . '/assets/css/css-global-utilities.css', - array('apus-bootstrap'), // Cambiado de 'apus-theme' a 'apus-bootstrap' + array('roi-bootstrap'), // Cambiado de 'roi-theme' a 'roi-bootstrap' '1.0.0', 'all' ); // Print Styles wp_enqueue_style( - 'apus-print', + 'roi-print', get_template_directory_uri() . '/assets/css/css-global-print.css', array(), '1.0.0', @@ -442,16 +442,16 @@ function apus_enqueue_theme_styles() { ); } -add_action('wp_enqueue_scripts', 'apus_enqueue_theme_styles', 13); +add_action('wp_enqueue_scripts', 'roi_enqueue_theme_styles', 13); /** * Enqueue social share styles * * HABILITADO: CSS de share buttons debe estar en su propio archivo * Arquitectura correcta: cada componente tiene su archivo CSS individual - * Ver: wp-content/themes/apus-theme/assets/css/componente-share-buttons.css + * Ver: wp-content/themes/roi-theme/assets/css/componente-share-buttons.css */ -function apus_enqueue_social_share_styles() { +function roi_enqueue_social_share_styles() { // Only enqueue on single posts if (!is_single()) { return; @@ -459,31 +459,31 @@ function apus_enqueue_social_share_styles() { // Social Share CSS wp_enqueue_style( - 'apus-social-share', + 'roi-social-share', get_template_directory_uri() . '/assets/css/componente-share-buttons.css', - array('apus-bootstrap'), - APUS_VERSION, + array('roi-bootstrap'), + ROI_VERSION, 'all' ); } -add_action('wp_enqueue_scripts', 'apus_enqueue_social_share_styles', 14); +add_action('wp_enqueue_scripts', 'roi_enqueue_social_share_styles', 14); /** * Enqueue APU Tables styles */ -function apus_enqueue_apu_tables_styles() { +function roi_enqueue_apu_tables_styles() { // APU Tables CSS wp_enqueue_style( - 'apus-tables-apu', + 'roi-tables-apu', get_template_directory_uri() . '/assets/css/css-tablas-apu.css', - array('apus-bootstrap'), - APUS_VERSION, + array('roi-bootstrap'), + ROI_VERSION, 'all' ); } -add_action('wp_enqueue_scripts', 'apus_enqueue_apu_tables_styles', 15); +add_action('wp_enqueue_scripts', 'roi_enqueue_apu_tables_styles', 15); /** * Enqueue APU Tables auto-class JavaScript @@ -493,13 +493,13 @@ add_action('wp_enqueue_scripts', 'apus_enqueue_apu_tables_styles', 15); * * Issue #132 */ -function apus_enqueue_apu_tables_autoclass_script() { +function roi_enqueue_apu_tables_autoclass_script() { // APU Tables Auto-Class JS wp_enqueue_script( - 'apus-apu-tables-autoclass', + 'roi-apu-tables-autoclass', get_template_directory_uri() . '/assets/js/apu-tables-auto-class.js', array(), - APUS_VERSION, + ROI_VERSION, array( 'in_footer' => true, 'strategy' => 'defer', @@ -507,38 +507,38 @@ function apus_enqueue_apu_tables_autoclass_script() { ); } -add_action('wp_enqueue_scripts', 'apus_enqueue_apu_tables_autoclass_script', 15); +add_action('wp_enqueue_scripts', 'roi_enqueue_apu_tables_autoclass_script', 15); /** * Enqueue CTA A/B Testing styles and scripts */ -function apus_enqueue_cta_assets() { +function roi_enqueue_cta_assets() { // Solo enqueue en posts individuales if (!is_single()) { return; } // Verificar si el CTA está habilitado - $enable_cta = get_theme_mod('apus_enable_cta', true); + $enable_cta = get_theme_mod('roi_enable_cta', true); if (!$enable_cta) { return; } // CTA CSS wp_enqueue_style( - 'apus-cta-style', + 'roi-cta-style', get_template_directory_uri() . '/assets/css/componente-cta-ab-testing.css', - array('apus-bootstrap'), - APUS_VERSION, + array('roi-bootstrap'), + ROI_VERSION, 'all' ); // CTA Tracking JS wp_enqueue_script( - 'apus-cta-tracking', + 'roi-cta-tracking', get_template_directory_uri() . '/assets/js/cta-tracking.js', array(), - APUS_VERSION, + ROI_VERSION, array( 'in_footer' => true, 'strategy' => 'defer', @@ -546,12 +546,12 @@ function apus_enqueue_cta_assets() { ); } -add_action('wp_enqueue_scripts', 'apus_enqueue_cta_assets', 16); +add_action('wp_enqueue_scripts', 'roi_enqueue_cta_assets', 16); /** * Enqueue CTA Box Sidebar styles (Issue #36) */ -function apus_enqueue_cta_box_sidebar_assets() { +function roi_enqueue_cta_box_sidebar_assets() { // Solo enqueue en posts individuales if (!is_single()) { return; @@ -559,15 +559,15 @@ function apus_enqueue_cta_box_sidebar_assets() { // CTA Box Sidebar CSS wp_enqueue_style( - 'apus-cta-box-sidebar', + 'roi-cta-box-sidebar', get_template_directory_uri() . '/assets/css/componente-cta-box-sidebar.css', - array('apus-bootstrap'), + array('roi-bootstrap'), filemtime(get_template_directory() . '/assets/css/componente-cta-box-sidebar.css'), 'all' ); } -add_action('wp_enqueue_scripts', 'apus_enqueue_cta_box_sidebar_assets', 17); +add_action('wp_enqueue_scripts', 'roi_enqueue_cta_box_sidebar_assets', 17); /** * Enqueue TOC Sidebar styles (only on single posts) @@ -577,7 +577,7 @@ add_action('wp_enqueue_scripts', 'apus_enqueue_cta_box_sidebar_assets', 17); * * @since 1.0.5 */ -function apus_enqueue_toc_sidebar_assets() { +function roi_enqueue_toc_sidebar_assets() { // Only load on single posts if (!is_single()) { return; @@ -585,33 +585,33 @@ function apus_enqueue_toc_sidebar_assets() { // TOC Sidebar CSS wp_enqueue_style( - 'apus-toc-sidebar', + 'roi-toc-sidebar', get_template_directory_uri() . '/assets/css/componente-sidebar-toc.css', - array('apus-bootstrap'), + array('roi-bootstrap'), filemtime(get_template_directory() . '/assets/css/componente-sidebar-toc.css'), 'all' ); } -add_action('wp_enqueue_scripts', 'apus_enqueue_toc_sidebar_assets', 18); +add_action('wp_enqueue_scripts', 'roi_enqueue_toc_sidebar_assets', 18); /** * Enqueue Footer Contact Form styles * * ARQUITECTURA CORRECTA: Cada componente debe tener su propio archivo CSS * Footer Contact Form CSS ahora está en su archivo individual - * Ver: wp-content/themes/apus-theme/assets/css/componente-footer-contact-form.css + * Ver: wp-content/themes/roi-theme/assets/css/componente-footer-contact-form.css */ -function apus_enqueue_footer_contact_assets() { +function roi_enqueue_footer_contact_assets() { // Footer Contact CSS wp_enqueue_style( - 'apus-footer-contact', + 'roi-footer-contact', get_template_directory_uri() . '/assets/css/componente-footer-contact-form.css', - array('apus-bootstrap'), - APUS_VERSION, + array('roi-bootstrap'), + ROI_VERSION, 'all' ); } -add_action('wp_enqueue_scripts', 'apus_enqueue_footer_contact_assets', 18); +add_action('wp_enqueue_scripts', 'roi_enqueue_footer_contact_assets', 18); diff --git a/inc/featured-image.php b/inc/featured-image.php index 0168807c..4ae4b4a1 100644 --- a/inc/featured-image.php +++ b/inc/featured-image.php @@ -6,7 +6,7 @@ * Sin placeholders - solo muestra imagen si existe. * Issue #10 - Imágenes destacadas configurables * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -24,17 +24,17 @@ if (!defined('ABSPATH')) { * - Retorna HTML de la imagen o cadena vacía (sin placeholder) * * Tamaños disponibles: - * - apus-featured-large: 1200x600 (para single posts) - * - apus-featured-medium: 800x400 (para archives) - * - apus-thumbnail: 400x300 (para widgets/sidebars) + * - roi-featured-large: 1200x600 (para single posts) + * - roi-featured-medium: 800x400 (para archives) + * - roi-thumbnail: 400x300 (para widgets/sidebars) * * @param int|null $post_id ID del post (null = post actual) - * @param string $size Tamaño de imagen registrado (default: apus-featured-large) + * @param string $size Tamaño de imagen registrado (default: roi-featured-large) * @param array $attr Atributos HTML adicionales para la imagen * @param bool $force_show Forzar mostrar ignorando configuración (default: false) * @return string HTML de la imagen o cadena vacía */ -function apus_get_featured_image($post_id = null, $size = 'apus-featured-large', $attr = array(), $force_show = false) { +function roi_get_featured_image($post_id = null, $size = 'roi-featured-large', $attr = array(), $force_show = false) { // Obtener ID del post actual si no se especifica if (!$post_id) { $post_id = get_the_ID(); @@ -55,18 +55,18 @@ function apus_get_featured_image($post_id = null, $size = 'apus-featured-large', // Verificar configuración global según tipo de contenido if (!$force_show) { - // Primero intentar con apus_get_option (sistema de opciones del tema) - if (function_exists('apus_get_option')) { + // Primero intentar con roi_get_option (sistema de opciones del tema) + if (function_exists('roi_get_option')) { if ($post_type === 'post') { - $enabled = apus_get_option('featured_image_single', true); + $enabled = roi_get_option('featured_image_single', true); } elseif ($post_type === 'page') { - $enabled = apus_get_option('featured_image_page', true); + $enabled = roi_get_option('featured_image_page', true); } else { - $enabled = apus_get_option('featured_image_' . $post_type, true); + $enabled = roi_get_option('featured_image_' . $post_type, true); } } else { // Fallback a theme_mod - $option_key = 'apus_featured_image_' . $post_type; + $option_key = 'roi_featured_image_' . $post_type; $enabled = get_theme_mod($option_key, true); } @@ -106,19 +106,19 @@ function apus_get_featured_image($post_id = null, $size = 'apus-featured-large', * Muestra la imagen destacada de un post * * Template tag para usar directamente en templates. - * Echo wrapper de apus_get_featured_image(). + * Echo wrapper de roi_get_featured_image(). * * Uso en templates: - * - * + * + * * * @param int|null $post_id ID del post (null = post actual) * @param string $size Tamaño de imagen registrado * @param array $attr Atributos HTML adicionales * @param bool $force_show Forzar mostrar ignorando configuración */ -function apus_the_featured_image($post_id = null, $size = 'apus-featured-large', $attr = array(), $force_show = false) { - echo apus_get_featured_image($post_id, $size, $attr, $force_show); +function roi_the_featured_image($post_id = null, $size = 'roi-featured-large', $attr = array(), $force_show = false) { + echo roi_get_featured_image($post_id, $size, $attr, $force_show); } /** @@ -131,7 +131,7 @@ function apus_the_featured_image($post_id = null, $size = 'apus-featured-large', * @param bool $with_link Envolver en enlace al post (default: true) * @return string HTML del thumbnail o cadena vacía */ -function apus_get_post_thumbnail($post_id = null, $with_link = true) { +function roi_get_post_thumbnail($post_id = null, $with_link = true) { // Obtener ID del post actual si no se especifica if (!$post_id) { $post_id = get_the_ID(); @@ -148,7 +148,7 @@ function apus_get_post_thumbnail($post_id = null, $with_link = true) { } // Obtener la imagen con clases Bootstrap - $image = get_the_post_thumbnail($post_id, 'apus-featured-medium', array( + $image = get_the_post_thumbnail($post_id, 'roi-featured-medium', array( 'class' => 'img-fluid post-thumbnail', 'loading' => 'lazy', 'alt' => get_the_title($post_id) @@ -179,30 +179,30 @@ function apus_get_post_thumbnail($post_id = null, $with_link = true) { * Muestra el thumbnail del post para archives * * Template tag para usar directamente en template-parts. - * Echo wrapper de apus_get_post_thumbnail(). + * Echo wrapper de roi_get_post_thumbnail(). * * Uso en templates: - * - * + * + * * * @param int|null $post_id ID del post (null = post actual) * @param bool $with_link Envolver en enlace al post */ -function apus_the_post_thumbnail($post_id = null, $with_link = true) { - echo apus_get_post_thumbnail($post_id, $with_link); +function roi_the_post_thumbnail($post_id = null, $with_link = true) { + echo roi_get_post_thumbnail($post_id, $with_link); } /** * Obtiene HTML de thumbnail pequeño para widgets/sidebars * * Versión mini para listados compactos en sidebars. - * Usa el tamaño apus-thumbnail (400x300). + * Usa el tamaño roi-thumbnail (400x300). * * @param int|null $post_id ID del post (null = post actual) * @param bool $with_link Envolver en enlace al post (default: true) * @return string HTML del thumbnail o cadena vacía */ -function apus_get_post_thumbnail_small($post_id = null, $with_link = true) { +function roi_get_post_thumbnail_small($post_id = null, $with_link = true) { // Obtener ID del post actual si no se especifica if (!$post_id) { $post_id = get_the_ID(); @@ -219,7 +219,7 @@ function apus_get_post_thumbnail_small($post_id = null, $with_link = true) { } // Obtener la imagen - $image = get_the_post_thumbnail($post_id, 'apus-thumbnail', array( + $image = get_the_post_thumbnail($post_id, 'roi-thumbnail', array( 'class' => 'img-fluid post-thumbnail-small', 'loading' => 'lazy', 'alt' => get_the_title($post_id) @@ -250,13 +250,13 @@ function apus_get_post_thumbnail_small($post_id = null, $with_link = true) { * Muestra el thumbnail pequeño del post * * Template tag para usar en widgets y sidebars. - * Echo wrapper de apus_get_post_thumbnail_small(). + * Echo wrapper de roi_get_post_thumbnail_small(). * * @param int|null $post_id ID del post (null = post actual) * @param bool $with_link Envolver en enlace al post */ -function apus_the_post_thumbnail_small($post_id = null, $with_link = true) { - echo apus_get_post_thumbnail_small($post_id, $with_link); +function roi_the_post_thumbnail_small($post_id = null, $with_link = true) { + echo roi_get_post_thumbnail_small($post_id, $with_link); } /** @@ -266,14 +266,14 @@ function apus_the_post_thumbnail_small($post_id = null, $with_link = true) { * Útil para estructuras if/else en templates. * * Uso en templates: - * + * *
    ...
    * * * @param int|null $post_id ID del post (null = post actual) * @return bool True si debe mostrarse, false en caso contrario */ -function apus_should_show_featured_image($post_id = null) { +function roi_should_show_featured_image($post_id = null) { // Obtener ID del post actual si no se especifica if (!$post_id) { $post_id = get_the_ID(); @@ -293,17 +293,17 @@ function apus_should_show_featured_image($post_id = null) { $post_type = get_post_type($post_id); // Verificar configuración global según tipo de contenido - if (function_exists('apus_get_option')) { + if (function_exists('roi_get_option')) { if ($post_type === 'post') { - $enabled = apus_get_option('featured_image_single', true); + $enabled = roi_get_option('featured_image_single', true); } elseif ($post_type === 'page') { - $enabled = apus_get_option('featured_image_page', true); + $enabled = roi_get_option('featured_image_page', true); } else { - $enabled = apus_get_option('featured_image_' . $post_type, true); + $enabled = roi_get_option('featured_image_' . $post_type, true); } } else { // Fallback a theme_mod - $option_key = 'apus_featured_image_' . $post_type; + $option_key = 'roi_featured_image_' . $post_type; $enabled = get_theme_mod($option_key, true); } @@ -316,14 +316,14 @@ function apus_should_show_featured_image($post_id = null) { * Útil para backgrounds CSS o meta tags de redes sociales (Open Graph, Twitter Cards). * * Uso: - * $image_url = apus_get_featured_image_url(); + * $image_url = roi_get_featured_image_url(); * echo '
    '; * * @param int|null $post_id ID del post (null = post actual) - * @param string $size Tamaño de imagen registrado (default: apus-featured-large) + * @param string $size Tamaño de imagen registrado (default: roi-featured-large) * @return string URL de la imagen o cadena vacía */ -function apus_get_featured_image_url($post_id = null, $size = 'apus-featured-large') { +function roi_get_featured_image_url($post_id = null, $size = 'roi-featured-large') { // Obtener ID del post actual si no se especifica if (!$post_id) { $post_id = get_the_ID(); @@ -352,17 +352,17 @@ function apus_get_featured_image_url($post_id = null, $size = 'apus-featured-lar * Evita layout shift (CLS) con ratio predefinido usando Bootstrap ratio utility. * * Uso en templates: - * - * + * + * * * @param int|null $post_id ID del post (null = post actual) - * @param string $size Tamaño de imagen registrado (default: apus-featured-large) + * @param string $size Tamaño de imagen registrado (default: roi-featured-large) * @param string $aspect_ratio Ratio CSS - '2/1' para 2:1, '16/9', etc. (default: '2/1') * @return string HTML del contenedor con imagen o cadena vacía */ -function apus_get_featured_image_responsive($post_id = null, $size = 'apus-featured-large', $aspect_ratio = '2/1') { +function roi_get_featured_image_responsive($post_id = null, $size = 'roi-featured-large', $aspect_ratio = '2/1') { // Obtener la imagen - $image = apus_get_featured_image($post_id, $size); + $image = roi_get_featured_image($post_id, $size); // Si no hay imagen, retornar vacío if (empty($image)) { @@ -381,14 +381,14 @@ function apus_get_featured_image_responsive($post_id = null, $size = 'apus-featu * Muestra el contenedor responsive de imagen destacada * * Template tag para usar directamente en templates. - * Echo wrapper de apus_get_featured_image_responsive(). + * Echo wrapper de roi_get_featured_image_responsive(). * * @param int|null $post_id ID del post (null = post actual) * @param string $size Tamaño de imagen registrado * @param string $aspect_ratio Ratio CSS (ej: '16/9', '2/1') */ -function apus_the_featured_image_responsive($post_id = null, $size = 'apus-featured-large', $aspect_ratio = '2/1') { - echo apus_get_featured_image_responsive($post_id, $size, $aspect_ratio); +function roi_the_featured_image_responsive($post_id = null, $size = 'roi-featured-large', $aspect_ratio = '2/1') { + echo roi_get_featured_image_responsive($post_id, $size, $aspect_ratio); } /** @@ -399,7 +399,7 @@ function apus_the_featured_image_responsive($post_id = null, $size = 'apus-featu * @param string $post_type Tipo de post (vacío = post actual) * @return bool True si habilitadas, false en caso contrario */ -function apus_is_featured_image_enabled($post_type = '') { +function roi_is_featured_image_enabled($post_type = '') { if (empty($post_type)) { $post_type = get_post_type(); } @@ -408,19 +408,19 @@ function apus_is_featured_image_enabled($post_type = '') { return true; // Default habilitado } - // Intentar con apus_get_option primero - if (function_exists('apus_get_option')) { + // Intentar con roi_get_option primero + if (function_exists('roi_get_option')) { if ($post_type === 'post') { - return apus_get_option('featured_image_single', true); + return roi_get_option('featured_image_single', true); } elseif ($post_type === 'page') { - return apus_get_option('featured_image_page', true); + return roi_get_option('featured_image_page', true); } else { - return apus_get_option('featured_image_' . $post_type, true); + return roi_get_option('featured_image_' . $post_type, true); } } // Fallback a theme_mod - $option_key = 'apus_featured_image_' . $post_type; + $option_key = 'roi_featured_image_' . $post_type; return (bool) get_theme_mod($option_key, true); } @@ -432,16 +432,16 @@ function apus_is_featured_image_enabled($post_type = '') { * * @param WP_Customize_Manager $wp_customize Objeto Theme Customizer */ -function apus_featured_image_customizer($wp_customize) { +function roi_featured_image_customizer($wp_customize) { // Solo agregar si no existe el panel de opciones del tema - if (function_exists('apus_get_option')) { + if (function_exists('roi_get_option')) { return; // El panel de opciones manejará esto } // Agregar sección - $wp_customize->add_section('apus_featured_images', array( - 'title' => __('Imágenes Destacadas', 'apus-theme'), - 'description' => __('Configurar visualización de imágenes destacadas por tipo de contenido.', 'apus-theme'), + $wp_customize->add_section('roi_featured_images', array( + 'title' => __('Imágenes Destacadas', 'roi-theme'), + 'description' => __('Configurar visualización de imágenes destacadas por tipo de contenido.', 'roi-theme'), 'priority' => 30, )); @@ -454,7 +454,7 @@ function apus_featured_image_customizer($wp_customize) { continue; } - $setting_id = 'apus_featured_image_' . $post_type->name; + $setting_id = 'roi_featured_image_' . $post_type->name; // Agregar setting $wp_customize->add_setting($setting_id, array( @@ -467,12 +467,12 @@ function apus_featured_image_customizer($wp_customize) { $wp_customize->add_control($setting_id, array( 'label' => sprintf( /* translators: %s: nombre del tipo de post */ - __('Habilitar para %s', 'apus-theme'), + __('Habilitar para %s', 'roi-theme'), $post_type->labels->name ), - 'section' => 'apus_featured_images', + 'section' => 'roi_featured_images', 'type' => 'checkbox', )); } } -add_action('customize_register', 'apus_featured_image_customizer'); +add_action('customize_register', 'roi_featured_image_customizer'); diff --git a/inc/image-optimization.php b/inc/image-optimization.php index 8cb99913..c45714df 100644 --- a/inc/image-optimization.php +++ b/inc/image-optimization.php @@ -4,7 +4,7 @@ * * Handles responsive images, WebP/AVIF support, lazy loading, and image preloading. * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -16,51 +16,51 @@ if (!defined('ABSPATH')) { /** * Enable AVIF image support */ -function apus_enable_avif_support($mime_types) { +function roi_enable_avif_support($mime_types) { $mime_types['avif'] = 'image/avif'; return $mime_types; } -add_filter('upload_mimes', 'apus_enable_avif_support'); +add_filter('upload_mimes', 'roi_enable_avif_support'); /** * Add AVIF to allowed file extensions */ -function apus_allow_avif_extension($types, $file, $filename, $mimes) { +function roi_allow_avif_extension($types, $file, $filename, $mimes) { if (false !== strpos($filename, '.avif')) { $types['ext'] = 'avif'; $types['type'] = 'image/avif'; } return $types; } -add_filter('wp_check_filetype_and_ext', 'apus_allow_avif_extension', 10, 4); +add_filter('wp_check_filetype_and_ext', 'roi_allow_avif_extension', 10, 4); /** * Configure custom image sizes * Already defined in functions.php, but we can add more if needed */ -function apus_setup_additional_image_sizes() { +function roi_setup_additional_image_sizes() { // Add support for additional modern image sizes - add_image_size('apus-hero', 1920, 800, true); // Hero images - add_image_size('apus-card', 600, 400, true); // Card thumbnails - add_image_size('apus-thumbnail-2x', 800, 600, true); // Retina thumbnails + add_image_size('roi-hero', 1920, 800, true); // Hero images + add_image_size('roi-card', 600, 400, true); // Card thumbnails + add_image_size('roi-thumbnail-2x', 800, 600, true); // Retina thumbnails } -add_action('after_setup_theme', 'apus_setup_additional_image_sizes'); +add_action('after_setup_theme', 'roi_setup_additional_image_sizes'); /** * Add custom image sizes to media library dropdown */ -function apus_custom_image_sizes($sizes) { +function roi_custom_image_sizes($sizes) { return array_merge($sizes, array( - 'apus-thumbnail' => __('Thumbnail (400x300)', 'apus-theme'), - 'apus-medium' => __('Medium (800x600)', 'apus-theme'), - 'apus-large' => __('Large (1200x900)', 'apus-theme'), - 'apus-featured-large' => __('Featured Large (1200x600)', 'apus-theme'), - 'apus-featured-medium' => __('Featured Medium (800x400)', 'apus-theme'), - 'apus-hero' => __('Hero (1920x800)', 'apus-theme'), - 'apus-card' => __('Card (600x400)', 'apus-theme'), + 'roi-thumbnail' => __('Thumbnail (400x300)', 'roi-theme'), + 'roi-medium' => __('Medium (800x600)', 'roi-theme'), + 'roi-large' => __('Large (1200x900)', 'roi-theme'), + 'roi-featured-large' => __('Featured Large (1200x600)', 'roi-theme'), + 'roi-featured-medium' => __('Featured Medium (800x400)', 'roi-theme'), + 'roi-hero' => __('Hero (1920x800)', 'roi-theme'), + 'roi-card' => __('Card (600x400)', 'roi-theme'), )); } -add_filter('image_size_names_choose', 'apus_custom_image_sizes'); +add_filter('image_size_names_choose', 'roi_custom_image_sizes'); /** * Generate srcset and sizes attributes for responsive images @@ -70,7 +70,7 @@ add_filter('image_size_names_choose', 'apus_custom_image_sizes'); * @param array $additional_sizes Additional sizes to include in srcset * @return array Array with 'srcset' and 'sizes' attributes */ -function apus_get_responsive_image_attrs($attachment_id, $size = 'full', $additional_sizes = array()) { +function roi_get_responsive_image_attrs($attachment_id, $size = 'full', $additional_sizes = array()) { if (empty($attachment_id)) { return array('srcset' => '', 'sizes' => ''); } @@ -110,13 +110,13 @@ function apus_get_responsive_image_attrs($attachment_id, $size = 'full', $additi * @param bool $lazy Enable lazy loading (default: true) * @return string Image HTML */ -function apus_get_responsive_image($attachment_id, $size = 'full', $attr = array(), $lazy = true) { +function roi_get_responsive_image($attachment_id, $size = 'full', $attr = array(), $lazy = true) { if (empty($attachment_id)) { return ''; } // Get responsive attributes - $responsive_attrs = apus_get_responsive_image_attrs($attachment_id, $size); + $responsive_attrs = roi_get_responsive_image_attrs($attachment_id, $size); // Merge default attributes with custom ones $default_attr = array( @@ -140,7 +140,7 @@ function apus_get_responsive_image($attachment_id, $size = 'full', $attr = array /** * Enable lazy loading by default for all images */ -function apus_add_lazy_loading_to_images($attr, $attachment, $size) { +function roi_add_lazy_loading_to_images($attr, $attachment, $size) { // Don't add lazy loading if explicitly disabled if (isset($attr['loading']) && $attr['loading'] === 'eager') { return $attr; @@ -158,12 +158,12 @@ function apus_add_lazy_loading_to_images($attr, $attachment, $size) { return $attr; } -add_filter('wp_get_attachment_image_attributes', 'apus_add_lazy_loading_to_images', 10, 3); +add_filter('wp_get_attachment_image_attributes', 'roi_add_lazy_loading_to_images', 10, 3); /** * Add lazy loading to content images */ -function apus_add_lazy_loading_to_content($content) { +function roi_add_lazy_loading_to_content($content) { // Don't process if empty if (empty($content)) { return $content; @@ -174,7 +174,7 @@ function apus_add_lazy_loading_to_content($content) { return $content; } -add_filter('the_content', 'apus_add_lazy_loading_to_content', 20); +add_filter('the_content', 'roi_add_lazy_loading_to_content', 20); /** * Preload critical images (LCP images) @@ -183,7 +183,7 @@ add_filter('the_content', 'apus_add_lazy_loading_to_content', 20); * @param int $attachment_id Image attachment ID * @param string $size Image size */ -function apus_preload_image($attachment_id, $size = 'full') { +function roi_preload_image($attachment_id, $size = 'full') { if (empty($attachment_id)) { return; } @@ -230,7 +230,7 @@ function apus_preload_image($attachment_id, $size = 'full') { /** * Preload featured image for single posts (LCP optimization) */ -function apus_preload_featured_image() { +function roi_preload_featured_image() { // Only on single posts/pages with featured images if (!is_singular() || !has_post_thumbnail()) { return; @@ -240,17 +240,17 @@ function apus_preload_featured_image() { $thumbnail_id = get_post_thumbnail_id(); // Determine the size based on the post type - $size = 'apus-featured-large'; + $size = 'roi-featured-large'; // Preload the image - apus_preload_image($thumbnail_id, $size); + roi_preload_image($thumbnail_id, $size); } -add_action('wp_head', 'apus_preload_featured_image', 5); +add_action('wp_head', 'roi_preload_featured_image', 5); /** * Enable fetchpriority attribute for featured images */ -function apus_add_fetchpriority_to_featured_image($attr, $attachment, $size) { +function roi_add_fetchpriority_to_featured_image($attr, $attachment, $size) { // Only add fetchpriority="high" to featured images on singular pages if (is_singular() && get_post_thumbnail_id() === $attachment->ID) { $attr['fetchpriority'] = 'high'; @@ -259,20 +259,20 @@ function apus_add_fetchpriority_to_featured_image($attr, $attachment, $size) { return $attr; } -add_filter('wp_get_attachment_image_attributes', 'apus_add_fetchpriority_to_featured_image', 20, 3); +add_filter('wp_get_attachment_image_attributes', 'roi_add_fetchpriority_to_featured_image', 20, 3); /** * Optimize image quality for uploads */ -function apus_optimize_image_quality($quality, $mime_type) { +function roi_optimize_image_quality($quality, $mime_type) { // Set quality to 85% for better file size without visible quality loss if ($mime_type === 'image/jpeg') { return 85; } return $quality; } -add_filter('jpeg_quality', 'apus_optimize_image_quality', 10, 2); -add_filter('wp_editor_set_quality', 'apus_optimize_image_quality', 10, 2); +add_filter('jpeg_quality', 'roi_optimize_image_quality', 10, 2); +add_filter('wp_editor_set_quality', 'roi_optimize_image_quality', 10, 2); /** * Add picture element support for WebP/AVIF with fallbacks @@ -282,7 +282,7 @@ add_filter('wp_editor_set_quality', 'apus_optimize_image_quality', 10, 2); * @param array $attr Additional attributes * @return string Picture element HTML */ -function apus_get_picture_element($attachment_id, $size = 'full', $attr = array()) { +function roi_get_picture_element($attachment_id, $size = 'full', $attr = array()) { if (empty($attachment_id)) { return ''; } @@ -340,26 +340,26 @@ function apus_get_picture_element($attachment_id, $size = 'full', $attr = array( * WordPress 5.3+ escala imágenes mayores a 2560px por defecto * Mantenemos 2560px como límite para balance entre calidad y rendimiento */ -function apus_big_image_size_threshold($threshold) { +function roi_big_image_size_threshold($threshold) { // Mantener 2560px como threshold (no desactivar completamente) return 2560; } -add_filter('big_image_size_threshold', 'apus_big_image_size_threshold'); +add_filter('big_image_size_threshold', 'roi_big_image_size_threshold'); /** * Set maximum srcset image width */ -function apus_max_srcset_image_width($max_width, $size_array) { +function roi_max_srcset_image_width($max_width, $size_array) { // Limit srcset to images up to 2560px wide return 2560; } -add_filter('max_srcset_image_width', 'apus_max_srcset_image_width', 10, 2); +add_filter('max_srcset_image_width', 'roi_max_srcset_image_width', 10, 2); /** * Habilitar generación automática de WebP en WordPress * WordPress 5.8+ soporta WebP nativamente si el servidor tiene soporte */ -function apus_enable_webp_generation($editors) { +function roi_enable_webp_generation($editors) { // Verificar que GD o Imagick tengan soporte WebP if (extension_loaded('gd')) { $gd_info = gd_info(); @@ -380,12 +380,12 @@ function apus_enable_webp_generation($editors) { return $editors; } -add_filter('wp_image_editors', 'apus_enable_webp_generation'); +add_filter('wp_image_editors', 'roi_enable_webp_generation'); /** * Configurar tipos MIME adicionales para WebP y AVIF */ -function apus_additional_mime_types($mimes) { +function roi_additional_mime_types($mimes) { // WebP ya está soportado en WordPress 5.8+, pero lo agregamos por compatibilidad if (!isset($mimes['webp'])) { $mimes['webp'] = 'image/webp'; @@ -398,12 +398,12 @@ function apus_additional_mime_types($mimes) { return $mimes; } -add_filter('mime_types', 'apus_additional_mime_types'); +add_filter('mime_types', 'roi_additional_mime_types'); /** * Remover tamaños de imagen no utilizados para ahorrar espacio */ -function apus_remove_unused_image_sizes($sizes) { +function roi_remove_unused_image_sizes($sizes) { // Remover tamaños de WordPress que no usamos unset($sizes['medium_large']); // 768px - no necesario con nuestros tamaños custom unset($sizes['1536x1536']); // 2x medium_large - no necesario @@ -411,42 +411,42 @@ function apus_remove_unused_image_sizes($sizes) { return $sizes; } -add_filter('intermediate_image_sizes_advanced', 'apus_remove_unused_image_sizes'); +add_filter('intermediate_image_sizes_advanced', 'roi_remove_unused_image_sizes'); /** * Agregar sizes attribute personalizado según contexto * Mejora la selección del tamaño correcto de imagen por el navegador */ -function apus_responsive_image_sizes_attr($sizes, $size, $image_src, $image_meta, $attachment_id) { +function roi_responsive_image_sizes_attr($sizes, $size, $image_src, $image_meta, $attachment_id) { // Para imágenes destacadas grandes (single posts) - if ($size === 'apus-featured-large' || $size === 'apus-large') { + if ($size === 'roi-featured-large' || $size === 'roi-large') { $sizes = '(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px'; } // Para imágenes destacadas medianas (archives) - elseif ($size === 'apus-featured-medium' || $size === 'apus-medium') { + elseif ($size === 'roi-featured-medium' || $size === 'roi-medium') { $sizes = '(max-width: 768px) 100vw, (max-width: 992px) 50vw, 800px'; } // Para thumbnails (widgets, related posts) - elseif ($size === 'apus-thumbnail') { + elseif ($size === 'roi-thumbnail') { $sizes = '(max-width: 576px) 100vw, 400px'; } // Para hero images - elseif ($size === 'apus-hero') { + elseif ($size === 'roi-hero') { $sizes = '100vw'; } return $sizes; } -add_filter('wp_calculate_image_sizes', 'apus_responsive_image_sizes_attr', 10, 5); +add_filter('wp_calculate_image_sizes', 'roi_responsive_image_sizes_attr', 10, 5); /** * Forzar regeneración de metadatos de imagen para incluir WebP/AVIF * Solo se ejecuta cuando sea necesario */ -function apus_maybe_regenerate_image_metadata($metadata, $attachment_id) { +function roi_maybe_regenerate_image_metadata($metadata, $attachment_id) { // Verificar si ya tiene formatos modernos generados if (!empty($metadata) && is_array($metadata)) { // WordPress maneja automáticamente la generación de sub-formatos @@ -455,12 +455,12 @@ function apus_maybe_regenerate_image_metadata($metadata, $attachment_id) { return $metadata; } -add_filter('wp_generate_attachment_metadata', 'apus_maybe_regenerate_image_metadata', 10, 2); +add_filter('wp_generate_attachment_metadata', 'roi_maybe_regenerate_image_metadata', 10, 2); /** * Excluir lazy loading en la primera imagen del contenido (posible LCP) */ -function apus_skip_lazy_loading_first_image($content) { +function roi_skip_lazy_loading_first_image($content) { // Solo en posts/páginas singulares if (!is_singular()) { return $content; @@ -482,13 +482,13 @@ function apus_skip_lazy_loading_first_image($content) { return $content; } -add_filter('the_content', 'apus_skip_lazy_loading_first_image', 15); +add_filter('the_content', 'roi_skip_lazy_loading_first_image', 15); /** * Agregar soporte para formatos de imagen modernos en subsizes * WordPress 5.8+ genera automáticamente WebP si está disponible */ -function apus_enable_image_subsizes($metadata, $attachment_id, $context) { +function roi_enable_image_subsizes($metadata, $attachment_id, $context) { if ($context !== 'create') { return $metadata; } @@ -497,4 +497,4 @@ function apus_enable_image_subsizes($metadata, $attachment_id, $context) { // Este filtro asegura que se ejecute correctamente return $metadata; } -add_filter('wp_generate_attachment_metadata', 'apus_enable_image_subsizes', 20, 3); +add_filter('wp_generate_attachment_metadata', 'roi_enable_image_subsizes', 20, 3); diff --git a/inc/nav-walker.php b/inc/nav-walker.php index b87bddc9..b49a37b7 100644 --- a/inc/nav-walker.php +++ b/inc/nav-walker.php @@ -5,7 +5,7 @@ * Custom Walker para wp_nav_menu() compatible con Bootstrap 5. * Genera markup correcto para navbar, dropdowns y menús responsive. * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -191,7 +191,7 @@ class WP_Bootstrap_Navwalker extends Walker_Nav_Menu { echo ''; diff --git a/inc/performance.php b/inc/performance.php index be775ae6..19e95145 100644 --- a/inc/performance.php +++ b/inc/performance.php @@ -7,7 +7,7 @@ * NOTA: Versión reducida con solo optimizaciones seguras después de * resolver problemas de memory exhaustion en Issue #22. * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -24,7 +24,7 @@ if ( ! defined( 'ABSPATH' ) ) { * * @since 1.0.0 */ -function apus_disable_emojis() { +function roi_disable_emojis() { remove_action( 'wp_head', 'print_emoji_detection_script', 7 ); remove_action( 'admin_print_scripts', 'print_emoji_detection_script' ); remove_action( 'wp_print_styles', 'print_emoji_styles' ); @@ -34,9 +34,9 @@ function apus_disable_emojis() { remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' ); // Remove from TinyMCE. - add_filter( 'tiny_mce_plugins', 'apus_disable_emojis_tinymce' ); + add_filter( 'tiny_mce_plugins', 'roi_disable_emojis_tinymce' ); } -add_action( 'init', 'apus_disable_emojis' ); +add_action( 'init', 'roi_disable_emojis' ); /** * Filter function used to remove emoji plugin from TinyMCE @@ -45,7 +45,7 @@ add_action( 'init', 'apus_disable_emojis' ); * @param array $plugins An array of default TinyMCE plugins. * @return array Modified array of TinyMCE plugins without emoji plugin. */ -function apus_disable_emojis_tinymce( $plugins ) { +function roi_disable_emojis_tinymce( $plugins ) { if ( is_array( $plugins ) ) { return array_diff( $plugins, array( 'wpemoji' ) ); } @@ -61,7 +61,7 @@ function apus_disable_emojis_tinymce( $plugins ) { * * @since 1.0.0 */ -function apus_disable_oembed() { +function roi_disable_oembed() { // Remove oEmbed discovery links. remove_action( 'wp_head', 'wp_oembed_add_discovery_links' ); @@ -69,12 +69,12 @@ function apus_disable_oembed() { remove_action( 'wp_head', 'wp_oembed_add_host_js' ); // Remove all embeds rewrite rules. - add_filter( 'rewrite_rules_array', 'apus_disable_oembed_rewrites' ); + add_filter( 'rewrite_rules_array', 'roi_disable_oembed_rewrites' ); // Remove filter of the oEmbed result before any HTTP requests are made. remove_filter( 'pre_oembed_result', 'wp_filter_pre_oembed_result', 10 ); } -add_action( 'init', 'apus_disable_oembed', 9999 ); +add_action( 'init', 'roi_disable_oembed', 9999 ); /** * Remove all rewrite rules related to embeds @@ -83,7 +83,7 @@ add_action( 'init', 'apus_disable_oembed', 9999 ); * @param array $rules WordPress rewrite rules. * @return array Modified rewrite rules. */ -function apus_disable_oembed_rewrites( $rules ) { +function roi_disable_oembed_rewrites( $rules ) { foreach ( $rules as $rule => $rewrite ) { if ( false !== strpos( $rewrite, 'embed=true' ) ) { unset( $rules[ $rule ] ); @@ -100,10 +100,10 @@ function apus_disable_oembed_rewrites( $rules ) { * * @since 1.0.0 */ -function apus_dequeue_embed_script() { +function roi_dequeue_embed_script() { wp_deregister_script( 'wp-embed' ); } -add_action( 'wp_footer', 'apus_dequeue_embed_script' ); +add_action( 'wp_footer', 'roi_dequeue_embed_script' ); /** * Disable WordPress Feeds @@ -113,10 +113,10 @@ add_action( 'wp_footer', 'apus_dequeue_embed_script' ); * * @since 1.0.0 */ -function apus_disable_feeds() { +function roi_disable_feeds() { wp_die( - esc_html__( 'No feed available, please visit our homepage!', 'apus' ), - esc_html__( 'Feed Not Available', 'apus' ), + esc_html__( 'No feed available, please visit our homepage!', 'roi' ), + esc_html__( 'Feed Not Available', 'roi' ), array( 'response' => 404, 'back_link' => true, @@ -129,21 +129,21 @@ function apus_disable_feeds() { * * @since 1.0.0 */ -function apus_disable_feed_links() { +function roi_disable_feed_links() { // Remove feed links from header. remove_action( 'wp_head', 'feed_links', 2 ); remove_action( 'wp_head', 'feed_links_extra', 3 ); // Redirect feed URLs to homepage. - add_action( 'do_feed', 'apus_disable_feeds', 1 ); - add_action( 'do_feed_rdf', 'apus_disable_feeds', 1 ); - add_action( 'do_feed_rss', 'apus_disable_feeds', 1 ); - add_action( 'do_feed_rss2', 'apus_disable_feeds', 1 ); - add_action( 'do_feed_atom', 'apus_disable_feeds', 1 ); - add_action( 'do_feed_rss2_comments', 'apus_disable_feeds', 1 ); - add_action( 'do_feed_atom_comments', 'apus_disable_feeds', 1 ); + add_action( 'do_feed', 'roi_disable_feeds', 1 ); + add_action( 'do_feed_rdf', 'roi_disable_feeds', 1 ); + add_action( 'do_feed_rss', 'roi_disable_feeds', 1 ); + add_action( 'do_feed_rss2', 'roi_disable_feeds', 1 ); + add_action( 'do_feed_atom', 'roi_disable_feeds', 1 ); + add_action( 'do_feed_rss2_comments', 'roi_disable_feeds', 1 ); + add_action( 'do_feed_atom_comments', 'roi_disable_feeds', 1 ); } -add_action( 'init', 'apus_disable_feed_links' ); +add_action( 'init', 'roi_disable_feed_links' ); /** * Disable RSD and Windows Live Writer Manifest @@ -153,14 +153,14 @@ add_action( 'init', 'apus_disable_feed_links' ); * * @since 1.0.0 */ -function apus_disable_rsd_wlw() { +function roi_disable_rsd_wlw() { // Remove RSD link. remove_action( 'wp_head', 'rsd_link' ); // Remove Windows Live Writer manifest link. remove_action( 'wp_head', 'wlwmanifest_link' ); } -add_action( 'init', 'apus_disable_rsd_wlw' ); +add_action( 'init', 'roi_disable_rsd_wlw' ); /** * Disable Dashicons for non-logged users @@ -170,12 +170,12 @@ add_action( 'init', 'apus_disable_rsd_wlw' ); * * @since 1.0.0 */ -function apus_disable_dashicons() { +function roi_disable_dashicons() { if ( ! is_user_logged_in() ) { wp_deregister_style( 'dashicons' ); } } -add_action( 'wp_enqueue_scripts', 'apus_disable_dashicons' ); +add_action( 'wp_enqueue_scripts', 'roi_disable_dashicons' ); /** * Disable Block Library CSS @@ -186,7 +186,7 @@ add_action( 'wp_enqueue_scripts', 'apus_disable_dashicons' ); * * @since 1.0.0 */ -function apus_disable_block_library_css() { +function roi_disable_block_library_css() { // Remove default block library styles. wp_dequeue_style( 'wp-block-library' ); wp_dequeue_style( 'wp-block-library-theme' ); @@ -197,7 +197,7 @@ function apus_disable_block_library_css() { // Remove classic theme styles (if not using classic editor). wp_dequeue_style( 'classic-theme-styles' ); } -add_action( 'wp_enqueue_scripts', 'apus_disable_block_library_css', 100 ); +add_action( 'wp_enqueue_scripts', 'roi_disable_block_library_css', 100 ); /** * Remove WordPress version from head and feeds @@ -206,10 +206,10 @@ add_action( 'wp_enqueue_scripts', 'apus_disable_block_library_css', 100 ); * * @since 1.0.0 */ -function apus_remove_wp_version() { +function roi_remove_wp_version() { return ''; } -add_filter( 'the_generator', 'apus_remove_wp_version' ); +add_filter( 'the_generator', 'roi_remove_wp_version' ); /** * Disable XML-RPC @@ -220,10 +220,10 @@ add_filter( 'the_generator', 'apus_remove_wp_version' ); * @since 1.0.0 * @return bool */ -function apus_disable_xmlrpc() { +function roi_disable_xmlrpc() { return false; } -add_filter( 'xmlrpc_enabled', 'apus_disable_xmlrpc' ); +add_filter( 'xmlrpc_enabled', 'roi_disable_xmlrpc' ); /** * Remove jQuery Migrate @@ -234,7 +234,7 @@ add_filter( 'xmlrpc_enabled', 'apus_disable_xmlrpc' ); * @since 1.0.0 * @param WP_Scripts $scripts WP_Scripts object. */ -function apus_remove_jquery_migrate( $scripts ) { +function roi_remove_jquery_migrate( $scripts ) { if ( ! is_admin() && isset( $scripts->registered['jquery'] ) ) { $script = $scripts->registered['jquery']; @@ -244,7 +244,7 @@ function apus_remove_jquery_migrate( $scripts ) { } } } -add_action( 'wp_default_scripts', 'apus_remove_jquery_migrate' ); +add_action( 'wp_default_scripts', 'roi_remove_jquery_migrate' ); /** * Optimize WordPress Database Queries @@ -253,12 +253,12 @@ add_action( 'wp_default_scripts', 'apus_remove_jquery_migrate' ); * * @since 1.0.0 */ -function apus_optimize_queries() { +function roi_optimize_queries() { // Remove unnecessary post meta from queries remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10 ); remove_action( 'wp_head', 'wp_shortlink_wp_head', 10 ); } -add_action( 'init', 'apus_optimize_queries' ); +add_action( 'init', 'roi_optimize_queries' ); /** * Disable WordPress Admin Bar for Non-Admins @@ -267,12 +267,12 @@ add_action( 'init', 'apus_optimize_queries' ); * * @since 1.0.0 */ -function apus_disable_admin_bar() { +function roi_disable_admin_bar() { if ( ! current_user_can( 'administrator' ) && ! is_admin() ) { show_admin_bar( false ); } } -add_action( 'after_setup_theme', 'apus_disable_admin_bar' ); +add_action( 'after_setup_theme', 'roi_disable_admin_bar' ); /** * ============================================================================ @@ -291,7 +291,7 @@ add_action( 'after_setup_theme', 'apus_disable_admin_bar' ); * @param string $relation_type The relation type (dns-prefetch, preconnect, etc.). * @return array Modified array of resource URLs. */ -function apus_add_resource_hints( $urls, $relation_type ) { +function roi_add_resource_hints( $urls, $relation_type ) { // DNS Prefetch para recursos externos que no son críticos if ( 'dns-prefetch' === $relation_type ) { // CDN de Bootstrap Icons (ya usado en enqueue-scripts.php) @@ -318,7 +318,7 @@ function apus_add_resource_hints( $urls, $relation_type ) { return $urls; } -add_filter( 'wp_resource_hints', 'apus_add_resource_hints', 10, 2 ); +add_filter( 'wp_resource_hints', 'roi_add_resource_hints', 10, 2 ); /** * Preload de recursos críticos para mejorar LCP @@ -328,7 +328,7 @@ add_filter( 'wp_resource_hints', 'apus_add_resource_hints', 10, 2 ); * * @since 1.0.0 */ -function apus_preload_critical_resources() { +function roi_preload_critical_resources() { // Preload de fuentes críticas $fonts = array( 'inter-var.woff2', @@ -357,7 +357,7 @@ function apus_preload_critical_resources() { esc_url( $fonts_css ) ); } -add_action( 'wp_head', 'apus_preload_critical_resources', 2 ); +add_action( 'wp_head', 'roi_preload_critical_resources', 2 ); /** * ============================================================================ @@ -376,7 +376,7 @@ add_action( 'wp_head', 'apus_preload_critical_resources', 2 ); * @param string $handle The script handle. * @return string Modified script tag. */ -function apus_add_script_attributes( $tag, $handle ) { +function roi_add_script_attributes( $tag, $handle ) { // Scripts que deben tener async (no dependen de otros ni del DOM) $async_scripts = array( // Google Analytics u otros scripts de tracking @@ -396,7 +396,7 @@ function apus_add_script_attributes( $tag, $handle ) { return $tag; } -add_filter( 'script_loader_tag', 'apus_add_script_attributes', 10, 2 ); +add_filter( 'script_loader_tag', 'roi_add_script_attributes', 10, 2 ); /** * Optimizar el Heartbeat API de WordPress @@ -406,13 +406,13 @@ add_filter( 'script_loader_tag', 'apus_add_script_attributes', 10, 2 ); * * @since 1.0.0 */ -function apus_optimize_heartbeat() { +function roi_optimize_heartbeat() { // Desactivar completamente en el frontend if ( ! is_admin() ) { wp_deregister_script( 'heartbeat' ); } } -add_action( 'init', 'apus_optimize_heartbeat', 1 ); +add_action( 'init', 'roi_optimize_heartbeat', 1 ); /** * Modificar configuración del Heartbeat en admin @@ -421,12 +421,12 @@ add_action( 'init', 'apus_optimize_heartbeat', 1 ); * @param array $settings Heartbeat settings. * @return array Modified settings. */ -function apus_modify_heartbeat_settings( $settings ) { +function roi_modify_heartbeat_settings( $settings ) { // Cambiar intervalo de 15 segundos (default) a 60 segundos $settings['interval'] = 60; return $settings; } -add_filter( 'heartbeat_settings', 'apus_modify_heartbeat_settings' ); +add_filter( 'heartbeat_settings', 'roi_modify_heartbeat_settings' ); /** * ============================================================================ @@ -449,7 +449,7 @@ add_filter( 'heartbeat_settings', 'apus_modify_heartbeat_settings' ); * @since 1.0.0 * @param WP_Query $query The WP_Query instance. */ -function apus_optimize_main_query( $query ) { +function roi_optimize_main_query( $query ) { // Solo en queries principales en el frontend if ( is_admin() || ! $query->is_main_query() ) { return; @@ -467,7 +467,7 @@ function apus_optimize_main_query( $query ) { } } } -add_action( 'pre_get_posts', 'apus_optimize_main_query' ); +add_action( 'pre_get_posts', 'roi_optimize_main_query' ); /** * Deshabilitar self-pingbacks @@ -479,7 +479,7 @@ add_action( 'pre_get_posts', 'apus_optimize_main_query' ); * @param array $links An array of post links to ping. * @return array Modified array without self-pings. */ -function apus_disable_self_pingbacks( &$links ) { +function roi_disable_self_pingbacks( &$links ) { $home = get_option( 'home' ); foreach ( $links as $l => $link ) { if ( 0 === strpos( $link, $home ) ) { @@ -487,7 +487,7 @@ function apus_disable_self_pingbacks( &$links ) { } } } -add_action( 'pre_ping', 'apus_disable_self_pingbacks' ); +add_action( 'pre_ping', 'roi_disable_self_pingbacks' ); /** * ============================================================================ @@ -505,13 +505,13 @@ add_action( 'pre_ping', 'apus_disable_self_pingbacks' ); * @param string $src The source URL. * @return string Modified source URL. */ -function apus_add_font_display_swap( $src ) { +function roi_add_font_display_swap( $src ) { if ( strpos( $src, 'fonts.googleapis.com' ) !== false ) { $src = add_query_arg( 'display', 'swap', $src ); } return $src; } -add_filter( 'style_loader_src', 'apus_add_font_display_swap' ); +add_filter( 'style_loader_src', 'roi_add_font_display_swap' ); /** * Agregar width y height a imágenes para prevenir CLS @@ -521,10 +521,10 @@ add_filter( 'style_loader_src', 'apus_add_font_display_swap' ); * @since 1.0.0 * @return bool */ -function apus_enable_image_dimensions() { +function roi_enable_image_dimensions() { return true; } -add_filter( 'wp_lazy_loading_enabled', 'apus_enable_image_dimensions' ); +add_filter( 'wp_lazy_loading_enabled', 'roi_enable_image_dimensions' ); /** * Optimizar buffer de salida HTML @@ -533,7 +533,7 @@ add_filter( 'wp_lazy_loading_enabled', 'apus_enable_image_dimensions' ); * * @since 1.0.0 */ -function apus_enable_gzip_compression() { +function roi_enable_gzip_compression() { // Solo en frontend if ( is_admin() ) { return; @@ -552,7 +552,7 @@ function apus_enable_gzip_compression() { } } } -add_action( 'template_redirect', 'apus_enable_gzip_compression', 0 ); +add_action( 'template_redirect', 'roi_enable_gzip_compression', 0 ); /** * ============================================================================ @@ -567,24 +567,24 @@ add_action( 'template_redirect', 'apus_enable_gzip_compression', 0 ); * * @since 1.0.0 */ -function apus_cleanup_expired_transients() { +function roi_cleanup_expired_transients() { global $wpdb; // Eliminar transients expirados (solo los del tema) $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s AND option_value < %d", - $wpdb->esc_like( '_transient_timeout_apus_' ) . '%', + $wpdb->esc_like( '_transient_timeout_roi_' ) . '%', time() ) ); } // Ejecutar limpieza semanalmente -add_action( 'apus_weekly_cleanup', 'apus_cleanup_expired_transients' ); +add_action( 'roi_weekly_cleanup', 'roi_cleanup_expired_transients' ); // Registrar evento cron si no existe -if ( ! wp_next_scheduled( 'apus_weekly_cleanup' ) ) { - wp_schedule_event( time(), 'weekly', 'apus_weekly_cleanup' ); +if ( ! wp_next_scheduled( 'roi_weekly_cleanup' ) ) { + wp_schedule_event( time(), 'weekly', 'roi_weekly_cleanup' ); } /* diff --git a/inc/related-posts.php b/inc/related-posts.php index 3eedef96..8f9df840 100644 --- a/inc/related-posts.php +++ b/inc/related-posts.php @@ -4,7 +4,7 @@ * * Provides configurable related posts functionality with Bootstrap grid support. * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -19,7 +19,7 @@ if (!defined('ABSPATH')) { * @param int $post_id The post ID to get related posts for * @return WP_Query|false Query object with related posts or false if none found */ -function apus_get_related_posts($post_id) { +function roi_get_related_posts($post_id) { // Get post categories $categories = wp_get_post_categories($post_id); @@ -28,7 +28,7 @@ function apus_get_related_posts($post_id) { } // Get number of posts to display (default: 3) - $posts_per_page = get_option('apus_related_posts_count', 3); + $posts_per_page = get_option('roi_related_posts_count', 3); // Query arguments $args = array( @@ -44,7 +44,7 @@ function apus_get_related_posts($post_id) { ); // Allow filtering of query args - $args = apply_filters('apus_related_posts_args', $args, $post_id); + $args = apply_filters('roi_related_posts_args', $args, $post_id); // Get related posts $related_query = new WP_Query($args); @@ -58,33 +58,33 @@ function apus_get_related_posts($post_id) { * @param int|null $post_id Optional. Post ID. Default is current post. * @return void */ -function apus_display_related_posts($post_id = null) { +function roi_display_related_posts($post_id = null) { // Get post ID if (!$post_id) { $post_id = get_the_ID(); } // Check if related posts are enabled - $enabled = get_option('apus_related_posts_enabled', true); + $enabled = get_option('roi_related_posts_enabled', true); if (!$enabled) { return; } // Get related posts - $related_query = apus_get_related_posts($post_id); + $related_query = roi_get_related_posts($post_id); if (!$related_query) { return; } // Get configuration options - $title = get_option('apus_related_posts_title', __('Related Posts', 'apus-theme')); - $columns = get_option('apus_related_posts_columns', 3); - $show_excerpt = get_option('apus_related_posts_show_excerpt', true); - $show_date = get_option('apus_related_posts_show_date', true); - $show_category = get_option('apus_related_posts_show_category', true); - $excerpt_length = get_option('apus_related_posts_excerpt_length', 20); - $background_colors = get_option('apus_related_posts_bg_colors', array( + $title = get_option('roi_related_posts_title', __('Related Posts', 'roi-theme')); + $columns = get_option('roi_related_posts_columns', 3); + $show_excerpt = get_option('roi_related_posts_show_excerpt', true); + $show_date = get_option('roi_related_posts_show_date', true); + $show_category = get_option('roi_related_posts_show_category', true); + $excerpt_length = get_option('roi_related_posts_excerpt_length', 20); + $background_colors = get_option('roi_related_posts_bg_colors', array( '#1a73e8', // Blue '#e91e63', // Pink '#4caf50', // Green @@ -94,7 +94,7 @@ function apus_display_related_posts($post_id = null) { )); // Calculate Bootstrap column class - $col_class = apus_get_column_class($columns); + $col_class = roi_get_column_class($columns); // Start output ?> @@ -126,7 +126,7 @@ function apus_display_related_posts($post_id = null) {
    the_title_attribute(array('echo' => false)), 'loading' => 'lazy', )); @@ -213,7 +213,7 @@ function apus_display_related_posts($post_id = null) { * @param int $columns Number of columns (1-4) * @return string Bootstrap column classes */ -function apus_get_column_class($columns) { +function roi_get_column_class($columns) { $columns = absint($columns); switch ($columns) { @@ -233,49 +233,49 @@ function apus_get_column_class($columns) { /** * Hook related posts display after post content */ -function apus_hook_related_posts() { +function roi_hook_related_posts() { if (is_single() && !is_attachment()) { - apus_display_related_posts(); + roi_display_related_posts(); } } -add_action('apus_after_post_content', 'apus_hook_related_posts'); +add_action('roi_after_post_content', 'roi_hook_related_posts'); /** * Enqueue related posts styles */ -function apus_enqueue_related_posts_styles() { +function roi_enqueue_related_posts_styles() { if (is_single() && !is_attachment()) { - $enabled = get_option('apus_related_posts_enabled', true); + $enabled = get_option('roi_related_posts_enabled', true); if ($enabled) { wp_enqueue_style( - 'apus-related-posts', + 'roirelated-posts', get_template_directory_uri() . '/assets/css/related-posts.css', - array('apus-bootstrap'), - APUS_VERSION, + array('roibootstrap'), + ROI_VERSION, 'all' ); } } } -add_action('wp_enqueue_scripts', 'apus_enqueue_related_posts_styles'); +add_action('wp_enqueue_scripts', 'roi_enqueue_related_posts_styles'); /** * Register related posts settings * These can be configured via theme options or customizer */ -function apus_related_posts_default_options() { +function roi_related_posts_default_options() { // Set default options if they don't exist $defaults = array( - 'apus_related_posts_enabled' => true, - 'apus_related_posts_title' => __('Related Posts', 'apus-theme'), - 'apus_related_posts_count' => 3, - 'apus_related_posts_columns' => 3, - 'apus_related_posts_show_excerpt' => true, - 'apus_related_posts_excerpt_length' => 20, - 'apus_related_posts_show_date' => true, - 'apus_related_posts_show_category' => true, - 'apus_related_posts_bg_colors' => array( + 'roi_related_posts_enabled' => true, + 'roi_related_posts_title' => __('Related Posts', 'roi-theme'), + 'roi_related_posts_count' => 3, + 'roi_related_posts_columns' => 3, + 'roi_related_posts_show_excerpt' => true, + 'roi_related_posts_excerpt_length' => 20, + 'roi_related_posts_show_date' => true, + 'roi_related_posts_show_category' => true, + 'roi_related_posts_bg_colors' => array( '#1a73e8', // Blue '#e91e63', // Pink '#4caf50', // Green @@ -291,4 +291,4 @@ function apus_related_posts_default_options() { } } } -add_action('after_setup_theme', 'apus_related_posts_default_options'); +add_action('after_setup_theme', 'roi_related_posts_default_options'); diff --git a/inc/sanitize-functions.php b/inc/sanitize-functions.php index 8e1c6517..92c7bbcf 100644 --- a/inc/sanitize-functions.php +++ b/inc/sanitize-functions.php @@ -1,11 +1,11 @@ manager->get_control($setting->id)->choices; @@ -51,7 +51,7 @@ if (!function_exists('apus_sanitize_select')) { } } -if (!function_exists('apus_sanitize_css')) { +if (!function_exists('roi_sanitize_css')) { /** * Sanitiza CSS * @@ -61,7 +61,7 @@ if (!function_exists('apus_sanitize_css')) { * @return string CSS sanitizado * @since 1.0.0 */ - function apus_sanitize_css($css) { + function roi_sanitize_css($css) { // Remove #is', '', $css); // Remove potential PHP code @@ -70,7 +70,7 @@ if (!function_exists('apus_sanitize_css')) { } } -if (!function_exists('apus_sanitize_js')) { +if (!function_exists('roi_sanitize_js')) { /** * Sanitiza JavaScript * @@ -80,7 +80,7 @@ if (!function_exists('apus_sanitize_js')) { * @return string JavaScript sanitizado * @since 1.0.0 */ - function apus_sanitize_js($js) { + function roi_sanitize_js($js) { // Remove #is', '$2', $js); // Remove potential PHP code @@ -89,7 +89,7 @@ if (!function_exists('apus_sanitize_js')) { } } -if (!function_exists('apus_sanitize_integer')) { +if (!function_exists('roi_sanitize_integer')) { /** * Sanitiza valores enteros * @@ -99,12 +99,12 @@ if (!function_exists('apus_sanitize_integer')) { * @return int Valor sanitizado como entero * @since 1.0.0 */ - function apus_sanitize_integer($input) { + function roi_sanitize_integer($input) { return absint($input); } } -if (!function_exists('apus_sanitize_text')) { +if (!function_exists('roi_sanitize_text')) { /** * Sanitiza campos de texto * @@ -114,12 +114,12 @@ if (!function_exists('apus_sanitize_text')) { * @return string Texto sanitizado * @since 1.0.0 */ - function apus_sanitize_text($input) { + function roi_sanitize_text($input) { return sanitize_text_field($input); } } -if (!function_exists('apus_sanitize_url')) { +if (!function_exists('roi_sanitize_url')) { /** * Sanitiza URLs * @@ -129,12 +129,12 @@ if (!function_exists('apus_sanitize_url')) { * @return string URL sanitizada * @since 1.0.0 */ - function apus_sanitize_url($input) { + function roi_sanitize_url($input) { return esc_url_raw($input); } } -if (!function_exists('apus_sanitize_html')) { +if (!function_exists('roi_sanitize_html')) { /** * Sanitiza contenido HTML * @@ -144,7 +144,7 @@ if (!function_exists('apus_sanitize_html')) { * @return string HTML sanitizado * @since 1.0.0 */ - function apus_sanitize_html($input) { + function roi_sanitize_html($input) { return wp_kses_post($input); } } diff --git a/inc/search-disable.php b/inc/search-disable.php index 31fe704f..f7565a35 100644 --- a/inc/search-disable.php +++ b/inc/search-disable.php @@ -9,7 +9,7 @@ * - Rutas de búsqueda (ej. /search/ o /?s=query desde raíz) → 404 * - URLs válidas con parámetro ?s= → entregar página normal, ignorar parámetro * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 * @link https://github.com/prime-leads-app/analisisdepreciosunitarios.com/issues/3 */ @@ -26,10 +26,10 @@ if (!defined('ABSPATH')) { * * @since 1.0.0 */ -function apus_disable_search_widget() { +function roi_disable_search_widget() { unregister_widget('WP_Widget_Search'); } -add_action('widgets_init', 'apus_disable_search_widget'); +add_action('widgets_init', 'roi_disable_search_widget'); /** * Bloquear queries de búsqueda @@ -40,7 +40,7 @@ add_action('widgets_init', 'apus_disable_search_widget'); * @since 1.0.0 * @param WP_Query $query La instancia de WP_Query. */ -function apus_disable_search_queries($query) { +function roi_disable_search_queries($query) { // Solo procesar en el frontend y en la query principal if (is_admin() || !$query->is_main_query()) { return; @@ -66,7 +66,7 @@ function apus_disable_search_queries($query) { } } } -add_action('pre_get_posts', 'apus_disable_search_queries', 10); +add_action('pre_get_posts', 'roi_disable_search_queries', 10); /** * Remover enlaces de búsqueda del frontend @@ -76,10 +76,10 @@ add_action('pre_get_posts', 'apus_disable_search_queries', 10); * @since 1.0.0 * @return string Cadena vacía. */ -function apus_disable_search_form() { +function roi_disable_search_form() { return ''; } -add_filter('get_search_form', 'apus_disable_search_form'); +add_filter('get_search_form', 'roi_disable_search_form'); /** * Prevenir indexación de páginas de búsqueda @@ -88,12 +88,12 @@ add_filter('get_search_form', 'apus_disable_search_form'); * * @since 1.0.0 */ -function apus_noindex_search() { +function roi_noindex_search() { if (is_search()) { echo '' . "\n"; } } -add_action('wp_head', 'apus_noindex_search', 1); +add_action('wp_head', 'roi_noindex_search', 1); /** * Remover rewrite rules de búsqueda @@ -104,7 +104,7 @@ add_action('wp_head', 'apus_noindex_search', 1); * @param array $rules Reglas de reescritura de WordPress. * @return array Reglas modificadas sin búsqueda. */ -function apus_remove_search_rewrite_rules($rules) { +function roi_remove_search_rewrite_rules($rules) { foreach ($rules as $rule => $rewrite) { if (preg_match('/search/', $rule)) { unset($rules[$rule]); @@ -112,4 +112,4 @@ function apus_remove_search_rewrite_rules($rules) { } return $rules; } -add_filter('rewrite_rules_array', 'apus_remove_search_rewrite_rules'); +add_filter('rewrite_rules_array', 'roi_remove_search_rewrite_rules'); diff --git a/inc/seo.php b/inc/seo.php index 3052eef0..9d3e4f94 100644 --- a/inc/seo.php +++ b/inc/seo.php @@ -5,7 +5,7 @@ * This file contains SEO-related theme functions that work * seamlessly with Rank Math SEO plugin without conflicts. * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -22,11 +22,11 @@ if (!defined('ABSPATH')) { * * @since 1.0.0 */ -function apus_remove_generator() { +function roi_remove_generator() { return ''; } remove_action('wp_head', 'wp_generator'); -add_filter('the_generator', 'apus_remove_generator'); +add_filter('the_generator', 'roi_remove_generator'); /** * Remove RSD (Really Simple Discovery) link @@ -64,13 +64,13 @@ remove_action('wp_head', 'rest_output_link_wp_head'); * * @since 1.0.0 */ -function apus_robots_header() { +function roi_robots_header() { if (is_robots()) { header('Cache-Control: public, max-age=86400'); header('Expires: ' . gmdate('r', time() + 86400)); } } -add_action('pre_handle_robots_txt', 'apus_robots_header'); +add_action('pre_handle_robots_txt', 'roi_robots_header'); /** * Improve comment feed performance @@ -90,7 +90,7 @@ add_action('pre_handle_robots_txt', 'apus_robots_header'); * * @since 1.0.0 */ -function apus_admin_notice_missing_alt() { +function roi_admin_notice_missing_alt() { if (!current_user_can('upload_files')) { return; } @@ -107,9 +107,9 @@ function apus_admin_notice_missing_alt() { * * @since 1.0.0 */ -function apus_seo_head_hooks() { +function roi_seo_head_hooks() { // This ensures proper hook execution order for Rank Math compatibility - do_action('apus_head_close'); + do_action('roi_head_close'); } /** @@ -120,12 +120,12 @@ function apus_seo_head_hooks() { * * @since 1.0.0 */ -function apus_prefetch_external() { +function roi_prefetch_external() { // Google Fonts prefetch echo '' . "\n"; echo '' . "\n"; } -add_action('wp_head', 'apus_prefetch_external', 1); +add_action('wp_head', 'roi_prefetch_external', 1); /** * Open Graph support for Rank Math compatibility @@ -135,7 +135,7 @@ add_action('wp_head', 'apus_prefetch_external', 1); * * @since 1.0.0 */ -function apus_check_rank_math_active() { +function roi_check_rank_math_active() { return defined('RANK_MATH_VERSION'); } @@ -147,9 +147,9 @@ function apus_check_rank_math_active() { * * @since 1.0.0 */ -function apus_schema_fallback() { +function roi_schema_fallback() { // Only output schema if Rank Math is NOT active - if (apus_check_rank_math_active()) { + if (roi_check_rank_math_active()) { return; } @@ -165,12 +165,12 @@ function apus_schema_fallback() { $schema['description'] = get_bloginfo('description'); } - echo "\n" . '' . "\n"; + echo "\n" . '' . "\n"; echo '' . "\n"; } -add_action('wp_head', 'apus_schema_fallback', 20); +add_action('wp_head', 'roi_schema_fallback', 20); /** * Security headers configuration @@ -180,13 +180,13 @@ add_action('wp_head', 'apus_schema_fallback', 20); * * @since 1.0.0 */ -function apus_security_headers() { +function roi_security_headers() { // These headers improve trust signals for search engines header('X-Content-Type-Options: nosniff'); header('X-Frame-Options: SAMEORIGIN'); header('X-XSS-Protection: 1; mode=block'); } -add_action('send_headers', 'apus_security_headers'); +add_action('send_headers', 'roi_security_headers'); /** * Ensure title tag support is active @@ -196,10 +196,10 @@ add_action('send_headers', 'apus_security_headers'); * * @since 1.0.0 */ -function apus_verify_title_tag_support() { +function roi_verify_title_tag_support() { if (!current_theme_supports('title-tag')) { // Log warning if title-tag support is somehow disabled - error_log('Warning: Apus Theme title-tag support not properly initialized'); + error_log('Warning: ROI Theme title-tag support not properly initialized'); } } -add_action('after_setup_theme', 'apus_verify_title_tag_support', 20); +add_action('after_setup_theme', 'roi_verify_title_tag_support', 20); diff --git a/inc/social-share.php b/inc/social-share.php index d5517050..a9b9da38 100644 --- a/inc/social-share.php +++ b/inc/social-share.php @@ -5,7 +5,7 @@ * Funciones para mostrar botones de compartir en redes sociales * en posts individuales. Utiliza URLs nativas sin dependencias de JavaScript. * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -20,7 +20,7 @@ if ( ! defined( 'ABSPATH' ) ) { * @param int $post_id ID del post (opcional, usa el post actual si no se proporciona) * @return string HTML de los botones de compartir */ -function apus_get_social_share_buttons( $post_id = 0 ) { +function roi_get_social_share_buttons( $post_id = 0 ) { // Si no se proporciona post_id, usar el post actual if ( ! $post_id ) { $post_id = get_the_ID(); @@ -45,7 +45,7 @@ function apus_get_social_share_buttons( $post_id = 0 ) { $email_url = 'mailto:?subject=' . $post_title_encoded . '&body=' . $post_url_encoded; // Obtener texto de compartir desde las opciones del tema - $share_text = apus_get_option( 'apus_share_text', __( 'Compartir:', 'apus-theme' ) ); + $share_text = roi_get_option( 'roi_share_text', __( 'Compartir:', 'roi-theme' ) ); // Construir el HTML ob_start(); @@ -57,7 +57,7 @@ function apus_get_social_share_buttons( $post_id = 0 ) { @@ -66,7 +66,7 @@ function apus_get_social_share_buttons( $post_id = 0 ) { @@ -75,7 +75,7 @@ function apus_get_social_share_buttons( $post_id = 0 ) { @@ -84,7 +84,7 @@ function apus_get_social_share_buttons( $post_id = 0 ) { @@ -93,7 +93,7 @@ function apus_get_social_share_buttons( $post_id = 0 ) { + aria-label="">
    @@ -110,18 +110,18 @@ function apus_get_social_share_buttons( $post_id = 0 ) { * * @param int $post_id ID del post (opcional) */ -function apus_display_social_share( $post_id = 0 ) { +function roi_display_social_share( $post_id = 0 ) { // Solo mostrar en posts individuales if ( ! is_single() ) { return; } // Verificar si los botones de compartir están habilitados - $enable_share = apus_get_option( 'apus_enable_share_buttons', '1' ); + $enable_share = roi_get_option( 'roi_enable_share_buttons', '1' ); if ( $enable_share !== '1' ) { return; } // Mostrar los botones - echo apus_get_social_share_buttons( $post_id ); + echo roi_get_social_share_buttons( $post_id ); } diff --git a/inc/template-functions.php b/inc/template-functions.php index 7c83f1df..e9d4b16d 100644 --- a/inc/template-functions.php +++ b/inc/template-functions.php @@ -4,7 +4,7 @@ * * Helper functions for theme templates. * - * @package Apus_Theme + * @package ROI_Theme * @since 1.0.0 */ @@ -18,7 +18,7 @@ if ( ! defined( 'ABSPATH' ) ) { * * @since 1.0.0 */ -function apus_posted_on() { +function roi_posted_on() { $time_string = ''; if ( get_the_time( 'U' ) !== get_the_modified_time( 'U' ) ) { @@ -35,7 +35,7 @@ function apus_posted_on() { $posted_on = sprintf( /* translators: %s: post date. */ - esc_html_x( 'Publicado el %s', 'post date', 'apus' ), + esc_html_x( 'Publicado el %s', 'post date', 'roi' ), '' . $time_string . '' ); @@ -47,10 +47,10 @@ function apus_posted_on() { * * @since 1.0.0 */ -function apus_posted_by() { +function roi_posted_by() { $byline = sprintf( /* translators: %s: post author. */ - esc_html_x( 'por %s', 'post author', 'apus' ), + esc_html_x( 'por %s', 'post author', 'roi' ), '' . esc_html( get_the_author() ) . '' ); @@ -62,21 +62,21 @@ function apus_posted_by() { * * @since 1.0.0 */ -function apus_entry_footer() { +function roi_entry_footer() { // Hide category and tag text for pages. if ( 'post' === get_post_type() ) { /* translators: used between list items, there is a space after the comma */ - $categories_list = get_the_category_list( esc_html__( ', ', 'apus' ) ); + $categories_list = get_the_category_list( esc_html__( ', ', 'roi' ) ); if ( $categories_list ) { /* translators: 1: list of categories. */ - printf( '' . esc_html__( 'Categorías: %1$s', 'apus' ) . '', $categories_list ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + printf( '' . esc_html__( 'Categorías: %1$s', 'roi' ) . '', $categories_list ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /* translators: used between list items, there is a space after the comma */ - $tags_list = get_the_tag_list( '', esc_html_x( ', ', 'list item separator', 'apus' ) ); + $tags_list = get_the_tag_list( '', esc_html_x( ', ', 'list item separator', 'roi' ) ); if ( $tags_list ) { /* translators: 1: list of tags. */ - printf( '' . esc_html__( 'Etiquetas: %1$s', 'apus' ) . '', $tags_list ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + printf( '' . esc_html__( 'Etiquetas: %1$s', 'roi' ) . '', $tags_list ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } @@ -86,7 +86,7 @@ function apus_entry_footer() { sprintf( wp_kses( /* translators: %s: post title */ - __( 'Comentar en %s', 'apus' ), + __( 'Comentar en %s', 'roi' ), array( 'span' => array( 'class' => array(), @@ -103,7 +103,7 @@ function apus_entry_footer() { sprintf( wp_kses( /* translators: %s: Name of current post. Only visible to screen readers */ - __( 'Editar %s', 'apus' ), + __( 'Editar %s', 'roi' ), array( 'span' => array( 'class' => array(), @@ -124,14 +124,14 @@ function apus_entry_footer() { * @param int $length Default excerpt length. * @return int Modified excerpt length. */ -function apus_excerpt_length( $length ) { +function roi_excerpt_length( $length ) { if ( is_admin() ) { return $length; } return 40; // Change this to desired excerpt length. } -add_filter( 'excerpt_length', 'apus_excerpt_length', 999 ); +add_filter( 'excerpt_length', 'roi_excerpt_length', 999 ); /** * Custom excerpt more string @@ -140,14 +140,14 @@ add_filter( 'excerpt_length', 'apus_excerpt_length', 999 ); * @param string $more Default more string. * @return string Modified more string. */ -function apus_excerpt_more( $more ) { +function roi_excerpt_more( $more ) { if ( is_admin() ) { return $more; } return '…'; } -add_filter( 'excerpt_more', 'apus_excerpt_more' ); +add_filter( 'excerpt_more', 'roi_excerpt_more' ); /** * Get custom excerpt by character count @@ -157,7 +157,7 @@ add_filter( 'excerpt_more', 'apus_excerpt_more' ); * @param string $more More string. * @return string Custom excerpt. */ -function apus_get_excerpt( $charlength = 200, $more = '...' ) { +function roi_get_excerpt( $charlength = 200, $more = '...' ) { $excerpt = get_the_excerpt(); $charlength++; @@ -185,7 +185,7 @@ function apus_get_excerpt( $charlength = 200, $more = '...' ) { * @param string $size Image size. * @return string|false Thumbnail URL or false if not found. */ -function apus_get_post_thumbnail_url( $size = 'full' ) { +function roi_get_post_thumbnail_url( $size = 'full' ) { if ( has_post_thumbnail() ) { $thumb_id = get_post_thumbnail_id(); $thumb = wp_get_attachment_image_src( $thumb_id, $size ); @@ -204,14 +204,14 @@ function apus_get_post_thumbnail_url( $size = 'full' ) { * @since 1.0.0 * @param array $args Breadcrumb arguments. */ -function apus_breadcrumbs( $args = array() ) { +function roi_breadcrumbs( $args = array() ) { // Default arguments. $defaults = array( 'separator' => '/', - 'home_label' => esc_html__( 'Inicio', 'apus' ), + 'home_label' => esc_html__( 'Inicio', 'roi' ), 'show_home' => true, 'show_current' => true, - 'before' => '