feat(visibility): sistema de visibilidad por tipo de página

- Añadir PageVisibility use case y repositorio
- Implementar PageTypeDetector para detectar home/single/page/archive
- Actualizar FieldMappers con soporte show_on_[page_type]
- Extender FormBuilders con UI de visibilidad por página
- Refactorizar Renderers para evaluar visibilidad dinámica
- Limpiar schemas removiendo campos de visibilidad legacy
- Añadir MigrationCommand para migrar configuraciones existentes
- Implementar adsense-loader.js para carga lazy de ads
- Actualizar front-page.php con nueva estructura
- Extender DIContainer con nuevos servicios

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
FrankZamora
2025-12-03 09:16:34 -06:00
parent 7fb5eda108
commit 8735962f52
66 changed files with 2614 additions and 573 deletions

View File

@@ -22,6 +22,12 @@ use ROITheme\Shared\Infrastructure\Services\CriticalCSSCollector;
use ROITheme\Shared\Application\UseCases\GetComponentSettings\GetComponentSettingsUseCase;
use ROITheme\Shared\Application\UseCases\SaveComponentSettings\SaveComponentSettingsUseCase;
use ROITheme\Public\AdsensePlacement\Infrastructure\Ui\AdsensePlacementRenderer;
use ROITheme\Shared\Domain\Contracts\PageVisibilityRepositoryInterface;
use ROITheme\Shared\Domain\Contracts\PageTypeDetectorInterface;
use ROITheme\Shared\Infrastructure\Services\WordPressPageTypeDetector;
use ROITheme\Shared\Infrastructure\Persistence\WordPress\WordPressPageVisibilityRepository;
use ROITheme\Shared\Application\UseCases\EvaluatePageVisibility\EvaluatePageVisibilityUseCase;
use ROITheme\Shared\Infrastructure\Services\MigratePageVisibilityService;
/**
* DIContainer - Contenedor de Inyección de Dependencias
@@ -46,10 +52,38 @@ final class DIContainer
{
private array $instances = [];
/**
* Instancia singleton del contenedor
* @var self|null
*/
private static ?self $instance = null;
/**
* Obtiene la instancia singleton del contenedor
*
* NOTA: Se debe haber creado una instancia previamente en functions.php
* El constructor registra automáticamente la instancia.
*
* @return self
* @throws \RuntimeException Si no se ha inicializado el contenedor
*/
public static function getInstance(): self
{
if (self::$instance === null) {
throw new \RuntimeException(
'DIContainer no ha sido inicializado. Asegúrate de que functions.php se haya ejecutado primero.'
);
}
return self::$instance;
}
public function __construct(
private \wpdb $wpdb,
private string $schemasPath
) {}
) {
// Registrar como instancia singleton
self::$instance = $this;
}
/**
* Obtener repositorio de componentes
@@ -272,4 +306,61 @@ final class DIContainer
return $this->instances['criticalCSSCollector'];
}
// ===============================
// Page Visibility System
// ===============================
/**
* Obtiene el repositorio de visibilidad de página
*
* IMPORTANTE: Inyecta $wpdb para consistencia con el resto del código
* (WordPressComponentSettingsRepository también recibe $wpdb por constructor)
*/
public function getPageVisibilityRepository(): PageVisibilityRepositoryInterface
{
if (!isset($this->instances['pageVisibilityRepository'])) {
// Inyectar $wpdb siguiendo el patrón existente
$this->instances['pageVisibilityRepository'] = new WordPressPageVisibilityRepository($this->wpdb);
}
return $this->instances['pageVisibilityRepository'];
}
/**
* Obtiene el detector de tipo de página
*/
public function getPageTypeDetector(): PageTypeDetectorInterface
{
if (!isset($this->instances['pageTypeDetector'])) {
$this->instances['pageTypeDetector'] = new WordPressPageTypeDetector();
}
return $this->instances['pageTypeDetector'];
}
/**
* Obtiene el caso de uso de evaluación de visibilidad
*/
public function getEvaluatePageVisibilityUseCase(): EvaluatePageVisibilityUseCase
{
if (!isset($this->instances['evaluatePageVisibilityUseCase'])) {
$this->instances['evaluatePageVisibilityUseCase'] = new EvaluatePageVisibilityUseCase(
$this->getPageTypeDetector(),
$this->getPageVisibilityRepository()
);
}
return $this->instances['evaluatePageVisibilityUseCase'];
}
/**
* Obtiene el servicio de migración de visibilidad
*/
public function getMigratePageVisibilityService(): MigratePageVisibilityService
{
if (!isset($this->instances['migratePageVisibilityService'])) {
$this->instances['migratePageVisibilityService'] = new MigratePageVisibilityService(
$this->getPageVisibilityRepository()
);
}
return $this->instances['migratePageVisibilityService'];
}
}