# Especificacion de Arquitectura Cache-First ## 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. 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) --- ### Requirement: Contexto Rico para Plugins Externos The system MUST provide sufficient context for external plugins to make access decisions. #### Scenario: Plugin necesita 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 #### Scenario: Plugin necesita informacion del visitante - **GIVEN** un plugin enganchado a `roi_theme_before_page_serve` - **WHEN** el hook se dispara - **THEN** `is_user_logged_in()` esta disponible - **AND** `$_SERVER['REMOTE_ADDR']` esta disponible - **AND** headers HTTP estan disponibles via `$_SERVER` --- ### Requirement: No Bloquear Cache The system MUST NOT define DONOTCACHEPAGE or similar constants that prevent caching. #### Scenario: Tema no interfiere con plugins de cache - **GIVEN** el tema roi-theme instalado - **WHEN** W3TC, WP Super Cache, o Redis Object Cache 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 - **THEN** es responsabilidad del PLUGIN definir `DONOTCACHEPAGE` - **AND** el tema NO participa en esa decision --- ### Requirement: Ubicacion en Clean Architecture The hook registration MUST follow ROITheme's Clean Architecture patterns. #### 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 #### 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/` --- ## Implementation Notes ### Hook Priority ``` 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 ``` ### Ejemplo de Plugin Enganchado ```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; } // Si no hay problema, simplemente retornar // La pagina se servira (con cache si disponible) }, 10); ``` ### Archivos a Crear ``` Shared/ ├── Domain/ │ └── Contracts/ │ └── PageServeHookInterface.php # Interface del hook └── Infrastructure/ └── Hooks/ └── CacheFirstHooksRegistrar.php # Registro del hook ``` --- ## 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 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