feat(core): cambiar las fotos de un registro sella su updatedDate
This commit is contained in:
+147
-3
@@ -129,7 +129,7 @@ class AcaiAPI
|
||||
'order' => time() + $i,
|
||||
'width' => 640,
|
||||
'height' => 480,
|
||||
], [], ['ignoreSchema' => true, 'prefix' => $prefix]);
|
||||
], [], ['ignoreSchema' => true, 'prefix' => $prefix, 'skipTouchParent' => true]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,6 +154,15 @@ class AcaiAPI
|
||||
self::updateCategoryMetadata($table, $prefix);
|
||||
}
|
||||
|
||||
// Fotos nuevas = registro cambiado (ver "FOTOS -> FECHA DEL REGISTRO").
|
||||
// skipTouchParent: las que registra el propio insert/update del padre,
|
||||
// que ya sello su fecha en el mismo SET.
|
||||
if ($table === 'uploads' && $count && empty($options['skipTouchParent'])) {
|
||||
$pairs = [];
|
||||
foreach ($records as $r) $pairs[] = [$r['tableName'] ?? '', $r['recordNum'] ?? ''];
|
||||
self::touchUploadParents($pairs, $prefix);
|
||||
}
|
||||
|
||||
return !empty($options['return_last_id']) ? $lastId : $count;
|
||||
}
|
||||
|
||||
@@ -198,6 +207,11 @@ class AcaiAPI
|
||||
|
||||
if ($whereSql === null || $whereSql === '') return 0;
|
||||
|
||||
// Fotos cambiadas = registro cambiado: los padres de ANTES (y abajo los
|
||||
// de despues, por si la foto cambia de registro).
|
||||
$touchParents = ($table === 'uploads' && empty($options['skipTouchParent']));
|
||||
$parents = $touchParents ? self::uploadParents($where, $prefix) : [];
|
||||
|
||||
$count = 0;
|
||||
|
||||
foreach ($records as $record) {
|
||||
@@ -273,7 +287,7 @@ class AcaiAPI
|
||||
'order' => time() + $i,
|
||||
'width' => 640,
|
||||
'height' => 480,
|
||||
], [], ['ignoreSchema' => true, 'prefix' => $prefix]);
|
||||
], [], ['ignoreSchema' => true, 'prefix' => $prefix, 'skipTouchParent' => true]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -283,6 +297,10 @@ class AcaiAPI
|
||||
self::updateCategoryMetadata($table, $prefix);
|
||||
}
|
||||
|
||||
if ($touchParents && $count) {
|
||||
self::touchUploadParents(array_merge($parents, self::uploadParents($where, $prefix)), $prefix);
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
@@ -313,8 +331,14 @@ class AcaiAPI
|
||||
self::error(['info' => $sql, 'params' => $params]);
|
||||
}
|
||||
|
||||
// Fotos borradas = registro cambiado: hay que saber de quien eran ANTES.
|
||||
$parents = ($table === 'uploads' && empty($options['skipTouchParent']))
|
||||
? self::uploadParents($where, $prefix) : [];
|
||||
|
||||
$db = Db::getInstance();
|
||||
return $db->execute($sql, $params ? $params : null) !== false;
|
||||
$ok = $db->execute($sql, $params ? $params : null) !== false;
|
||||
if ($ok && $parents) self::touchUploadParents($parents, $prefix);
|
||||
return $ok;
|
||||
}
|
||||
|
||||
|
||||
@@ -1343,6 +1367,126 @@ class AcaiAPI
|
||||
}
|
||||
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// FOTOS -> FECHA DEL REGISTRO
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
//
|
||||
// Cambiar las fotos de un registro (filas de `uploads` con
|
||||
// tableName/recordNum) NO tocaba su `updatedDate`: el sync de Forge decide
|
||||
// por esa fecha que esta pendiente, y un registro al que solo se le
|
||||
// cambiaban las fotos (desde VSCode, el agente o el panel de fotos) nunca
|
||||
// se publicaba (reydimobel, 2026-09-26: siete categorias con las fotos
|
||||
// sustituidas en local y produccion enseñando las antiguas, en 404).
|
||||
// Regla: toda escritura en `uploads` sella la fecha de los registros a los
|
||||
// que pertenecen esas fotos. insert/update/delete de AcaiAPI lo hacen
|
||||
// solos; quien escriba `uploads` por SQL directo llama a
|
||||
// `touchUploadParents` (builder_saas/mcp_respond.php).
|
||||
|
||||
/** Cache por peticion: tabla completa => [columna => true] | null. */
|
||||
private static $auditColsCache = [];
|
||||
|
||||
/**
|
||||
* Los registros `[tableName, recordNum]` (sin repetir) a los que pertenecen
|
||||
* las fotos de `uploads` que cumplen `$where` (mismos formatos que
|
||||
* buildWhere). Las fotos sin registro todavia (recordNum vacio, las
|
||||
* temporales de preSaveTempId) no cuentan. Nunca lanza: [] si falla.
|
||||
*/
|
||||
static function uploadParents($where, $prefix = null)
|
||||
{
|
||||
global $TABLE_PREFIX;
|
||||
$prefix = $prefix === null ? $TABLE_PREFIX : $prefix;
|
||||
$params = [];
|
||||
$whereSql = self::buildWhere($where, $params);
|
||||
if (!$whereSql) return [];
|
||||
try {
|
||||
$rows = Db::getInstance()->executeS(
|
||||
"SELECT DISTINCT tableName, recordNum FROM `{$prefix}uploads` WHERE {$whereSql}",
|
||||
$params ?: null
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
return [];
|
||||
}
|
||||
$pairs = [];
|
||||
foreach ((array) $rows as $row) {
|
||||
if (is_array($row)) $pairs[] = [$row['tableName'] ?? '', $row['recordNum'] ?? ''];
|
||||
}
|
||||
return $pairs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sella `updatedDate` (y `updatedByUserNum` si existe) de los registros
|
||||
* `[[tableName, recordNum], ...]`. Salta lo que no es un registro de
|
||||
* verdad: tabla con nombre raro, recordNum no numerico o 0, tabla sin
|
||||
* columna `updatedDate`. Nunca lanza ni corta al llamador: un fallo aqui
|
||||
* no puede impedir guardar una foto. Devuelve cuantos registros sello.
|
||||
*/
|
||||
static function touchUploadParents($pairs, $prefix = null)
|
||||
{
|
||||
global $TABLE_PREFIX;
|
||||
$prefix = $prefix === null ? $TABLE_PREFIX : $prefix;
|
||||
$porTabla = [];
|
||||
foreach ((array) $pairs as $pair) {
|
||||
$tabla = is_array($pair) ? (string) ($pair[0] ?? '') : '';
|
||||
$num = is_array($pair) ? (string) ($pair[1] ?? '') : '';
|
||||
if (!preg_match('/^[A-Za-z0-9_]+$/', $tabla) || !ctype_digit($num) || (int) $num === 0) continue;
|
||||
$porTabla[$tabla][(int) $num] = true;
|
||||
}
|
||||
$sellados = 0;
|
||||
foreach ($porTabla as $tabla => $nums) {
|
||||
$sellados += self::touchRecords($prefix . $tabla, array_keys($nums));
|
||||
}
|
||||
if ($sellados) self::$requestGetCache = [];
|
||||
return $sellados;
|
||||
}
|
||||
|
||||
private static function touchRecords($fullTable, array $nums)
|
||||
{
|
||||
try {
|
||||
$db = Db::getInstance();
|
||||
$cols = self::auditColumns($db, $fullTable);
|
||||
if (!$cols || !isset($cols['updatedDate'])) return 0;
|
||||
$set = ['`updatedDate` = ?'];
|
||||
$params = [date('Y-m-d H:i:s')];
|
||||
if (isset($cols['updatedByUserNum'])) {
|
||||
$user = (class_exists('API') && isset(API::$user['num'])) ? ((int) API::$user['num'] ?: 1) : 1;
|
||||
$set[] = '`updatedByUserNum` = ?';
|
||||
$params[] = $user;
|
||||
}
|
||||
$ph = implode(',', array_fill(0, count($nums), '?'));
|
||||
$ok = $db->execute(
|
||||
"UPDATE `{$fullTable}` SET " . implode(', ', $set) . " WHERE num IN ($ph)",
|
||||
array_merge($params, $nums)
|
||||
);
|
||||
return $ok === false ? 0 : count($nums);
|
||||
} catch (\Throwable $e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** `[columna => true]` de las columnas de auditoria de `$fullTable`, o null. */
|
||||
private static function auditColumns($db, $fullTable)
|
||||
{
|
||||
if (array_key_exists($fullTable, self::$auditColsCache)) {
|
||||
return self::$auditColsCache[$fullTable];
|
||||
}
|
||||
try {
|
||||
$rows = $db->executeS(
|
||||
"SELECT COLUMN_NAME FROM information_schema.COLUMNS"
|
||||
. " WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?"
|
||||
. " AND COLUMN_NAME IN ('updatedDate', 'updatedByUserNum')",
|
||||
[$fullTable]
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
return self::$auditColsCache[$fullTable] = null;
|
||||
}
|
||||
$cols = [];
|
||||
foreach ((array) $rows as $row) {
|
||||
if (is_array($row) && !empty($row['COLUMN_NAME'])) $cols[$row['COLUMN_NAME']] = true;
|
||||
}
|
||||
return self::$auditColsCache[$fullTable] = $cols;
|
||||
}
|
||||
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// WRITE HELPERS (private)
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user