From 031ef33f9f65f8e4d87b4443c3fc79442aa7f897 Mon Sep 17 00:00:00 2001 From: Jordan Diaz Date: Wed, 22 Jul 2026 11:14:55 +0000 Subject: [PATCH] fix: devolver valores como string en las lecturas (paridad mysql_* legacy) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PDO con prepares nativos devuelve tipos reales (depth=int 0) mientras que mysql_* devolvia siempre strings. Los templates y codigo Acai comparan estrictamente contra strings (is same as('0'), === '1'...) y con tipos nativos esos filtros fallan en silencio — p.ej. el menu del header vacio en webs importadas (impulse) porque el filtro depth is same as('0') no matcheaba int(0). stringifyRows normaliza todos los escalares no-NULL a string en los 5 paths de lectura que devuelven datos hacia fuera: get(), uploads, cache de queries de relaciones, traducciones y pluginsConfig. --- cms/lib/classes/AcaiAPI.php | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/cms/lib/classes/AcaiAPI.php b/cms/lib/classes/AcaiAPI.php index f96bea2..134bce1 100644 --- a/cms/lib/classes/AcaiAPI.php +++ b/cms/lib/classes/AcaiAPI.php @@ -495,6 +495,7 @@ class AcaiAPI $rows = $db->executeS($sql, $pdoParams); if (!is_array($rows)) $rows = []; + $rows = self::stringifyRows($rows); // paridad de tipos con mysql_* legacy // ── Hydrate records ─────────────────────────────────────────────── $firstTableName = trim(explode(' ', $tables[0])[0]); @@ -743,7 +744,7 @@ class AcaiAPI if (!self::$pluginsConfig) { $db = Db::getInstance(); $configTable = preg_replace("/[^a-zA-Z0-9_]/", "", (string) $table) ?: "aux_plg_config"; - $rows = $db->executeS("SELECT * FROM `".$configTable."` ORDER BY num DESC") ?: []; + $rows = self::stringifyRows($db->executeS("SELECT * FROM `".$configTable."` ORDER BY num DESC") ?: []); self::$pluginsConfig = []; foreach ($rows as $row) { if (!isset(self::$pluginsConfig[$row['plugin']])) { @@ -811,6 +812,7 @@ class AcaiAPI ORDER BY `order` ASC", $params ); + $uploads = self::stringifyRows($uploads); // paridad de tipos con mysql_* legacy if (empty($uploads)) return []; @@ -914,7 +916,7 @@ class AcaiAPI $cacheKey = md5($query); if (!isset(self::$queryCaches[$cacheKey])) { $db = Db::getInstance(); - self::$queryCaches[$cacheKey] = $db->executeS($query) ?: []; + self::$queryCaches[$cacheKey] = self::stringifyRows($db->executeS($query) ?: []); } // Extract table name from the query for tableName field $tableQuery = null; @@ -1157,6 +1159,7 @@ class AcaiAPI ORDER BY num ASC", $params ) ?: []; + $rows = self::stringifyRows($rows); // paridad de tipos con mysql_* legacy foreach ($rows as $row) { $uploadNum = $row['tableName'] === 'uploads' @@ -1317,6 +1320,30 @@ class AcaiAPI * $params mixed[] positional values matching each `?` * $uploadFields array [fieldName => [urlPath, ...]] */ + /** + * Devuelve las filas con TODOS los valores escalares como string (NULL se + * mantiene NULL) — la semantica exacta del mysql_* legacy. PDO con + * prepares nativos devuelve tipos reales (int/float) y 20 años de + * templates/codigo Acai comparan estrictamente contra strings + * ("depth is same as('0')", === "1"...): sin esta normalizacion los + * filtros estrictos fallan EN SILENCIO (p.ej. menu del header vacio en + * webs importadas). Se aplica en todos los paths de lectura que devuelven + * datos hacia fuera de la clase. + */ + private static function stringifyRows($rows) + { + if (!is_array($rows)) return []; + foreach ($rows as $i => $row) { + if (!is_array($row)) continue; + foreach ($row as $k => $v) { + if ($v !== null && is_scalar($v) && !is_string($v)) { + $rows[$i][$k] = (string) $v; + } + } + } + return $rows; + } + private static function buildSetClause( array $record, array $schema,