fix: validation error messages hidden by generic fallback in ErrorHandler::userMessage

ErrorHandler::userMessage only handled RuntimeException, but all validation
throws in ThesisCreateController and ThesisEditController use plain Exception.
This caused user-friendly messages like 'Le champ Nom/Prénom/Pseudo est requis'
to fall through to the 'Une erreur inattendue est survenue…' generic message.

Fix: add Exception check (after PDOException, since PDOException extends it)
so all validation exceptions pass their message through.
This commit is contained in:
Pontoporeia
2026-05-11 17:03:22 +02:00
parent c3f6e8a033
commit df12af8423
6 changed files with 22 additions and 7 deletions

View File

@@ -41,6 +41,8 @@
- [x] **Migration idempotency**`CREATE INDEX` / `CREATE TRIGGER` / `CREATE VIEW` now use `IF NOT EXISTS` in schema.sql and generate-schema.py; migrate.sh no longer fails on re-run
- [ ] **Database readonly** — intermittent permission issue after deploy (added deploy-nginx recipe; permissions should be fixed by --chown + deploy-server.sh)
- [x] **Upload progress bar not visible**`collectFileNames()` now also checks FilePond instances directly (not just `input.files`); `upload-progress.php` no longer requires admin auth (blocked partage form polling)
- [x] **Validation error messages hidden by generic fallback**`ErrorHandler::userMessage` doesn't handle plain `Exception`, so all `throw new Exception(...)` validation messages fall through to "Une erreur inattendue…". Fix: add `Exception` pass-through before the generic fallback.
- [x] **Validation messages use wrong field names** — "Nom/Prénom/Pseudo" → "Auteur·ice(s)", "Titre du mémoire" → "Titre du TFE" to match form labels. Updated autofocusFieldForError in both controllers.
## PeerTube Alternate Labels & FilePond Pools

View File

@@ -231,10 +231,10 @@ class ThesisCreateController
*/
public static function autofocusFieldForError(string $message): ?string
{
if (str_contains($message, 'Nom/Prénom/Pseudo')) {
if (str_contains($message, "Auteur·ice")) {
return 'auteurice';
}
if (str_contains($message, 'Titre du mémoire')) {
if (str_contains($message, 'Titre du TFE')) {
return 'titre';
}
if (str_contains($message, 'Synopsis')) {
@@ -302,7 +302,7 @@ class ThesisCreateController
sort($authorNames, SORT_NATURAL);
}
if (empty($authorNames)) {
throw new Exception("Le champ 'Nom/Prénom/Pseudo' est requis.");
throw new Exception("Le champ 'Auteur·ice(s)' est requis.");
}
// contact_interne (backoffice) takes precedence over mail (tfe-info fieldset)
@@ -339,7 +339,7 @@ class ThesisCreateController
throw new Exception('Veuillez sélectionner une finalité.');
}
$titre = $this->validateRequired($this->sanitiseString($post['titre'] ?? ''), 'Titre du mémoire');
$titre = $this->validateRequired($this->sanitiseString($post['titre'] ?? ''), 'Titre du TFE');
$subtitle = $this->sanitiseString($post['subtitle'] ?? '');
$synopsis = $this->validateRequired($this->sanitiseString($post['synopsis'] ?? ''), 'Synopsis');

View File

@@ -171,7 +171,7 @@ class ThesisEditController
$errors = [];
$titre = trim($post['titre'] ?? '');
if ($titre === '') {
$errors[] = 'Le titre est requis.';
$errors[] = 'Le titre du TFE est requis.';
}
$auteurice = trim($post['auteurice'] ?? '');
if ($auteurice === '') {

View File

@@ -70,9 +70,9 @@ class ErrorHandler
return self::pdoMessage($e);
}
// ── Validation errors (RuntimeException, InvalidArgumentException) ──
// ── Validation errors (Exception, RuntimeException) ──────────────
// These are thrown with user-friendly French messages — pass through.
if ($e instanceof \RuntimeException) {
if ($e instanceof \Exception) {
return $e->getMessage();
}

View File

@@ -1416,6 +1416,19 @@
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\ to: tqymlyml 4edc02cb "fix: upload progress bar not visible — collectFileNames checks FilePond instances; remove admin auth from progress poll endpoint" (rebased revision)
++ $linkName = $link['name'] ?? '';
++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: tqymlyml 4edc02cb "fix: upload progress bar not visible — collectFileNames checks FilePond instances; remove admin auth from progress poll endpoint" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
- $linkName = $link['name'] ?? '';
- $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ to: osltsstu 02038f35 "fix: validation error messages hidden by generic fallback in ErrorHandler::userMessage" (rebased revision)
$linkName = $link['name'] ?? '';
$linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
$linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\ to: osltsstu c8c1516d "fix: validation error messages hidden by generic fallback in ErrorHandler::userMessage" (rebased revision)
++ $linkName = $link['name'] ?? '';
++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
?>
<tr class="admin-table-row" onclick="event.stopPropagation(); window.open('/partage/<?= urlencode($link['slug']) ?>', '_blank')" style="cursor:pointer">