## Problema - Componentes deshabilitados/excluidos dejaban wrappers HTML vacíos (navbar 32px, sidebar col-lg-3 294px) - AdSense ignoraba exclusiones por URL pattern en grupo _exclusions ## Solución Plan 99.15 (Clean Architecture) ### Domain Layer - WrapperVisibilityCheckerInterface: contrato para verificar visibilidad ### Application Layer - CheckWrapperVisibilityUseCase: orquesta verificaciones de visibilidad ### Infrastructure Layer - WordPressComponentVisibilityRepository: consulta BD + PageVisibilityHelper - WrapperVisibilityService: facade estático para templates - BodyClassHooksRegistrar: agrega clases CSS failsafe al body ### Templates modificados - header.php: renderizado condicional de <nav> wrapper - page.php/single.php: lógica dinámica col-lg-9/col-lg-12 según sidebar ### CSS Failsafe - css-global-utilities.css: reglas body.roi-hide-* como respaldo ## Fix AdSense (Inc/adsense-placement.php) - Agregado PageVisibilityHelper::shouldShow() a todas las funciones: roi_render_ad_slot, roi_render_rail_ads, roi_enqueue_adsense_script, roi_inject_content_ads, roi_render_anchor_ads, roi_render_vignette_ad, roi_enqueue_anchor_vignette_scripts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
101 lines
2.7 KiB
PHP
101 lines
2.7 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace ROITheme\Shared\Infrastructure\Services;
|
|
|
|
use ROITheme\Shared\Application\UseCases\CheckWrapperVisibilityUseCase;
|
|
use ROITheme\Shared\Infrastructure\Di\DIContainer;
|
|
|
|
/**
|
|
* Servicio facade para verificar visibilidad de wrappers desde templates
|
|
*
|
|
* Responsabilidad: Proveer acceso simplificado (singleton/static) al
|
|
* CheckWrapperVisibilityUseCase para uso en templates PHP.
|
|
*
|
|
* USO EN TEMPLATES:
|
|
* ```php
|
|
* if (WrapperVisibilityService::shouldRenderWrapper('navbar')) {
|
|
* // Renderizar wrapper y componente
|
|
* }
|
|
* ```
|
|
*
|
|
* @package ROITheme\Shared\Infrastructure\Services
|
|
* @see Plan 99.15 - Fix Empty Layout Wrappers
|
|
*/
|
|
final class WrapperVisibilityService
|
|
{
|
|
private static ?CheckWrapperVisibilityUseCase $useCase = null;
|
|
|
|
/**
|
|
* Verifica si el wrapper de un componente debe renderizarse
|
|
*
|
|
* @param string $componentName Nombre del componente (kebab-case)
|
|
* @return bool True si el wrapper debe renderizarse
|
|
*/
|
|
public static function shouldRenderWrapper(string $componentName): bool
|
|
{
|
|
$useCase = self::getUseCase();
|
|
$isMobile = self::detectMobile();
|
|
|
|
return $useCase->execute($componentName, $isMobile);
|
|
}
|
|
|
|
/**
|
|
* Verifica visibilidad para múltiples componentes
|
|
*
|
|
* Útil para determinar si renderizar un contenedor que agrupa varios componentes
|
|
*
|
|
* @param array<string> $componentNames Lista de nombres de componentes
|
|
* @return bool True si AL MENOS UNO de los componentes debe mostrarse
|
|
*/
|
|
public static function shouldRenderAnyWrapper(array $componentNames): bool
|
|
{
|
|
foreach ($componentNames as $componentName) {
|
|
if (self::shouldRenderWrapper($componentName)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Obtiene o crea el UseCase
|
|
*
|
|
* @return CheckWrapperVisibilityUseCase
|
|
*/
|
|
private static function getUseCase(): CheckWrapperVisibilityUseCase
|
|
{
|
|
if (self::$useCase === null) {
|
|
$container = DIContainer::getInstance();
|
|
self::$useCase = $container->getCheckWrapperVisibilityUseCase();
|
|
}
|
|
|
|
return self::$useCase;
|
|
}
|
|
|
|
/**
|
|
* Detecta si el dispositivo actual es móvil
|
|
*
|
|
* Usa wp_is_mobile() de WordPress
|
|
*
|
|
* @return bool
|
|
*/
|
|
private static function detectMobile(): bool
|
|
{
|
|
if (function_exists('wp_is_mobile')) {
|
|
return wp_is_mobile();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Limpia la instancia del UseCase (útil para tests)
|
|
*/
|
|
public static function reset(): void
|
|
{
|
|
self::$useCase = null;
|
|
}
|
|
}
|