diff --git a/TODO.md b/TODO.md index 383ed99..862809e 100644 --- a/TODO.md +++ b/TODO.md @@ -69,3 +69,11 @@ - [x] Mots-clés: interactive tag search with HTMX suggestions, pill display, round bin-icon remove buttons - [x] Mots-clés: lowercase enforcement, deduplication, absolute dropdown, keyboard arrows/enter/escape, blur hide, spacing + counter above input, CSV import lowercased, space-collapse normalization, minimum 3 keywords required - [x] ErrorHandler: shared static helper for structured error_log + user-friendly messages with precise FK field extraction from SQLite errors. Applied to 12 action files + 6 public controllers + 2 form controllers + partage. Covers FK, UNIQUE, NOT NULL constraint types. +- [x] Fix: findOrCreateAuthor cannot clear email (empty string skips update, leaves old email) +- [ ] Fix: "NON" stored as literal email string in authors table (CSV import or old data) +- [x] Fix: contact_interne field in edit form never saved — removed dead field from form and dead validation from create controller +- [x] Fix: formulaire.php unconditionally suppresses display_errors even in dev mode +- [x] Fix: access_type_id radio has no "none" option — added "— Non défini" radio for admin mode +- [x] Fix: radio button checked detection broken (int vs string strict comparison in fieldset-licence-explanation.php) +- [x] Fix: htmlspecialchars(null) crash in old() on admin/add.php and admin/edit.php (null values in form data) +- [x] Fix: jury-fieldset.php old() return type confusion (array vs string) for jury_lecteur:_interne:_externe keys diff --git a/app/public/admin/actions/formulaire.php b/app/public/admin/actions/formulaire.php index 614567e..4fd1e71 100644 --- a/app/public/admin/actions/formulaire.php +++ b/app/public/admin/actions/formulaire.php @@ -3,9 +3,12 @@ require_once __DIR__ . '/../../../bootstrap.php'; require_once __DIR__ . '/../../../src/AdminAuth.php'; -ini_set('display_errors', 0); -ini_set('log_errors', 1); -ini_set('error_log', APP_ROOT . '/../error.log'); +// Only suppress display_errors in production (cli-server = dev mode). +if (php_sapi_name() !== 'cli-server') { + ini_set('display_errors', 0); + ini_set('log_errors', 1); + ini_set('error_log', APP_ROOT . '/../error.log'); +} AdminAuth::requireLogin(); diff --git a/app/public/admin/add.php b/app/public/admin/add.php index 1d3085e..96232bb 100644 --- a/app/public/admin/add.php +++ b/app/public/admin/add.php @@ -41,7 +41,8 @@ function old($key, $default = "") { global $formData; if (!isset($formData[$key])) return $default; if (is_array($formData[$key])) return $formData[$key]; // Return raw array for callers that handle it - return htmlspecialchars($formData[$key]); + if ($formData[$key] === null) return $default; + return htmlspecialchars((string)$formData[$key]); } function wasSelected($key, $value) { diff --git a/app/public/admin/edit.php b/app/public/admin/edit.php index d08f5f5..9326cbf 100644 --- a/app/public/admin/edit.php +++ b/app/public/admin/edit.php @@ -25,7 +25,8 @@ function old($key, $default = "") { global $formData; if (!isset($formData[$key])) return $default; if (is_array($formData[$key])) return $formData[$key]; // Return raw array for callers that handle it - return htmlspecialchars($formData[$key]); + if ($formData[$key] === null) return $default; + return htmlspecialchars((string)$formData[$key]); } try { diff --git a/app/src/Controllers/ThesisCreateController.php b/app/src/Controllers/ThesisCreateController.php index a7d783c..862c9ba 100644 --- a/app/src/Controllers/ThesisCreateController.php +++ b/app/src/Controllers/ThesisCreateController.php @@ -507,15 +507,6 @@ class ThesisCreateController } } - // Contact interne (optional, admin-only) - $contactInterne = trim($post['contact_interne'] ?? ''); - if ($contactInterne !== '') { - $contactInterne = filter_var($contactInterne, FILTER_VALIDATE_EMAIL); - if ($contactInterne === false) { - throw new Exception("L'adresse de contact interne n'est pas valide."); - } - } - // Note contextuelle (optional, max 1500 chars) $contextNote = $this->sanitiseString($post['context_note'] ?? ''); if (strlen($contextNote) > 1500) { @@ -539,7 +530,6 @@ class ThesisCreateController 'authorNames', 'mail', 'showContact', - 'contactInterne', 'annee', 'orientationId', 'apProgramId', diff --git a/app/src/Database.php b/app/src/Database.php index 0fb665d..cf76e62 100644 --- a/app/src/Database.php +++ b/app/src/Database.php @@ -959,13 +959,9 @@ class Database $author = $stmt->fetch(); if ($author) { - if ($email && $email !== '') { - $updateStmt = $this->pdo->prepare('UPDATE authors SET email = ?, show_contact = ? WHERE id = ?'); - $updateStmt->execute([$email, $showContact ? 1 : 0, $author['id']]); - } else { - $updateStmt = $this->pdo->prepare('UPDATE authors SET show_contact = ? WHERE id = ?'); - $updateStmt->execute([$showContact ? 1 : 0, $author['id']]); - } + // Always update email (may be null to clear) and show_contact. + $updateStmt = $this->pdo->prepare('UPDATE authors SET email = ?, show_contact = ? WHERE id = ?'); + $updateStmt->execute([$email && $email !== '' ? $email : null, $showContact ? 1 : 0, $author['id']]); return $author['id']; } diff --git a/app/templates/admin/acces.php b/app/templates/admin/acces.php index 076e0b8..56375d9 100644 --- a/app/templates/admin/acces.php +++ b/app/templates/admin/acces.php @@ -61,6 +61,19 @@ +%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision) +\\\\\\\ to: szktqmnn 29b3397f "Error tests, FK violations fix" (rebased revision) ++ $linkName = $link['name'] ?? ''; +++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : ''; +%%%%%%%%%%%%%%% diff from: szktqmnn 29b3397f "Error tests, FK violations fix" (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: vpwuyvyv 1573e164 "Fix: email clearing in findOrCreateAuthor, htmlspecialchars(null) crash in old(), dead contact_interne field, access_type_id radio clearing" (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: vpwuyvyv f513921d "Fix: email clearing in findOrCreateAuthor, htmlspecialchars(null) crash in old(), dead contact_interne field, access_type_id radio clearing" (rebased revision) +++ $linkName = $link['name'] ?? ''; ++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : ''; ?>
J'autorise l'erg à archiver mon TFE de la manière suivante :
- + + + +