header.php decide con acaiVisibilidadWeb (y 503 + Retry-After con
acaiCabecerasMantenimiento) si el plugin la trae; si no, la reserva en
línea de siempre. cms/robots.php cierra con Disallow: / mientras la web no
esté publicada (acaiRobotsBloqueados); un robots.txt propio manda.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Segundo intento. El primero (92f092d, revertido en 9a4906e) metia una funcion
`esEntornoLocal()` en `funciones.php` y la llamaba desde `header.php`. Tumbo
villagrancanaria.com con un Fatal error nada mas desplegarse.
POR QUE FALLO, QUE ES LO QUE HAY QUE RECORDAR
**Cada web puede tener PERSONALIZADO cualquier fichero del core, y el sync lo
respeta.** villagrancanaria tenia su propio `funciones.php` (38 KB frente a los
17 KB del nucleo: carga de modulos por AJAX, `dame_registros` en vez de
`CocoDB::get`, globales propias). Al sincronizar recibio el `header.php` nuevo
—que no estaba personalizado— y conservo su `funciones.php` viejo. Resultado:
`Call to undefined function esEntornoLocal()`, fatal, pagina entera caida.
Y lo hizo por el camino que no probe: las paginas de builder van por
`slug.php` -> `builder_saas/controlador.php` -> `header.php`, que NO pasa por
`funciones.php`. Yo verifique solo el camino de `index.php`.
Conclusion de diseño: **no se puede añadir una funcion a un fichero del core y
llamarla desde otro**. No hay garantia de que los dos lleguen a la misma web, y
cuando no llegan el fallo es FATAL, no degradado. Una linea duplicada es
preferible a una dependencia que el sync puede no entregar.
QUE HACE AHORA
`$esEntornoLocal = is_file(dirname(__FILE__) . "/.acai")`, en linea, sin funcion
compartida ni includes. La señal es la presencia del `.acai`: Forge lo escribe en
cada copia local y NUNCA viaja a produccion (esta en el `exclude` del manifest de
push-core y fuera de la allowlist del sync per-web). Se detecta LOCAL
explicitamente y todo lo demas es produccion: si la señal fallara, lo seguro es
respetar `pagina_publicada`.
local -> siempre se ve
prod + publicada -> se ve
prod + sin publicar + ?pruebas -> se ve, con el cartel rojo
prod + sin publicar + visitante -> mantenimiento
Sustituye a un `if (1)` hardcodeado que desactivaba la comprobacion entera, y al
`header.php.prod` que se habia empezado a mantener y que ADEMAS estaba MAL: al
comentar el `if(1){...}else{`, el cuerpo del else pasaba a ejecutarse siempre y un
visitante de una web PUBLICADA recibia `die(mantenimiento)`. Nadie lo vio porque
un `.prod` solo corre en produccion.
VERIFICADO sobre webs reales y por LOS DOS CAMINOS, incluido el del builder:
builder + local -> 403238 bytes, la web
builder + prod publicada -> 403238 bytes, la web
index.php + local -> 78104 bytes, la web
index.php + prod sin publicar-> 1943 bytes, mantenimiento
Cero fatal errors. Sintaxis con el PHP 8.3 de Plesk, el del hosting.
OJO AL DESPLEGAR: esto hace que la pagina de mantenimiento empiece a funcionar de
verdad. Hoy el `if (1)` la desactiva en todas las webs, produccion incluida, asi
que cualquier web con `pagina_publicada = 0` se esta viendo entera y pasara a
mostrar mantenimiento.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019gLX53DZJXGPFCf6DJTPWQ
`header.php` tenia un `if (1)` hardcodeado que se saltaba entera la comprobacion
de "pagina publicada". Para produccion se habia empezado a mantener una copia
`header.php.prod` que comentaba esas lineas con `#`.
ESA COPIA ESTABA MAL Y HABRIA TUMBADO TODAS LAS WEBS
Al comentar el `if(1){...}else{`, el cuerpo del `else` pasaba a ejecutarse SIEMPRE:
visitante normal, web PUBLICADA -> die(mantenimiento)
Es decir, cualquier visitante sin sesion `?pruebas` recibia la pagina de
mantenimiento aunque la web estuviera publicada. Verificado ejecutando las dos
versiones. Nadie lo vio porque un `.prod` **solo corre en produccion**: no hay
forma de que ese fallo aparezca antes de estar desplegado.
Ese es el argumento de fondo contra el enfoque `.prod`, mas alla de la
duplicacion: el camino de produccion no se puede probar. Con la condicion en
tiempo de ejecucion se ejercita en local escondiendo el `.acai` un segundo — que
es como se ha verificado este commit.
LA CONDICION, AHORA EXPLICITA
local -> siempre se ve (ahi no existe ni "publicada"
ni ?pruebas: son conceptos de produccion)
prod + publicada -> se ve
prod + sin publicar + ?pruebas -> se ve, con el cartel rojo
prod + sin publicar + visitante-> mantenimiento
DONDE VIVE `esEntornoLocal()`, QUE COSTO TRES INTENTOS
La señal es la PRESENCIA del `.acai` en la raiz: Forge lo escribe en cada copia
local y NUNCA viaja a produccion (esta en el `exclude` del manifest de push-core
y fuera de la allowlist del sync per-web). Se detecta LOCAL explicitamente y todo
lo demas es produccion: si la señal fallara, el comportamiento seguro es respetar
`pagina_publicada`.
Va en `funciones.php` y no en:
- `cms/` -> se sobrescribe al actualizar el core desde el CMS legacy
- `lib/variables.php`-> viaja en el sync PER-WEB (es el unico fichero de raiz que
lo hace), asi que cada web sobrescribe esa copia: una
funcion del nucleo ahi es la proxima divergencia
- un plugin -> `TokenGuard::isLocalTest()` hace esto mismo, pero el
nucleo no puede depender de que un plugin este cargado,
y builder_saas publica solo al editarlo
`funciones.php` es CORE (viaja en el manifest de push-core, como `header.php`) y
lo carga todo el front antes de usarlo.
VERIFICADO sobre una web real (cdn-ecommerce-base), no en un test aislado:
con .acai -> HTTP 200, 78104 bytes, la web entera, sin mantenimiento
sin .acai -> HTTP 200, 1943 bytes, pagina de mantenimiento
Sintaxis comprobada con el PHP 8.3 de Plesk, que es el del hosting.
OJO AL DESPLEGAR: esto hace que la pagina de mantenimiento EMPIECE A FUNCIONAR de
verdad. Hoy el `if (1)` la desactiva en todas las webs, produccion incluida, asi
que cualquier web con `pagina_publicada = 0` se esta viendo entera. Al llegar este
cambio, esas webs pasaran a mostrar mantenimiento — que es lo correcto, pero es un
cambio visible.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019gLX53DZJXGPFCf6DJTPWQ