- add ROI_DEBUG constant (default false) to control debug output
- create roi_debug_log() function for conditional logging
- replace all error_log DEBUG calls with roi_debug_log
- keep ERROR logs always active for exception tracking
- to enable debug, add define('ROI_DEBUG', true) in wp-config.php
this prevents production logs from growing to gb sizes
(previous error.log was 4.8gb from constant debug output)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
606 lines
23 KiB
PHP
606 lines
23 KiB
PHP
<?php
|
|
|
|
// =============================================================================
|
|
// ROI THEME DEBUG MODE
|
|
// =============================================================================
|
|
// Para activar el modo debug, agregar en wp-config.php:
|
|
// define('ROI_DEBUG', true);
|
|
//
|
|
// IMPORTANTE: Mantener desactivado en producción para evitar logs de GB.
|
|
// =============================================================================
|
|
if (!defined('ROI_DEBUG')) {
|
|
define('ROI_DEBUG', false);
|
|
}
|
|
|
|
/**
|
|
* Log de debug condicional para ROI Theme.
|
|
* Solo escribe al log si ROI_DEBUG está activado.
|
|
*/
|
|
function roi_debug_log(string $message): void {
|
|
if (ROI_DEBUG) {
|
|
error_log($message);
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// AUTOLOADER PARA COMPONENTES
|
|
// =============================================================================
|
|
|
|
spl_autoload_register(function ($class) {
|
|
// Mapeo de namespaces a directorios
|
|
$prefixes = [
|
|
'ROITheme\\Shared\\' => get_template_directory() . '/Shared/',
|
|
'ROITheme\\Public\\' => get_template_directory() . '/Public/',
|
|
'ROITheme\\Admin\\' => get_template_directory() . '/Admin/',
|
|
];
|
|
|
|
foreach ($prefixes as $prefix => $base_dir) {
|
|
$len = strlen($prefix);
|
|
if (strncmp($prefix, $class, $len) === 0) {
|
|
$relative_class = substr($class, $len);
|
|
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
|
|
|
|
if (file_exists($file)) {
|
|
require $file;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// =============================================================================
|
|
// FONT PRELOAD - Previene CLS por font swap
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Precarga fuentes críticas para prevenir CLS por font swap
|
|
*
|
|
* Las fuentes Poppins se precargan con alta prioridad para que estén
|
|
* disponibles cuando el CSS las necesite, evitando el "flash" de
|
|
* fuente de respaldo que causa layout shift.
|
|
*/
|
|
add_action('wp_head', function() {
|
|
$theme_url = get_template_directory_uri();
|
|
|
|
// Fuentes críticas: regular y 600 (usadas en títulos y body)
|
|
$critical_fonts = [
|
|
'poppins-v24-latin-regular.woff2',
|
|
'poppins-v24-latin-600.woff2',
|
|
];
|
|
|
|
foreach ($critical_fonts as $font) {
|
|
printf(
|
|
'<link rel="preload" href="%s/Assets/Fonts/%s" as="font" type="font/woff2" crossorigin>%s',
|
|
esc_url($theme_url),
|
|
esc_attr($font),
|
|
"\n"
|
|
);
|
|
}
|
|
}, 1); // Priority 1 = muy temprano en wp_head
|
|
|
|
// =============================================================================
|
|
// HELPER FUNCTION: roi_get_component_setting() - GENÉRICA
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Obtiene un valor de configuración de cualquier componente desde la BD
|
|
*
|
|
* Reemplaza a roi_get_option() legacy - lee de wp_roi_theme_component_settings
|
|
*
|
|
* @param string $component Nombre del componente (ej: 'featured-image', 'navbar')
|
|
* @param string $group Nombre del grupo (ej: 'visibility', 'content')
|
|
* @param string $attribute Nombre del atributo (ej: 'is_enabled', 'show_on_pages')
|
|
* @param mixed $default Valor por defecto si no existe
|
|
* @return mixed Valor del atributo
|
|
*/
|
|
function roi_get_component_setting(string $component, string $group, string $attribute, $default = null) {
|
|
global $wpdb;
|
|
|
|
$table = $wpdb->prefix . 'roi_theme_component_settings';
|
|
$value = $wpdb->get_var($wpdb->prepare(
|
|
"SELECT attribute_value FROM {$table}
|
|
WHERE component_name = %s
|
|
AND group_name = %s
|
|
AND attribute_name = %s",
|
|
$component,
|
|
$group,
|
|
$attribute
|
|
));
|
|
|
|
if ($value === null) {
|
|
return $default;
|
|
}
|
|
|
|
// Convertir booleanos
|
|
if ($value === '1') return true;
|
|
if ($value === '0') return false;
|
|
|
|
// Intentar decodificar JSON
|
|
$decoded = json_decode($value, true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
|
return $decoded;
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
// =============================================================================
|
|
// HELPER FUNCTION: roi_get_navbar_setting()
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Obtiene un valor de configuración del navbar desde la BD
|
|
*
|
|
* @param string $group Nombre del grupo (ej: 'media', 'visibility')
|
|
* @param string $attribute Nombre del atributo (ej: 'show_brand', 'logo_url')
|
|
* @param mixed $default Valor por defecto si no existe
|
|
* @return mixed Valor del atributo
|
|
*/
|
|
function roi_get_navbar_setting(string $group, string $attribute, $default = null) {
|
|
global $wpdb;
|
|
|
|
$table = $wpdb->prefix . 'roi_theme_component_settings';
|
|
$value = $wpdb->get_var($wpdb->prepare(
|
|
"SELECT attribute_value FROM {$table}
|
|
WHERE component_name = 'navbar'
|
|
AND group_name = %s
|
|
AND attribute_name = %s",
|
|
$group,
|
|
$attribute
|
|
));
|
|
|
|
if ($value === null) {
|
|
return $default;
|
|
}
|
|
|
|
// Convertir booleanos
|
|
if ($value === '1') return true;
|
|
if ($value === '0') return false;
|
|
|
|
// Intentar decodificar JSON
|
|
$decoded = json_decode($value, true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
|
return $decoded;
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
// =============================================================================
|
|
// CRITICAL CSS SERVICE SINGLETON
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Obtiene la instancia singleton del CriticalCSSService
|
|
*
|
|
* Este servicio consulta la BD para componentes con is_critical=true
|
|
* y genera su CSS en wp_head ANTES de que los componentes rendericen.
|
|
*
|
|
* @return \ROITheme\Shared\Infrastructure\Services\CriticalCSSService
|
|
*/
|
|
function roi_get_critical_css_service(): \ROITheme\Shared\Infrastructure\Services\CriticalCSSService {
|
|
global $wpdb;
|
|
static $cssGenerator = null;
|
|
|
|
if ($cssGenerator === null) {
|
|
$cssGenerator = new \ROITheme\Shared\Infrastructure\Services\CSSGeneratorService();
|
|
}
|
|
|
|
return \ROITheme\Shared\Infrastructure\Services\CriticalCSSService::getInstance($wpdb, $cssGenerator);
|
|
}
|
|
|
|
// =============================================================================
|
|
// HELPER FUNCTION: roi_render_component()
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Renderiza un componente por su nombre
|
|
*
|
|
* @param string $componentName Nombre del componente
|
|
* @return string HTML del componente renderizado
|
|
*/
|
|
function roi_render_component(string $componentName): string {
|
|
global $wpdb;
|
|
|
|
// DEBUG: Trace component rendering
|
|
roi_debug_log("ROI Theme DEBUG: roi_render_component called with: {$componentName}");
|
|
|
|
try {
|
|
// Obtener datos del componente desde BD normalizada
|
|
$table = $wpdb->prefix . 'roi_theme_component_settings';
|
|
$rows = $wpdb->get_results($wpdb->prepare(
|
|
"SELECT group_name, attribute_name, attribute_value
|
|
FROM {$table}
|
|
WHERE component_name = %s
|
|
ORDER BY group_name, attribute_name",
|
|
$componentName
|
|
));
|
|
|
|
if (empty($rows)) {
|
|
return '';
|
|
}
|
|
|
|
// Reconstruir estructura de datos agrupada
|
|
$data = [];
|
|
foreach ($rows as $row) {
|
|
if (!isset($data[$row->group_name])) {
|
|
$data[$row->group_name] = [];
|
|
}
|
|
// Decodificar valor
|
|
$value = $row->attribute_value;
|
|
|
|
// Solo convertir a booleano campos que realmente son booleanos
|
|
// Los grupos 'visibility', '_page_visibility' y campos que empiezan con 'show_', 'is_', 'enable'
|
|
$isBooleanField = (
|
|
$row->group_name === 'visibility' ||
|
|
$row->group_name === '_page_visibility' ||
|
|
str_starts_with($row->attribute_name, 'show_') ||
|
|
str_starts_with($row->attribute_name, 'is_') ||
|
|
str_starts_with($row->attribute_name, 'enable')
|
|
);
|
|
|
|
if ($isBooleanField && ($value === '1' || $value === '0')) {
|
|
$value = ($value === '1');
|
|
} else {
|
|
// Intentar decodificar JSON
|
|
$decoded = json_decode($value, true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
|
$value = $decoded;
|
|
}
|
|
}
|
|
|
|
$data[$row->group_name][$row->attribute_name] = $value;
|
|
}
|
|
|
|
// Crear Value Objects requeridos
|
|
$name = new \ROITheme\Shared\Domain\ValueObjects\ComponentName($componentName);
|
|
$configuration = new \ROITheme\Shared\Domain\ValueObjects\ComponentConfiguration($data);
|
|
|
|
// =====================================================================
|
|
// VALIDACIÓN DE VISIBILIDAD POR DISPOSITIVO (Previene CLS)
|
|
// =====================================================================
|
|
// Si el componente no debe mostrarse en el dispositivo actual,
|
|
// NO renderizar nada. Esto evita CLS causado por elementos que
|
|
// se renderizan y luego se ocultan con CSS.
|
|
// =====================================================================
|
|
|
|
// Leer configuración de visibilidad desde BD
|
|
$isEnabled = ($data['visibility']['is_enabled'] ?? true) === true;
|
|
$showOnDesktop = ($data['visibility']['show_on_desktop'] ?? true) === true;
|
|
$showOnMobile = ($data['visibility']['show_on_mobile'] ?? true) === true;
|
|
|
|
// Si no está habilitado, no renderizar
|
|
if (!$isEnabled) {
|
|
return '';
|
|
}
|
|
|
|
// Detectar dispositivo actual y validar visibilidad
|
|
// wp_is_mobile() detecta móviles y tablets via User-Agent
|
|
$isMobileDevice = wp_is_mobile();
|
|
|
|
if ($isMobileDevice && !$showOnMobile) {
|
|
// Dispositivo móvil pero show_on_mobile = false → NO renderizar
|
|
return '';
|
|
}
|
|
|
|
if (!$isMobileDevice && !$showOnDesktop) {
|
|
// Dispositivo desktop pero show_on_desktop = false → NO renderizar
|
|
return '';
|
|
}
|
|
|
|
// Crear ComponentVisibility con datos reales de BD
|
|
$visibility = new \ROITheme\Shared\Domain\ValueObjects\ComponentVisibility(
|
|
enabled: $isEnabled,
|
|
visibleDesktop: $showOnDesktop,
|
|
visibleTablet: $showOnMobile, // tablet tratado como mobile
|
|
visibleMobile: $showOnMobile
|
|
);
|
|
|
|
// Crear instancia del componente
|
|
$component = new \ROITheme\Shared\Domain\Entities\Component(
|
|
$name,
|
|
$configuration,
|
|
$visibility
|
|
);
|
|
|
|
// Obtener renderer específico para el componente
|
|
$renderer = null;
|
|
|
|
// Crear instancia del CSSGeneratorService (reutilizable para todos los renderers)
|
|
$cssGenerator = new \ROITheme\Shared\Infrastructure\Services\CSSGeneratorService();
|
|
|
|
switch ($componentName) {
|
|
// Componentes con soporte de CSS Crítico (above-the-fold)
|
|
// Nota: Si is_critical=true, el CSS ya fue inyectado en <head> por CriticalCSSService
|
|
case 'top-notification-bar':
|
|
$renderer = new \ROITheme\Public\TopNotificationBar\Infrastructure\Ui\TopNotificationBarRenderer($cssGenerator);
|
|
break;
|
|
case 'navbar':
|
|
$renderer = new \ROITheme\Public\Navbar\Infrastructure\Ui\NavbarRenderer($cssGenerator);
|
|
break;
|
|
case 'hero':
|
|
roi_debug_log("ROI Theme DEBUG: Creating HeroRenderer");
|
|
$renderer = new \ROITheme\Public\Hero\Infrastructure\Ui\HeroRenderer($cssGenerator);
|
|
roi_debug_log("ROI Theme DEBUG: HeroRenderer created successfully");
|
|
break;
|
|
|
|
// Componentes sin soporte de CSS Crítico (below-the-fold)
|
|
case 'cta-lets-talk':
|
|
$renderer = new \ROITheme\Public\CtaLetsTalk\Infrastructure\Ui\CtaLetsTalkRenderer($cssGenerator);
|
|
break;
|
|
case 'featured-image':
|
|
$renderer = new \ROITheme\Public\FeaturedImage\Infrastructure\Ui\FeaturedImageRenderer($cssGenerator);
|
|
break;
|
|
case 'table-of-contents':
|
|
$renderer = new \ROITheme\Public\TableOfContents\Infrastructure\Ui\TableOfContentsRenderer($cssGenerator);
|
|
break;
|
|
case 'cta-box-sidebar':
|
|
$renderer = new \ROITheme\Public\CtaBoxSidebar\Infrastructure\Ui\CtaBoxSidebarRenderer($cssGenerator);
|
|
break;
|
|
case 'social-share':
|
|
$renderer = new \ROITheme\Public\SocialShare\Infrastructure\Ui\SocialShareRenderer($cssGenerator);
|
|
break;
|
|
case 'cta-post':
|
|
$renderer = new \ROITheme\Public\CtaPost\Infrastructure\Ui\CtaPostRenderer($cssGenerator);
|
|
break;
|
|
case 'related-post':
|
|
$renderer = new \ROITheme\Public\RelatedPost\Infrastructure\Ui\RelatedPostRenderer($cssGenerator);
|
|
break;
|
|
case 'contact-form':
|
|
$renderer = new \ROITheme\Public\ContactForm\Infrastructure\Ui\ContactFormRenderer($cssGenerator);
|
|
break;
|
|
case 'footer':
|
|
$renderer = new \ROITheme\Public\Footer\Infrastructure\Ui\FooterRenderer($cssGenerator);
|
|
break;
|
|
case 'archive-header':
|
|
$renderer = new \ROITheme\Public\ArchiveHeader\Infrastructure\Ui\ArchiveHeaderRenderer($cssGenerator);
|
|
break;
|
|
case 'post-grid':
|
|
$renderer = new \ROITheme\Public\PostGrid\Infrastructure\Ui\PostGridRenderer($cssGenerator);
|
|
break;
|
|
}
|
|
|
|
if (!$renderer) {
|
|
roi_debug_log("ROI Theme DEBUG: No renderer for {$componentName}");
|
|
return '';
|
|
}
|
|
|
|
roi_debug_log("ROI Theme DEBUG: Calling render() for {$componentName}");
|
|
$output = $renderer->render($component);
|
|
roi_debug_log("ROI Theme DEBUG: render() returned " . strlen($output) . " chars for {$componentName}");
|
|
return $output;
|
|
|
|
} catch (\Exception $e) {
|
|
// Always log errors for debugging
|
|
error_log('ROI Theme ERROR: Exception rendering component ' . $componentName . ': ' . $e->getMessage());
|
|
error_log('ROI Theme ERROR: Stack trace: ' . $e->getTraceAsString());
|
|
return '';
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// REGISTRO DE CRITICAL CSS HOOKS
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Registra hooks para inyectar CSS crítico en <head>
|
|
*
|
|
* FLUJO:
|
|
* 1. wp_head (priority 0) → CriticalBootstrapService::render()
|
|
* - Inyecta critical-bootstrap.css inline (grid, navbar, utilities)
|
|
* - Permite diferir bootstrap-subset.min.css
|
|
*
|
|
* 2. wp_head (priority 1) → CriticalCSSService::render()
|
|
* - Consulta BD por componentes con is_critical=true
|
|
* - Genera CSS usando los métodos públicos generateCSS() de los Renderers
|
|
* - Output: <style id="roi-critical-css">...</style>
|
|
*
|
|
* IMPORTANTE: CriticalBootstrapService HABILITADO para mejorar LCP.
|
|
* critical-bootstrap.css incluye grid system para evitar CLS.
|
|
*/
|
|
add_action('after_setup_theme', function() {
|
|
// 1. Critical Bootstrap CSS (priority 0) - inline bootstrap crítico
|
|
$criticalBootstrapService = \ROITheme\Shared\Infrastructure\Services\CriticalBootstrapService::getInstance();
|
|
add_action('wp_head', [$criticalBootstrapService, 'render'], 0);
|
|
|
|
// 2. Critical Component CSS (priority 1) - CSS de componentes críticos
|
|
$criticalCSSService = roi_get_critical_css_service();
|
|
$hooksRegistrar = new \ROITheme\Shared\Infrastructure\Wordpress\CriticalCSSHooksRegistrar($criticalCSSService);
|
|
$hooksRegistrar->register();
|
|
|
|
// 3. Body Class Hooks (Plan 99.15) - CSS failsafe para componentes ocultos
|
|
$container = \ROITheme\Shared\Infrastructure\Di\DIContainer::getInstance();
|
|
$bodyClassHooksRegistrar = $container->getBodyClassHooksRegistrar();
|
|
$bodyClassHooksRegistrar->register();
|
|
});
|
|
|
|
// =============================================================================
|
|
// NOTA: Los estilos de TOC y CTA Box Sidebar se generan dinámicamente
|
|
// desde la base de datos a través de sus respectivos Renderers.
|
|
// NO hardcodear CSS aquí - viola la arquitectura Clean Architecture.
|
|
// =============================================================================
|
|
|
|
// =============================================================================
|
|
// HELPER FUNCTION: roi_should_render_wrapper() - Plan 99.15
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Verifica si el wrapper de un componente debe renderizarse
|
|
*
|
|
* Evalúa:
|
|
* - is_enabled
|
|
* - show_on_mobile / show_on_desktop
|
|
* - Exclusiones (categoría, post ID, URL pattern, page visibility)
|
|
*
|
|
* USO EN TEMPLATES:
|
|
* ```php
|
|
* if (roi_should_render_wrapper('navbar')) {
|
|
* echo '<nav class="navbar">';
|
|
* echo roi_render_component('navbar');
|
|
* echo '</nav>';
|
|
* }
|
|
* ```
|
|
*
|
|
* @param string $componentName Nombre del componente (kebab-case)
|
|
* @return bool True si el wrapper debe renderizarse
|
|
* @see Plan 99.15 - Fix Empty Layout Wrappers
|
|
*/
|
|
function roi_should_render_wrapper(string $componentName): bool {
|
|
return \ROITheme\Shared\Infrastructure\Services\WrapperVisibilityService::shouldRenderWrapper($componentName);
|
|
}
|
|
|
|
/**
|
|
* Verifica si AL MENOS UN componente de una lista debe renderizarse
|
|
*
|
|
* Útil para determinar si mostrar columna sidebar
|
|
*
|
|
* @param array<string> $componentNames Lista de nombres de componentes
|
|
* @return bool True si al menos uno debe mostrarse
|
|
*/
|
|
function roi_should_render_any_wrapper(array $componentNames): bool {
|
|
return \ROITheme\Shared\Infrastructure\Services\WrapperVisibilityService::shouldRenderAnyWrapper($componentNames);
|
|
}
|
|
|
|
// =============================================================================
|
|
// HELPER FUNCTION: roi_get_adsense_search_config()
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Obtiene la configuracion de AdSense para resultados de busqueda
|
|
*
|
|
* Esta funcion es la API publica que el plugin roi-apu-search consume.
|
|
* El plugin NO debe acceder directamente a la tabla del tema.
|
|
*
|
|
* OPTIMIZACION: Una sola query carga todos los settings del componente.
|
|
*
|
|
* @return array Configuracion para JavaScript
|
|
*/
|
|
function roi_get_adsense_search_config(): array {
|
|
global $wpdb;
|
|
|
|
// =========================================================================
|
|
// CARGAR TODOS LOS SETTINGS EN UNA SOLA QUERY
|
|
// =========================================================================
|
|
$table = $wpdb->prefix . 'roi_theme_component_settings';
|
|
$rows = $wpdb->get_results($wpdb->prepare(
|
|
"SELECT group_name, attribute_name, attribute_value
|
|
FROM {$table}
|
|
WHERE component_name = %s",
|
|
'adsense-placement'
|
|
));
|
|
|
|
if (empty($rows)) {
|
|
return ['enabled' => false];
|
|
}
|
|
|
|
// Organizar en array asociativo por grupo/atributo
|
|
$settings = [];
|
|
foreach ($rows as $row) {
|
|
if (!isset($settings[$row->group_name])) {
|
|
$settings[$row->group_name] = [];
|
|
}
|
|
// Decodificar valor
|
|
$value = $row->attribute_value;
|
|
if ($value === '1') $value = true;
|
|
elseif ($value === '0') $value = false;
|
|
else {
|
|
$decoded = json_decode($value, true);
|
|
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
|
|
$value = $decoded;
|
|
}
|
|
}
|
|
$settings[$row->group_name][$row->attribute_name] = $value;
|
|
}
|
|
|
|
// Helper para obtener valor con default
|
|
$get = function(string $group, string $attr, $default = null) use ($settings) {
|
|
return $settings[$group][$attr] ?? $default;
|
|
};
|
|
|
|
// =========================================================================
|
|
// VALIDAR CONDICIONES GLOBALES
|
|
// =========================================================================
|
|
|
|
// AdSense global deshabilitado
|
|
if ($get('visibility', 'is_enabled', false) !== true) {
|
|
return ['enabled' => false];
|
|
}
|
|
|
|
// Ads en busqueda deshabilitados
|
|
if ($get('search_results', 'search_ads_enabled', false) !== true) {
|
|
return ['enabled' => false];
|
|
}
|
|
|
|
// Publisher ID vacio
|
|
$publisherId = $get('content', 'publisher_id', '');
|
|
if (empty($publisherId)) {
|
|
return ['enabled' => false];
|
|
}
|
|
|
|
// =========================================================================
|
|
// VALIDAR EXCLUSIONES (igual que el resto del sistema)
|
|
// =========================================================================
|
|
|
|
// Ocultar para usuarios logueados
|
|
if ($get('visibility', 'hide_for_logged_in', false) === true && is_user_logged_in()) {
|
|
return ['enabled' => false];
|
|
}
|
|
|
|
// Visibilidad por dispositivo
|
|
$isMobile = wp_is_mobile();
|
|
if ($isMobile && $get('visibility', 'show_on_mobile', true) !== true) {
|
|
return ['enabled' => false];
|
|
}
|
|
if (!$isMobile && $get('visibility', 'show_on_desktop', true) !== true) {
|
|
return ['enabled' => false];
|
|
}
|
|
|
|
// =========================================================================
|
|
// CONSTRUIR CONFIGURACION
|
|
// =========================================================================
|
|
return [
|
|
'enabled' => true,
|
|
'publisherId' => $publisherId,
|
|
'slots' => [
|
|
'auto' => $get('content', 'slot_auto', ''),
|
|
'inArticle' => $get('content', 'slot_inarticle', ''),
|
|
'autorelaxed' => $get('content', 'slot_autorelaxed', ''),
|
|
'display' => $get('content', 'slot_display', ''),
|
|
],
|
|
'topAd' => [
|
|
'enabled' => $get('search_results', 'search_top_ad_enabled', true) === true,
|
|
'format' => $get('search_results', 'search_top_ad_format', 'auto'),
|
|
],
|
|
'betweenAds' => [
|
|
'enabled' => $get('search_results', 'search_between_enabled', true) === true,
|
|
'max' => min(3, max(1, (int) $get('search_results', 'search_between_max', '1'))),
|
|
'format' => $get('search_results', 'search_between_format', 'in-article'),
|
|
'position' => $get('search_results', 'search_between_position', 'random'),
|
|
'every' => (int) $get('search_results', 'search_between_every', '5'),
|
|
],
|
|
'delay' => [
|
|
'enabled' => $get('forms', 'delay_enabled', true) === true,
|
|
'timeout' => (int) $get('forms', 'delay_timeout', '5000'),
|
|
],
|
|
];
|
|
}
|
|
|
|
// =============================================================================
|
|
// POST GRID SHORTCODE [roi_post_grid]
|
|
// =============================================================================
|
|
|
|
/**
|
|
* Registra el shortcode [roi_post_grid] para mostrar grids de posts
|
|
* en cualquier pagina o entrada.
|
|
*
|
|
* USO:
|
|
* [roi_post_grid]
|
|
* [roi_post_grid category="precios-unitarios" posts_per_page="6"]
|
|
* [roi_post_grid id="grid-1" category="cursos" show_pagination="true"]
|
|
*
|
|
* @see Shared/Infrastructure/Wordpress/PostGridShortcodeRegistrar
|
|
*/
|
|
add_action('init', function() {
|
|
\ROITheme\Shared\Infrastructure\Wordpress\PostGridShortcodeRegistrar::register();
|
|
});
|