Files
acai-vscode-webbase/funciones.php
T
Jordan DiazandClaude Opus 5 92f092dcc4 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
2026-09-01 19:16:12 +00:00

376 lines
19 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?
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();
$recursosCSS = array();
// HASTA AUQI
if (!file_exists(__DIR__.'/'.CMS_FOLDER.'/uploads/webp/')) {
mkdir(__DIR__.'/'.CMS_FOLDER.'/uploads/webp/');
}
global $configuracionTienda;
$configuracionRecord = CocoDB::get("configuracion", "", null, 1);
$configuracionRecord = @$configuracionRecord[0];
$configuracionTienda = CocoDB::get("configuracion_tienda", "", null, 1);
$configuracionTienda = @$configuracionTienda[0];
define("HAY_TIENDA", @$configuracionTienda["tienda_activa"]);
if (@$configuracionRecord["pagina_publicada"] && !@$_SESSION["pruebas"]) error_reporting(0);
// COMPROBAMOS SI HAY CUSTOM HEADER Y FOOTER Y ACTIVAMOS LA VARIABLE
// ARCHIVOS AFECTADOS : header.php - footer.php - funciones.php - htaccess
$layoutFile = __DIR__."/".CMS_FOLDER."/lib/plugins/builder_saas/layout.json";
if (file_exists($layoutFile)){
$layoutJson = json_decode(file_get_contents($layoutFile),true);
if (@$layoutJson["active"]){
global $customCode;
$customCode = true;
}
}
/******** NUEVAS FUNCIONES ********/
function dame_alternates($link) {
global $SETTINGS, $TABLE_PREFIX,$tabla, $num;
$enlaces = array();
$idiomasPermitidos = array_filter(array_map(function($idioma) {
return str_replace("/", "", $idioma["valor"]);
}, dame_idiomas()));
if (!@$tabla) return [];
$encontrado = mysql_fetch_assoc(mysql_query("SELECT * FROM ".$tabla." WHERE num=".$num." limit 1"));
if (@$encontrado) $encontrado["tableName"] = str_replace($TABLE_PREFIX,"",$tabla);
if (!@$encontrado["num"]) return $enlaces;
$enlaces[] = array(
"prefix" => "es",
"fieldValue" => base64_encode($encontrado["enlace"])
);
$sql = mysql_query("SELECT * FROM ".$TABLE_PREFIX."traducciones WHERE fieldName='enlace' AND prefix IN('".join("','", $idiomasPermitidos)."') AND tableName='".$encontrado["tableName"]."' AND recordNum=".$encontrado["num"]);
while ($row = mysql_fetch_assoc($sql)) {
$enlaces[] = $row;
}
return $enlaces;
}
/******** FIN NUEVAS FUNCIONES ********/
function hasRecaptcha() {
global $configuracionRecord;
return @$configuracionRecord["site_key_recaptcha"] && @$configuracionRecord["secret_key_recaptcha"];
}
function dame_registros($tabla,$where="",$order="",$limit=1000,$depth=0){
global $TABLE_PREFIX;
list($configuracionRecords, $configuracionMetaData,$schema) = getRecords(array(
'tableName' => $tabla,
'where' => $where,
'allowSearch' => 0,
'orderBy' => $order,
'limit' => $limit
));
/*
EXPERIMENTAL - EN DESARROLLO
*/
foreach ($configuracionRecords as $index => $record) {
if (@$schema["menuType"] == "category"){
$configuracionRecords[$index]["childs"] = mysql_num_rows(mysql_query("SELECT * FROM ".$TABLE_PREFIX.$tabla." WHERE parentNum=".$record["num"]));
}
foreach ($record as $key => $value) {
if (!isset($schema[$key]["type"]) || !is_array($schema[$key])) continue;
switch (@$schema[$key]["type"]) {
case "list":
if (@$schema[$key]["optionsType"] == "table") {
$nums = array_filter(explode("\t", $value ?? ''));
if (@$nums && !$depth) {
$newSchema = loadSchema($schema[$key]["optionsTablename"]);
if (@$newSchema["dragSortOrder"]) $order = "dragSortOrder DESC";
if (@$newSchema["siblingOrder"]) $order = "siblingOrder ASC";
if (!@$order) $order = "num DESC";
$newRecord = dame_registros($schema[$key]["optionsTablename"], $schema[$key]["optionsValueField"]." IN (".join(",", $nums).")", $order,1000,1);
$configuracionRecords[$index][$key."_bd"] = $newRecord;
}else {
$configuracionRecords[$index][$key."_bd"] = array();
}
}else{
$configuracionRecords[$index][$key."_bd"] = array();
}
break;
case "multitext":
$result = (@$value) ? json_decode(t($record, $key), true) : array();
$configuracionRecords[$index][$key."_bd"] = $result;
break;
case "textfield":
if (@$schema[$key]["tipoTags"]) {
$tags = array_filter(explode(",", $value));
$configuracionRecords[$index][$key."_bd"] = $tags;
}
break;
default:
break;
}
}
$configuracionRecords[$index]["breadcrumbField"] = @$schema["breadcrumbField"];
// Si es parentNum ponemos valores por defecto
if (@$configuracionRecords[$index]["breadcrumbField"] == "parentNum") {
$configuracionRecords[$index]["optionsTablename"] = $configuracionRecords[$index]["tableName"];
$configuracionRecords[$index]["optionsValueField"] = "num";
} else if (@$configuracionRecords[$index]["breadcrumbField"]) {
// Si no es parentNum, ponemos los que dicte el schema
$configuracionRecords[$index]["optionsTablename"] = @$schema[$schema["breadcrumbField"]]["optionsTablename"];
$configuracionRecords[$index]["optionsValueField"] = @$schema[$schema["breadcrumbField"]]["optionsValueField"];
}
// Para el campo principal (para la generación de enlaces y el breadcrumb)
if (@$record["name"]) {
$configuracionRecords[$index]["mainFieldBreadcrumb"] = t($record, "name");
}
else if (@$record["title"]) {
$configuracionRecords[$index]["mainFieldBreadcrumb"] = t($record, "title");
}
else if (@$record["titulo"]) {
$configuracionRecords[$index]["mainFieldBreadcrumb"] = t($record, "titulo");
}
else if (@$record["nombre"]) {
$configuracionRecords[$index]["mainFieldBreadcrumb"] = t($record, "nombre");
}
else {
foreach ($schema as $key => $value):
if (!is_array($value)) continue;
if (@$value["type"] == "textfield" && $key != "enlace") {
$configuracionRecords[$index]["mainFieldBreadcrumb"] = t($record, $key);
break;
}
endforeach;
}
}
if ($configuracionRecords) {
return $configuracionRecords;
}else {
return array();
}
}
function dame_idiomas(){
$array_ini = parse_ini_file($_SERVER["DOCUMENT_ROOT"]."/".CMS_FOLDER."/data/settings.dat.php", true);
$resultado = array();
if (@$array_ini["idiomas"]){
foreach ($array_ini["idiomas"] as $idioma => $valor):
if ($valor!=""){
if ($valor=="www") $valor=""; else $valor="/".$valor;
if ($idioma=="espanol") $idioma="Español";
if ($idioma=="ingles") $idioma ="Inglés";
if ($idioma=="aleman") $idioma="Alemán";
if ($idioma=="frances") $idioma ="Francés";
if ($idioma=="portugues") $idioma ="Portugués";
if ($idioma=="catalan") $idioma ="Catalán";
if ($idioma=="italiano") $idioma ="Italiano";
if ($idioma=="koreano") $idioma ="Koreano";
if ($idioma=="chino") $idioma ="Chino";
if ($idioma=="noruego") $idioma ="Noruego";
if ($idioma=="ruso") $idioma ="Ruso";
if ($idioma=="nigeriano") $idioma ="Nigeriano";
array_push($resultado,array("idioma" => $idioma,"valor" => $valor));
}
endforeach;
}
return $resultado;
}
function tpl($p,$d=array()){
global $configuracionRecord,$recursosCSS,$SETTINGS;
extract($d);
ob_start();
$doc = new domdocument();
require("./".PLANTILLA."/".$p.'.tpl');
$resultado = ob_get_clean();
return minify_html($resultado);
}
function modulo($p,$d=array()){
return Module::load($p, $d);
}
// Parsea enlace definitivo
function parsea_enlace($txt) {
$transliterationTable = array('á' => 'a', 'Á' => 'A', 'à' => 'a', 'À' => 'A', 'ă' => 'a', 'Ă' => 'A', 'â' => 'a', 'Â' => 'A', 'å' => 'a', 'Å' => 'A', 'ã' => 'a', 'Ã' => 'A', 'ą' => 'a', 'Ą' => 'A', 'ā' => 'a', 'Ā' => 'A', 'ä' => 'a', 'Ä' => 'A', 'æ' => 'ae', 'Æ' => 'AE', 'ḃ' => 'b', 'Ḃ' => 'B', 'ć' => 'c', 'Ć' => 'C', 'ĉ' => 'c', 'Ĉ' => 'C', 'č' => 'c', 'Č' => 'C', 'ċ' => 'c', 'Ċ' => 'C', 'ç' => 'c', 'Ç' => 'C', 'ď' => 'd', 'Ď' => 'D', 'ḋ' => 'd', 'Ḋ' => 'D', 'đ' => 'd', 'Đ' => 'D', 'ð' => 'dh', 'Ð' => 'Dh', 'é' => 'e', 'É' => 'E', 'è' => 'e', 'È' => 'E', 'ĕ' => 'e', 'Ĕ' => 'E', 'ê' => 'e', 'Ê' => 'E', 'ě' => 'e', 'Ě' => 'E', 'ë' => 'e', 'Ë' => 'E', 'ė' => 'e', 'Ė' => 'E', 'ę' => 'e', 'Ę' => 'E', 'ē' => 'e', 'Ē' => 'E', 'ḟ' => 'f', 'Ḟ' => 'F', 'ƒ' => 'f', 'Ƒ' => 'F', 'ğ' => 'g', 'Ğ' => 'G', 'ĝ' => 'g', 'Ĝ' => 'G', 'ġ' => 'g', 'Ġ' => 'G', 'ģ' => 'g', 'Ģ' => 'G', 'ĥ' => 'h', 'Ĥ' => 'H', 'ħ' => 'h', 'Ħ' => 'H', 'í' => 'i', 'Í' => 'I', 'ì' => 'i', 'Ì' => 'I', 'î' => 'i', 'Î' => 'I', 'ï' => 'i', 'Ï' => 'I', 'ĩ' => 'i', 'Ĩ' => 'I', 'į' => 'i', 'Į' => 'I', 'ī' => 'i', 'Ī' => 'I', 'ĵ' => 'j', 'Ĵ' => 'J', 'ķ' => 'k', 'Ķ' => 'K', 'ĺ' => 'l', 'Ĺ' => 'L', 'ľ' => 'l', 'Ľ' => 'L', 'ļ' => 'l', 'Ļ' => 'L', 'ł' => 'l', 'Ł' => 'L', 'ṁ' => 'm', 'Ṁ' => 'M', 'ń' => 'n', 'Ń' => 'N', 'ň' => 'n', 'Ň' => 'N', 'ñ' => 'n', 'Ñ' => 'N', 'ņ' => 'n', 'Ņ' => 'N', 'ó' => 'o', 'Ó' => 'O', 'ò' => 'o', 'Ò' => 'O', 'ô' => 'o', 'Ô' => 'O', 'ő' => 'o', 'Ő' => 'O', 'õ' => 'o', 'Õ' => 'O', 'ø' => 'o', 'Ø' => 'O', 'ō' => 'o', 'Ō' => 'O', 'ơ' => 'o', 'Ơ' => 'O', 'ö' => 'o', 'Ö' => 'O', 'ṗ' => 'p', 'Ṗ' => 'P', 'ŕ' => 'r', 'Ŕ' => 'R', 'ř' => 'r', 'Ř' => 'R', 'ŗ' => 'r', 'Ŗ' => 'R', 'ś' => 's', 'Ś' => 'S', 'ŝ' => 's', 'Ŝ' => 'S', 'š' => 's', 'Š' => 'S', 'ṡ' => 's', 'Ṡ' => 'S', 'ş' => 's', 'Ş' => 'S', 'ș' => 's', 'Ș' => 'S', 'ß' => 'SS', 'ť' => 't', 'Ť' => 'T', 'ṫ' => 't', 'Ṫ' => 'T', 'ţ' => 't', 'Ţ' => 'T', 'ț' => 't', 'Ț' => 'T', 'ŧ' => 't', 'Ŧ' => 'T', 'ú' => 'u', 'Ú' => 'U', 'ù' => 'u', 'Ù' => 'U', 'ŭ' => 'u', 'Ŭ' => 'U', 'û' => 'u', 'Û' => 'U', 'ů' => 'u', 'Ů' => 'U', 'ű' => 'u', 'Ű' => 'U', 'ũ' => 'u', 'Ũ' => 'U', 'ų' => 'u', 'Ų' => 'U', 'ū' => 'u', 'Ū' => 'U', 'ư' => 'u', 'Ư' => 'U', 'ü' => 'u', 'Ü' => 'U', 'ẃ' => 'w', 'Ẃ' => 'W', 'ẁ' => 'w', 'Ẁ' => 'W', 'ŵ' => 'w', 'Ŵ' => 'W', 'ẅ' => 'w', 'Ẅ' => 'W', 'ý' => 'y', 'Ý' => 'Y', 'ỳ' => 'y', 'Ỳ' => 'Y', 'ŷ' => 'y', 'Ŷ' => 'Y', 'ÿ' => 'y', 'Ÿ' => 'Y', 'ź' => 'z', 'Ź' => 'Z', 'ž' => 'z', 'Ž' => 'Z', 'ż' => 'z', 'Ż' => 'Z', 'þ' => 'th', 'Þ' => 'Th', 'µ' => 'u', 'а' => 'a', 'А' => 'a', 'б' => 'b', 'Б' => 'b', 'в' => 'v', 'В' => 'v', 'г' => 'g', 'Г' => 'g', 'д' => 'd', 'Д' => 'd', 'е' => 'e', 'Е' => 'E', 'ё' => 'e', 'Ё' => 'E', 'ж' => 'zh', 'Ж' => 'zh', 'з' => 'z', 'З' => 'z', 'и' => 'i', 'И' => 'i', 'й' => 'j', 'Й' => 'j', 'к' => 'k', 'К' => 'k', 'л' => 'l', 'Л' => 'l', 'м' => 'm', 'М' => 'm', 'н' => 'n', 'Н' => 'n', 'о' => 'o', 'О' => 'o', 'п' => 'p', 'П' => 'p', 'р' => 'r', 'Р' => 'r', 'с' => 's', 'С' => 's', 'т' => 't', 'Т' => 't', 'у' => 'u', 'У' => 'u', 'ф' => 'f', 'Ф' => 'f', 'х' => 'h', 'Х' => 'h', 'ц' => 'c', 'Ц' => 'c', 'ч' => 'ch', 'Ч' => 'ch', 'ш' => 'sh', 'Ш' => 'sh', 'щ' => 'sch', 'Щ' => 'sch', 'ъ' => '', 'Ъ' => '', 'ы' => 'y', 'Ы' => 'y', 'ь' => '', 'Ь' => '', 'э' => 'e', 'Э' => 'e', 'ю' => 'ju', 'Ю' => 'ju', 'я' => 'ja', 'Я' => 'ja', "!" => "", "|" => "", "'" => "", "\"" => "", "'" => "", "@" => "", "·" => "", "#" => "", "$" => "", "¢" => "", "%" => "", "∞" => "", "¬" => "", "/" => "", "÷" => "", "(" => "", "“" => "", ")" => "", "”" => "", "≠" => "", "?" => "", "'" => "", "¡" => "", "¿" => "", "‚" => "", "´" => "", "^" => "", "`" => "", "[" => "", "*" => "", "+" => "", "]" => "", "¨" => "", "´" => "", "{" => "", "}" => "", "," => "", ";" => "", "„" => "", "." => "", ":" => "", "…" => "", "<" => "", ">" => "", "≤" => "", "≥" => "", "»" => "", "«" => "", "œ" => "", "æ" => "", "®" => "", "†" => "", "¥" => "", "π" => "", "∫" => "", "" => "", "™" => "", "¶" => "", "§" => "", "~" => "", "Ω" => "", "∑" => "", "©" => "", "√" => "", "µ" => "", "=" => "", "&" => "", " " => "-", "–" => "-", "_" => "-", " " => "-", '€' => 'e', 'º' => '', 'ª' => '', '&' => 'y', '\'' => '');
$enlace = strtolower(str_replace(array_keys($transliterationTable), array_values($transliterationTable), $txt));
$enlace = preg_replace("/([\-]+)/", "-", $enlace);
return urlencode($enlace);
}
function acorta_texto($texto, $numeroDePalabras) {
// Primero contamos el numero de palabras que hay
$arrayPalabrasTexto = explode(" ", $texto);
$numeroPalabrasEnTexto = count($arrayPalabrasTexto);
// Si el numero de palabras es menor que las palabras del texto, las recortamos y devolvemos
if ($numeroDePalabras < $numeroPalabrasEnTexto) {
$arrayPalabrasTextoFinal = array();
for ($i = 0; $i < $numeroDePalabras; $i++) {
array_push($arrayPalabrasTextoFinal, $arrayPalabrasTexto[$i]);
}
return join(" ", $arrayPalabrasTextoFinal)."...";
}else{
// Si no, devolvemos el mismo texto
return $texto;
}
}
function muestra_breadcrumb($record = array(), $previousLinks = array(),$class = "bg-gray-200 p-3 rounded font-sans w-full breadcrumb-v2") {
global $TABLE_PREFIX;
$enlaces = array();
if (@$record) {
array_unshift($enlaces, $record);
}
$cont = 0;
$breadcrumbRecord = $record;
$idiomas = array_column(dame_idiomas(),"valor");
$idiomas = array_map(function($i){
return $i."/";
},$idiomas);
while (true && $cont++ <= 30) { // Contador de seguridad para evitar el bucle infinito (que en teoría nunca pasará, jaja)
// Comprobamos si la tabla ha cambiado para no volver a cargar el schema
if (@$breadcrumbRecord["tableName"] != @$tabla) {
$tabla = $breadcrumbRecord["tableName"];
$breadcrumbField = @$breadcrumbRecord["breadcrumbField"];
}
if (!@$breadcrumbField || !@$breadcrumbRecord["optionsTablename"]) break;
$breadcrumbRecord = dame_registros($breadcrumbRecord["optionsTablename"], $breadcrumbRecord["optionsValueField"]."=".mysql_real_escape_string($breadcrumbRecord[$breadcrumbField]));
$breadcrumbRecord = @$breadcrumbRecord[0];
if (!@$breadcrumbRecord) break;
array_unshift($enlaces, $breadcrumbRecord);
}
if ($cont == 30) return; // Por si las moscas
$i = 1;
echo '<nav aria-label="Breadcrumb" class="'.$class.'">';
echo '<ol itemscope itemtype="https://schema.org/BreadcrumbList" class="list-reset flex text-gray-700">';
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem" class="text-black-500 font-bold"><a itemprop="item" href="'.RUTA_RAIZ.'/"><span itemprop="name">'.t_var("Inicio").'</span></a><meta itemprop="position" content="'.$i.'" /></li><li><span class="mx-2 text-gray-400">/</span></li>';
$i++;
if(!in_array($record["enlace"],$idiomas)){
if (@$previousLinks) {
foreach ($previousLinks as $link):
if(strpos(t($link, "enlace"), "#") !== false) continue;
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><a itemprop="item" href="'.t($link, "enlace").'"><span itemprop="name">'.acorta_texto($link["mainFieldBreadcrumb"], 4).'</span></a><meta itemprop="position" content="'.$i.'" /></li><li><span class="mx-2 text-gray-400">/</span></li>';
$i++;
endforeach;
}
foreach ($enlaces as $cont => $enlace):
$enlace_parsed = @$enlace["enlace_breadcrumb"] ? $enlace["enlace_breadcrumb"] : t($enlace, "enlace");
if(strpos($enlace_parsed, "#") !== false) continue;
if ($cont == count($enlaces)-1) {
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><a itemprop="item" href="'.$enlace_parsed.'" aria-current="page"><span itemprop="name">'.acorta_texto(@$enlace["mainFieldBreadcrumb"], 4).'</span></a><meta itemprop="position" content="'.$i.'" /></li><li><span class="mx-2 text-gray-400">/</span></li>';
}
else {
echo '<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><a itemprop="item" href="'.$enlace_parsed.'"><span itemprop="name">'.acorta_texto($enlace["mainFieldBreadcrumb"], 4).'</span></a><meta itemprop="position" content="'.$i.'" /></li><li><span class="mx-2 text-gray-400">/</span></li>';
}
$i++;
endforeach;
}
echo '</ol>';
echo '</nav>';
}
function detect_error_on_code($code) {
preg_match_all('/\b(Fatal error|Parse error|Warning|Notice):.*?\b/i', $code, $matches);
return !empty($matches[0]) ? $matches[0] : array();
}
function error_html($error, $a404 = false) {
$result = '';
$icon = '
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24" fill="none" stroke="#607d8b" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 8v-2a2 2 0 0 1 2 -2h2" />
<path d="M4 16v2a2 2 0 0 0 2 2h2" />
<path d="M16 4h2a2 2 0 0 1 2 2v2" />
<path d="M16 20h2a2 2 0 0 0 2 -2v-2" />
<path d="M9 10h.01" />
<path d="M15 10h.01" />
<path d="M9.5 15.05a3.5 3.5 0 0 1 5 0" />
</svg>
';
$message = $a404 ? "Página no encontrada" : "Error en la página";
if ($a404){
$icon = '
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24" fill="none" stroke="#607d8b" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 7v4a1 1 0 0 0 1 1h3" />
<path d="M7 7v10" />
<path d="M10 8v8a1 1 0 0 0 1 1h2a1 1 0 0 0 1 -1v-8a1 1 0 0 0 -1 -1h-2a1 1 0 0 0 -1 1z" />
<path d="M17 7v4a1 1 0 0 0 1 1h3" />
<path d="M21 7v10" />
</svg>
';
}
$result.='<div style="display:flex;align-items:center;justify-content:center;width:100%;height:100%;font-family:Arial, sans-serif;">
<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;color:#607d8b;">
'.$icon.'
<p>'.$message.'</p>
<small style="margin-top:10px;display:block;">Por favor, contacte con el administrador del sitio.</small>
</div>
</div>';
$result.="<!-- Error details: -->\n";
$result.="<!--\n$error\n-->";
return $result;
}
?>