From 09d87835b81e1648bc701fb41ba89b4664e46140 Mon Sep 17 00:00:00 2001 From: FrankZamora Date: Wed, 10 Dec 2025 10:58:48 -0600 Subject: [PATCH] chore: add debug comment to diagnose mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .claude/settings.local.json | 9 + .../Services/ContentAdInjector.php | 11 +- .../specs/cache-first-architecture/spec.md | 242 ++++++++++-------- 3 files changed, 157 insertions(+), 105 deletions(-) create mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000..6051fbda --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,9 @@ +{ + "permissions": { + "allow": [ + "Bash(mkdir:*)", + "mcp__serena__activate_project", + "mcp__serena__find_symbol" + ] + } +} diff --git a/Public/AdsensePlacement/Infrastructure/Services/ContentAdInjector.php b/Public/AdsensePlacement/Infrastructure/Services/ContentAdInjector.php index a1746997..6a614e9c 100644 --- a/Public/AdsensePlacement/Infrastructure/Services/ContentAdInjector.php +++ b/Public/AdsensePlacement/Infrastructure/Services/ContentAdInjector.php @@ -52,11 +52,18 @@ final class ContentAdInjector // Determinar modo de operacion $mode = $this->settings['incontent_advanced']['incontent_mode'] ?? 'paragraphs_only'; + // DEBUG TEMPORAL: Insertar comentario HTML para diagnosticar + $debugComment = sprintf( + '', + $mode, + isset($this->settings['incontent_advanced']) ? 'YES' : 'NO' + ); + if ($mode === 'paragraphs_only') { - return $this->injectParagraphsOnly($content); + return $debugComment . $this->injectParagraphsOnly($content); } - return $this->injectAdvanced($content); + return $debugComment . $this->injectAdvanced($content); } /** diff --git a/openspec/specs/cache-first-architecture/spec.md b/openspec/specs/cache-first-architecture/spec.md index 3300f0ee..a7ae20ac 100644 --- a/openspec/specs/cache-first-architecture/spec.md +++ b/openspec/specs/cache-first-architecture/spec.md @@ -1,154 +1,190 @@ -# Especificacion de Arquitectura Cache-First +# Especificacion: Hook de Pre-Evaluacion de Pagina ## Purpose -Define la arquitectura cache-first para ROITheme que permite que plugins de cache (W3TC, Redis, etc.) funcionen correctamente mientras plugins externos pueden evaluar condiciones ANTES de servir paginas. +Define un hook que permite a plugins externos evaluar condiciones ANTES de que WordPress sirva una pagina singular. Este hook es util para plugins de control de acceso, rate limiters, membership, etc. -Esta arquitectura: -- Permite que las paginas se sirvan desde cache siempre que sea posible -- Provee hooks para que plugins externos (rate limiters, access control, etc.) evaluen condiciones -- Desacopla el tema de plugins especificos de restriccion de acceso -- Es portable: cualquier sitio con roi-theme tiene esta capacidad - -## Requirements - -### Requirement: Hook de Pre-Evaluacion de Pagina - -The system MUST provide a hook that fires BEFORE WordPress serves a page, allowing external plugins to evaluate conditions and potentially redirect. - -#### Scenario: Plugin externo necesita evaluar acceso antes de servir pagina -- **GIVEN** un plugin de control de acceso (rate limiter, membership, etc.) -- **WHEN** un visitante solicita una pagina singular (post, page, CPT) -- **THEN** el tema DEBE disparar `do_action('roi_theme_before_page_serve', $post_id)` -- **AND** el hook DEBE ejecutarse en `template_redirect` con priority 0 -- **AND** si el plugin llama `wp_safe_redirect()` y `exit`, la pagina NO se sirve - -#### Scenario: Ningn plugin enganchado al hook -- **GIVEN** ningun plugin esta escuchando `roi_theme_before_page_serve` -- **WHEN** un visitante solicita una pagina -- **THEN** la pagina se sirve normalmente (con cache si disponible) -- **AND** no hay impacto en rendimiento - -#### Scenario: Hook solo dispara en paginas singulares -- **GIVEN** el hook `roi_theme_before_page_serve` -- **WHEN** la solicitud es para archivo, home, search, feed, o admin -- **THEN** el hook NO DEBE dispararse -- **AND** la pagina se sirve sin evaluacion adicional - -#### Scenario: Hook no dispara para usuarios logueados -- **GIVEN** un usuario autenticado (logged in) -- **WHEN** solicita cualquier pagina -- **THEN** el hook NO DEBE dispararse -- **AND** la pagina se sirve directamente sin evaluacion -- **BECAUSE** WordPress no cachea paginas para usuarios logueados (cookies de sesion) +**Alcance del tema:** ROI-Theme SOLO provee el hook. La implementacion de logica de acceso es responsabilidad de cada plugin. --- -### Requirement: Contexto Rico para Plugins Externos +## Requirements -The system MUST provide sufficient context for external plugins to make access decisions. +### Requirement: Hook roi_theme_before_page_serve -#### Scenario: Plugin necesita informacion del post +The system MUST provide a hook that fires before WordPress serves a singular page, allowing external plugins to evaluate conditions and potentially redirect. + +#### Scenario: Plugin externo evalua acceso antes de servir pagina +- **GIVEN** un plugin de control de acceso enganchado a `roi_theme_before_page_serve` +- **WHEN** un visitante anonimo solicita una pagina singular (post, page, CPT) +- **THEN** el tema DEBE disparar `do_action('roi_theme_before_page_serve', $post_id)` +- **AND** el hook DEBE ejecutarse en `template_redirect` con priority 0 +- **AND** si el plugin llama `wp_safe_redirect()` + `exit`, la pagina NO se sirve + +#### Scenario: Ningun plugin enganchado +- **GIVEN** ningun plugin esta escuchando `roi_theme_before_page_serve` +- **WHEN** un visitante solicita una pagina +- **THEN** la pagina se sirve normalmente +- **AND** no hay impacto en rendimiento + +#### Scenario: Solo paginas singulares +- **GIVEN** el hook `roi_theme_before_page_serve` +- **WHEN** la solicitud es para archivo, home, search, feed, o admin +- **THEN** el hook NO DEBE dispararse + +#### Scenario: Usuarios logueados excluidos +- **GIVEN** un usuario autenticado (logged in) +- **WHEN** solicita cualquier pagina +- **THEN** el hook NO DEBE dispararse +- **BECAUSE** los plugins de cache no cachean paginas para usuarios logueados + +#### Scenario: REST API excluida +- **GIVEN** una peticion REST API (REST_REQUEST === true) +- **WHEN** se procesa la peticion +- **THEN** el hook NO DEBE dispararse +- **BECAUSE** las peticiones REST tienen su propio ciclo de vida y no sirven paginas HTML + +--- + +### Requirement: Contexto para Plugins + +The hook MUST provide sufficient context for plugins to make decisions. + +#### Scenario: Plugin accede a informacion del post - **GIVEN** un plugin enganchado a `roi_theme_before_page_serve` - **WHEN** el hook se dispara - **THEN** el plugin recibe `$post_id` como parametro -- **AND** `get_queried_object()` retorna el objeto WP_Post completo -- **AND** `is_singular()`, `is_single()`, `is_page()` funcionan correctamente +- **AND** `get_queried_object()` retorna el WP_Post completo +- **AND** funciones como `is_singular()`, `is_single()`, `is_page()` funcionan -#### Scenario: Plugin necesita informacion del visitante -- **GIVEN** un plugin enganchado a `roi_theme_before_page_serve` +#### Scenario: Plugin accede a informacion del visitante +- **GIVEN** un plugin enganchado al hook - **WHEN** el hook se dispara -- **THEN** `is_user_logged_in()` esta disponible -- **AND** `$_SERVER['REMOTE_ADDR']` esta disponible +- **THEN** `$_SERVER['REMOTE_ADDR']` esta disponible - **AND** headers HTTP estan disponibles via `$_SERVER` --- -### Requirement: No Bloquear Cache +### Requirement: No Interferir con Cache -The system MUST NOT define DONOTCACHEPAGE or similar constants that prevent caching. +The theme MUST NOT define cache-blocking constants. -#### Scenario: Tema no interfiere con plugins de cache +#### Scenario: Tema no bloquea cache - **GIVEN** el tema roi-theme instalado -- **WHEN** W3TC, WP Super Cache, o Redis Object Cache estan activos +- **WHEN** plugins de cache (W3TC, WP Super Cache, etc.) estan activos - **THEN** el tema NO DEBE definir `DONOTCACHEPAGE` -- **AND** el tema NO DEBE definir `DONOTCACHEOBJECT` - **AND** el tema NO DEBE enviar headers `Cache-Control: no-cache` -#### Scenario: Plugin externo decide bloquear cache -- **GIVEN** un plugin enganchado a `roi_theme_before_page_serve` -- **WHEN** el plugin necesita bloquear cache para una pagina especifica +#### Scenario: Plugin decide bloquear cache +- **GIVEN** un plugin necesita bloquear cache para una pagina +- **WHEN** el plugin esta enganchado al hook - **THEN** es responsabilidad del PLUGIN definir `DONOTCACHEPAGE` - **AND** el tema NO participa en esa decision --- -### Requirement: Ubicacion en Clean Architecture +## Known Limitations -The hook registration MUST follow ROITheme's Clean Architecture patterns. +### Limitation 1: Page Cache Bypass -#### Scenario: Hook registrado en Infrastructure -- **GIVEN** el sistema de hooks del tema -- **WHEN** el hook `roi_theme_before_page_serve` es registrado -- **THEN** el registro DEBE estar en `Shared/Infrastructure/Hooks/` -- **AND** DEBE seguir el patron de HooksRegistrar existente +**Severity**: CRITICAL para plugins que requieren evaluacion en cada request -#### Scenario: Servicio como punto de extension -- **GIVEN** la arquitectura del tema -- **WHEN** se necesita extender funcionalidad de pre-evaluacion -- **THEN** DEBE existir una interfaz en `Shared/Domain/Contracts/` -- **AND** la implementacion DEBE estar en `Shared/Infrastructure/Services/` +Cuando Page Cache esta habilitado (W3TC, WP Super Cache, etc.), el hook `roi_theme_before_page_serve` NO SE EJECUTA para paginas cacheadas. + +**Razon tecnica:** +``` +Request → advanced-cache.php → [Cache HIT] → HTML servido + ↓ + WordPress NUNCA carga + ↓ + Hook NUNCA se dispara +``` + +**Implicacion para plugins:** +- Rate limiters: Los limites no se evaluan en cache hits +- Membership plugins: El acceso no se verifica en cache hits +- Geolocation: Las restricciones no aplican en cache hits + +**Solucion:** Los plugins que requieren evaluacion en cada request deben implementar su propia estrategia (JavaScript-First, cookies, edge workers, etc.). Esto esta FUERA del alcance de esta spec. + +### Limitation 2: Solo Paginas Singulares + +El hook solo dispara para `is_singular() === true`. Archives, taxonomies, search, y home NO disparan el hook. --- -## Implementation Notes +## Implementation -### Hook Priority +### Ubicacion en Clean Architecture -``` -template_redirect priority order: -├─ Priority 0: roi_theme_before_page_serve (tema dispara hook) -│ └─ Plugins externos se enganchan aqui -├─ Priority 1+: Otros plugins -└─ Priority 10 (default): WordPress template loading -``` +El hook DEBE registrarse en `Shared/Infrastructure/Hooks/`. -### Ejemplo de Plugin Enganchado +### Archivo: CacheFirstHooksRegistrar.php ```php -// En un plugin externo (ej: ip-rate-limiter) -add_action('roi_theme_before_page_serve', function(int $post_id) { - // Evaluar condicion (ej: limite de IP) - if ($this->is_limit_exceeded()) { - wp_safe_redirect('/suscripcion-vip/?reason=limit', 302); - exit; + 0) { + do_action('roi_theme_before_page_serve', $post_id); + } + } +} ``` -### Archivos a Crear +### Registro en functions.php -``` -Shared/ -├── Domain/ -│ └── Contracts/ -│ └── PageServeHookInterface.php # Interface del hook -└── Infrastructure/ - └── Hooks/ - └── CacheFirstHooksRegistrar.php # Registro del hook +```php +$cacheFirstHooks = new \ROITheme\Shared\Infrastructure\Hooks\CacheFirstHooksRegistrar(); +$cacheFirstHooks->register(); ``` --- ## Acceptance Criteria -1. El hook `roi_theme_before_page_serve` se dispara en `template_redirect` priority 0 -2. Solo se dispara para `is_singular() === true` -3. NO se dispara para usuarios logueados (`is_user_logged_in() === true`) -4. Pasa `$post_id` como parametro al hook +1. Hook `roi_theme_before_page_serve` se dispara en `template_redirect` priority 0 +2. Solo dispara para `is_singular() === true` +3. NO dispara para usuarios logueados +4. Pasa `$post_id` como parametro 5. No define DONOTCACHEPAGE ni headers anti-cache -6. Plugins externos pueden enganchar y hacer redirect/exit -7. Si ningun plugin engancha, no hay impacto en rendimiento -8. Sigue patrones de Clean Architecture del tema +6. Plugins pueden enganchar y hacer redirect/exit +7. Sin impacto en rendimiento si ningun plugin engancha + +--- + +## Version History + +| Version | Date | Changes | +|---------|------|---------| +| 1.0 | 2025-12-07 | Initial spec | +| 2.0 | 2025-12-07 | Simplified: Only defines hook, removed plugin implementation details |