fix: prevent file deletion on relink + restore button now visible + OOB-style in-place update

Two critical fixes:

1. Relink flow no longer destroys/recreates FilePond instances:
   The relink (XamxamRelinkFile) and PeerTube relink (XamxamRelinkPeerTube)
   previously refreshed the entire fichiers fragment via HTMX after
   pond.addFile(). This triggered destroyFilePondsIn on ALL pools, which
   could fire server.remove callbacks and move existing files to corbeille.
   Now just closes the modal — the file is already added to the pool in-place,
   and syncOrderInput creates the hidden form input.

2. Cleanup page « Corbeille (restaurable) » now actually shows files:
   _cleanup-stats-data.php previously classified trash files by checking if
   the thesis_files DB row still existed. But both deleteThesisFileToTrash
   and FilepondHandler::handleRemove DELETE the DB row. So ALL trash files
   appeared as `stale` (not restorable). Now uses the JSON sidecar file
   presence as the classification criterion — if the sidecar exists and is
   recent, the file is restorable regardless of DB row state.

Also removed unused DB query from _cleanup-stats-data.php.
This commit is contained in:
Pontoporeia
2026-07-10 16:29:04 +02:00
parent ed19e30cf0
commit 3cecee10c9
12 changed files with 587 additions and 73 deletions
@@ -92,7 +92,7 @@ if ($trStale > 0) {
<?php endif; ?>
<?php if ($trStale > 0): ?>
<h3 id="tmp-trash-heading">Corbeille <span class="n-meta"><?= htmlspecialchars($trMeta) ?></span></h3>
<h3 id="tmp-trash-heading">Corbeille (à nettoyer) <span class="n-meta"><?= htmlspecialchars($trMeta) ?></span></h3>
<table class="n-table" aria-labelledby="tmp-trash-heading">
<thead><tr><th width="1%"><input type="checkbox" onchange="cleanupToggleAll(this, 'trash')" title="Tout sélectionner"></th><th>Nom</th><th>Taille</th><th>Âge</th><th width="1%"></th></tr></thead>
<tbody>
@@ -120,9 +120,62 @@ if ($trStale > 0) {
</table>
<?php endif; ?>
<?php if ($fpActive > 0 || $trActive > 0): ?>
<?php
$trActiveFiles = $d['trash_active_files'] ?? [];
if (!empty($trActiveFiles)):
$trActiveMeta = $trActive . ' fichier' . ($trActive > 1 ? 's' : '');
if ($trActive > 0) {
$trActiveMeta .= ' · ' . ($d['trash_active_human'] ?? '');
}
?>
<h3 id="tmp-trash-restore-heading">Corbeille (restaurable) <span class="n-meta"><?= htmlspecialchars($trActiveMeta) ?></span></h3>
<p style="font-size:0.85em;color:var(--text-secondary);margin:0 0 var(--space-sm)">
Fichiers récemment supprimés pour lesquels le TFE associé existe encore. Vous pouvez les restaurer ou les supprimer définitivement.
</p>
<table class="n-table" aria-labelledby="tmp-trash-restore-heading">
<thead><tr><th>Nom</th><th>Taille</th><th>Âge</th><th>Origine</th><th width="1%"></th></tr></thead>
<tbody>
<?php foreach ($trActiveFiles as $f): ?>
<tr>
<td><strong><?= htmlspecialchars($f['name']) ?></strong></td>
<td style="white-space:nowrap"><?= htmlspecialchars($f['human']) ?></td>
<td style="white-space:nowrap">~<?= (int)$f['age_days'] ?> j</td>
<td style="font-size:0.85em;color:var(--text-secondary)">
<?= $f['has_sidecar'] ? htmlspecialchars($f['original_name'] ?? '?') . ' (' . htmlspecialchars($f['file_type'] ?? '?') . ')' : 'métadonnées indisponibles' ?>
</td>
<td style="white-space:nowrap">
<?php if ($f['has_sidecar']): ?>
<button type="button" class="btn btn--sm"
style="font-size:0.85em;padding:2px var(--space-xs);margin-right:4px"
hx-post="/admin/actions/restore-trash.php"
hx-confirm="Restaurer ce fichier vers le TFE associé ?"
hx-vals='{"csrf_token":"<?= htmlspecialchars($_SESSION['csrf_token']) ?>","trash_file":"<?= htmlspecialchars($f['name']) ?>"}'
hx-target="#tmp-cleanup-stats-wrapper"
hx-swap="innerHTML"
hx-indicator="#tmp-cleanup-stats-wrapper">
↺ Restaurer
</button>
<?php endif; ?>
<button type="button" class="btn btn--sm btn--danger"
style="font-size:0.85em;padding:2px var(--space-xs)"
hx-post="/admin/actions/cleanup-tmp.php"
hx-confirm="Supprimer définitivement ce fichier de la corbeille ?"
hx-vals='{"csrf_token":"<?= htmlspecialchars($_SESSION['csrf_token']) ?>","trash_file":"<?= htmlspecialchars($f['name']) ?>"}'
hx-target="#tmp-cleanup-stats-wrapper"
hx-swap="innerHTML"
hx-indicator="#tmp-cleanup-stats-wrapper">
<?= icon('trash') ?>
Supprimer
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<?php if ($fpActive > 0): ?>
<p style="margin:var(--space-sm) 0 0 0;font-size:0.85em;color:var(--text-secondary)">Conservés :
<?php if ($fpActive) echo $fpActive . ' téléversement(s) actif(s) (' . htmlspecialchars($d['filepond_active_human']) . '), '; ?>
<?php if ($trActive) echo $trActive . ' fichier(s) récent(s) (' . htmlspecialchars($d['trash_active_human']) . ')'; ?>
<?= $fpActive . ' téléversement(s) actif(s) (' . htmlspecialchars($d['filepond_active_human']) . ')' ?>
</p>
<?php endif; ?>