feat: fix file deletion on save + trash policy + documents/ prefix + relink browser

1. note_intention: Delete old file only when a genuinely new upload arrives
   (32-char hex file_id), not when the FilePond pool preserves an existing
   file by sending its DB integer ID.  Previously the DB integer ID
   triggered $hasNewNote=true, which deleted the existing note_intention
   from disk+DB, then handleFilePondSingleFile couldn't re-process it
   because the regex requires a hex pattern.  Same fix applied to cover.

2. All file deletions now use deleteThesisFileToTrash() which renames
   files to tmp/_trash/ instead of unlinking.  The trash preserves
   original filenames prefixed with DB id for traceability.  Skips
   website URLs and PeerTube refs (no disk file).

3. Storage prefix changed from theses/ to documents/ to reflect that
   the folder holds all document types (determined by file_type in DB).
   MediaController visibility gate supports both prefixes for backward
   compat with existing files.

4. File browser + relink feature for orphaned files:
   - /admin/fragments/file-browser.php — HTMX tree browser for
     storage/documents/ and storage/theses/
   - /admin/actions/filepond/relink.php — POST endpoint that inserts
     a thesis_files row pointing to existing on-disk file
   - Per-pool "📂 Relier" buttons (edit mode only)
   - JS: XamxamOpenFileBrowser / XamxamRelinkFile with FilePond integration
   - CSS: .relink-modal dialog + .file-browser tree styles
This commit is contained in:
Pontoporeia
2026-05-13 14:58:15 +02:00
parent 6f7a02244f
commit 79eddf5d5a
30 changed files with 191580 additions and 187 deletions

View File

@@ -52,3 +52,5 @@
{"source":"admin","action":"submit","status":"error","error":"Le champ 'Auteur·ice(s)' est requis.","author":"","post_keys":["progress_token","csrf_token","titre","subtitle","auteurice","mail","synopsis","language_search_q","tag_search_q","année","orientation","ap","finality","jury_promoteur","jury_promoteur_ulb_name","jury_lecteur_interne","jury_lecteur_externe","admin_mode","edit_mode","has_annexes","website_url","access_type_id","context_note","jury_points","remarks","lien","contact_interne","go"],"timestamp":"2026-05-11T15:09:54+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0"}
{"source":"admin","action":"submit","status":"error","error":"Année invalide. Veuillez entrer une année valide.","author":"dqlskjflkjdsqf","post_keys":["progress_token","csrf_token","titre","subtitle","auteurice","mail","synopsis","language_search_q","tag_search_q","année","orientation","ap","finality","jury_promoteur","jury_promoteur_ulb_name","jury_lecteur_interne","jury_lecteur_externe","admin_mode","edit_mode","has_annexes","website_url","access_type_id","context_note","jury_points","remarks","lien","contact_interne","go"],"timestamp":"2026-05-11T15:10:00+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0"}
{"source":"partage","action":"submit","status":"success","thesis_id":1122,"identifier":"2025-074","author":"Théo Marchand","share_slug":"20260509-6UWYB2ZJ","timestamp":"2026-05-12T10:30:46+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0"}
{"source":"partage","action":"submit","status":"error","error":"SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: authors.email","share_slug":"20260512-HRO5QB4O","author":"Lila Dubois, Karim Nassar","post_keys":["filepond_mode","share_link_token","objet","titre","subtitle","auteurice","mail","synopsis","languages","language_autre","language_search_q","tag","tag_search_q","année","orientation","ap","finality","jury_promoteur","jury_promoteur_ulb_name","jury_lecteur_interne","jury_lecteur_externe","admin_mode","edit_mode","formats","queue_file","has_annexes","website_url","access_type_id","confirmation_email","go"],"timestamp":"2026-05-13T13:41:58+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0"}
{"source":"partage","action":"submit","status":"error","error":"SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: authors.email","share_slug":"20260512-HRO5QB4O","author":"Lila Dubois, Karim Nassar","post_keys":["filepond_mode","share_link_token","objet","titre","subtitle","auteurice","mail","synopsis","languages","language_search_q","tag","tag_search_q","année","orientation","ap","finality","jury_promoteur","jury_promoteur_ulb_name","jury_lecteur_interne","jury_lecteur_externe","admin_mode","edit_mode","formats","queue_file","has_annexes","website_url","access_type_id","confirmation_email","go"],"timestamp":"2026-05-13T13:43:56+00:00","ip":"127.0.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0"}