fix(header): el entorno se detecta en tiempo de ejecucion, no con un fichero .prod

`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
This commit is contained in:
Jordan Diaz
2026-09-01 19:16:12 +00:00
co-authored by Claude Opus 5
parent 3747508812
commit 92f092dcc4
3 changed files with 63 additions and 95 deletions
+33
View File
@@ -1,6 +1,39 @@
<?
require_once CMS_VIEWER_LIB;
/**
* ¿Esta copia de la web corre en Forge (local o test) o en producción?
*
* La señal es la PRESENCIA del `.acai` en la raíz: Forge lo escribe en cada copia
* local, y NUNCA viaja a producción — está en el `exclude` del manifest de
* push-core y fuera de la allowlist del sync per-web (verificado 2026-09-01).
*
* Se detecta LOCAL de forma explícita y todo lo demás se trata como producción,
* no al revés: si la señal fallara, el comportamiento seguro es el de producción
* (respetar `pagina_publicada`). Asumir local ante la duda podría dejar visible
* una web sin terminar.
*
* POR QUÉ VIVE AQUÍ y no en otro sitio, que costó tres intentos:
* - NO en `cms/`: esa carpeta se sobrescribe al actualizar el core desde el CMS
* legacy y el cambio se perdería.
* - NO en `lib/variables.php`: ese fichero viaja en el sync PER-WEB (es el único
* de raíz que lo hace), así que la copia de cada web manda y puede quedarse
* vieja o divergir. Una función del núcleo no puede vivir en un fichero que
* cada web sobrescribe.
* - NO en un plugin (`TokenGuard::isLocalTest()` hace esto mismo): el núcleo no
* debe depender de que un plugin esté presente y 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.
*/
function esEntornoLocal() {
static $local = null;
if ($local === null) {
$local = is_file(dirname(__FILE__) . "/.acai");
}
return $local;
}
// VARIABLES RELACIONADAS CON LA EXTRACCION DE CSS
$contadorImagenes = 0;
$modulosCargados = array();
+28 -15
View File
@@ -56,23 +56,36 @@ $config_header = array(
'alternate' => @$alternate
);
if (1){
// Quien ve la web y quien ve la pagina de mantenimiento.
//
// En LOCAL/TEST (Forge) siempre se ve la web: ahi no existe el concepto de
// "publicada" ni el modo `?pruebas`, que son solo de produccion.
//
// En PRODUCCION:
// - publicada -> se ve
// - sin publicar + ?pruebas -> se ve, con el cartel rojo
// - sin publicar + visitante -> pagina de mantenimiento
//
// Antes esto era un `if (1)` hardcodeado que se saltaba la comprobacion entera,
// con una copia `header.php.prod` que comentaba esas lineas para produccion. La
// copia estaba MAL: al comentar el `if(1){...}else{`, el cuerpo del else pasaba a
// ejecutarse siempre y un visitante normal de una web PUBLICADA recibia
// `die(mantenimiento)`. Nadie lo vio porque ese fichero solo corria en
// produccion. Con la condicion en tiempo de ejecucion el camino de produccion se
// prueba en local tocando la señal.
$verLaWeb = esEntornoLocal()
|| @$configuracionRecord["pagina_publicada"]
|| isset($_SESSION["pruebas"]);
if ($verLaWeb) {
if (@$customCode) echo modulo('custom-header',$config_header); else echo tpl('cabecera',$config_header);
}else{
if (!isset($_SESSION["pruebas"])){
die(tpl('mantenimiento',$config_header));
}else{
if (@$customCode) echo modulo('custom-header',$config_header); else echo tpl('cabecera',$config_header);
if (isset($_SESSION["pruebas"])){
if ($configuracionRecord["pagina_publicada"]==0){
?>
<div style="position:absolute;top:0px;width:150px;background-color:red;color:#fff;font-size:12px;padding:0 10px;z-index:99999999;transform:translateZ(1000px);">SITIO EN PRUEBAS</div>
<?
}
}
// Aviso solo cuando de verdad estas mirando algo sin publicar (prod + pruebas).
if (!esEntornoLocal() && isset($_SESSION["pruebas"]) && @$configuracionRecord["pagina_publicada"] == 0) {
?>
<div style="position:absolute;top:0px;width:150px;background-color:red;color:#fff;font-size:12px;padding:0 10px;z-index:99999999;transform:translateZ(1000px);">SITIO EN PRUEBAS</div>
<?
}
} else {
die(tpl('mantenimiento',$config_header));
}
?>
-78
View File
@@ -1,78 +0,0 @@
<?
require_once ("sesion.php");
if (isset($_GET["pruebas"])) $_SESSION["pruebas"]=true;
require_once "funciones.php";
if (!isset($current)) $current=0;
if (HAY_TIENDA) {
$categorias = CocoDB::get("categorias_productos", "parentNum=0", "siblingOrder ASC", null, ["ignoreSchema" => true]);
}
$idiomas = dame_idiomas();
$idiomaSeleccionado = "Español";
foreach ($idiomas as $idioma):
if ($idioma["valor"]=="/".@$_REQUEST["idioma"]) $idiomaSeleccionado=$idioma["idioma"];
endforeach;
$apartadoCesta = CocoDB::get("apartados", "controlador='cesta.php'", null, 1, ["ignoreSchema" => true]);
$apartadoCesta = @$apartadoCesta[0];
$apartadoFavoritos = CocoDB::get("apartados", "controlador='favoritos.php'", null, 1, ["ignoreSchema" => true]);
$apartadoFavoritos = @$apartadoFavoritos[0];
$apartadoLogin = CocoDB::get("apartados", "controlador='login.php'", null, 1, ["ignoreSchema" => true]);
$apartadoLogin = @$apartadoLogin[0];
$apartadoRegistro = CocoDB::get("apartados", "controlador='registro.php'", null, 1, ["ignoreSchema" => true]);
$apartadoRegistro = @$apartadoRegistro[0];
$alternate = dame_alternates($_SERVER["REQUEST_URI"]);
$config_header = array(
'titulo_de_pagina' => $configuracionRecord["titulo_de_pagina"],
'categorias' => @$categorias,
'pagina_publicada' => $configuracionRecord["pagina_publicada"],
'current' => $current,
'portada' => @$portada,
'index' => @$index,
'configuracionRecord' => $configuracionRecord,
'configuracionTienda' => $configuracionTienda,
'meta_descripcion' => $configuracionRecord["metatag_descripcion"],
'meta_palabras' => @$configuracionRecord["metatag_palabras"],
'otros_metas' => @$otros_metas,
'color_base' => @$color_base,
'categorias' => @$categorias,
'idiomas' => @$idiomas,
'idiomaSeleccionado'=> @$idiomaSeleccionado,
'apartadoCesta' => @$apartadoCesta,
'apartadoFavoritos' => @$apartadoFavoritos,
'apartadoLogin' => @$apartadoLogin,
'apartadoRegistro' => @$apartadoRegistro,
'sitebuilder' => @$apartado["plantilla_sitebuilder"],
'alternate' => @$alternate
);
#if (1){
# if (@$customCode) echo modulo('custom-header',$config_header); else echo tpl('cabecera',$config_header);
#}else{
if (!isset($_SESSION["pruebas"])){
die(tpl('mantenimiento',$config_header));
}else{
if (@$customCode) echo modulo('custom-header',$config_header); else echo tpl('cabecera',$config_header);
if (isset($_SESSION["pruebas"])){
if ($configuracionRecord["pagina_publicada"]==0){
?>
<div style="position:absolute;top:0px;width:150px;background-color:red;color:#fff;font-size:12px;padding:0 10px;z-index:99999999;transform:translateZ(1000px);">SITIO EN PRUEBAS</div>
<?
}
}
}
#}
?>