Files
FrankZamora 09d87835b8 chore: add debug comment to diagnose mode
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 10:58:48 -06:00

6.0 KiB

Especificacion: Hook de Pre-Evaluacion de Pagina

Purpose

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.

Alcance del tema: ROI-Theme SOLO provee el hook. La implementacion de logica de acceso es responsabilidad de cada plugin.


Requirements

Requirement: Hook roi_theme_before_page_serve

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 WP_Post completo
  • AND funciones como is_singular(), is_single(), is_page() funcionan

Scenario: Plugin accede a informacion del visitante

  • GIVEN un plugin enganchado al hook
  • WHEN el hook se dispara
  • THEN $_SERVER['REMOTE_ADDR'] esta disponible
  • AND headers HTTP estan disponibles via $_SERVER

Requirement: No Interferir con Cache

The theme MUST NOT define cache-blocking constants.

Scenario: Tema no bloquea cache

  • GIVEN el tema roi-theme instalado
  • WHEN plugins de cache (W3TC, WP Super Cache, etc.) estan activos
  • THEN el tema NO DEBE definir DONOTCACHEPAGE
  • AND el tema NO DEBE enviar headers Cache-Control: no-cache

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

Known Limitations

Limitation 1: Page Cache Bypass

Severity: CRITICAL para plugins que requieren evaluacion en cada request

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

Ubicacion en Clean Architecture

El hook DEBE registrarse en Shared/Infrastructure/Hooks/.

Archivo: CacheFirstHooksRegistrar.php

<?php
declare(strict_types=1);

namespace ROITheme\Shared\Infrastructure\Hooks;

final class CacheFirstHooksRegistrar
{
    public function register(): void
    {
        add_action('template_redirect', [$this, 'fireBeforePageServe'], 0);
    }

    public function fireBeforePageServe(): void
    {
        if (is_user_logged_in()) {
            return;
        }

        if (!is_singular()) {
            return;
        }

        if (is_admin() || wp_doing_ajax() || wp_doing_cron()) {
            return;
        }

        if (defined('REST_REQUEST') && REST_REQUEST) {
            return;
        }

        $post_id = get_queried_object_id();

        if ($post_id > 0) {
            do_action('roi_theme_before_page_serve', $post_id);
        }
    }
}

Registro en functions.php

$cacheFirstHooks = new \ROITheme\Shared\Infrastructure\Hooks\CacheFirstHooksRegistrar();
$cacheFirstHooks->register();

Acceptance Criteria

  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 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