diff --git a/.gitignore b/.gitignore index b9eb6b5..52a29f2 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ Thumbs.db .idea/ /node_modules +*.db diff --git a/TODO.md b/TODO.md index 0eeda79..8f492c4 100644 --- a/TODO.md +++ b/TODO.md @@ -1,35 +1,3 @@ -# Posterg TODO - -## Fixes -- [x] Replace `mb_strtolower` with `strtolower` in admin/index.php (mbstring not available in php8.4-fpm) -- [x] Replace `mb_strlen`/`mb_substr` with `strlen`/`substr` in student-preview.php (same root cause) -- [x] Add `objet` column migration (production DB missing column → SQLSTATE[HY000]: table theses has no column named objet) - -## Logging -- [x] `AppLogger` — structured JSON logger at `storage/logs/form-submissions.log` -- [x] Admin formulaire: log submissions (success + error, IP, UA, author, post keys) -- [x] Partage form: log submissions (success + error, share slug, IP, UA, post keys) - -## Migrations -- [x] Migration runner (`app/migrations/run.php`) with tracking table `_migrations` -- [x] `001_add_objet_column.sql` (handles duplicate-column gracefully) - -## Features -- [x] Student name popover preview in /repertoire (zero per-hover requests) - - [x] `Database::getThesesByAuthorName()` query - - [x] `SearchController::handleStudentPreview()` HTMX endpoint - - [x] `/repertoire/student-preview` route in Dispatcher - - [x] `partials/student-preview.php` — iframe (single) or link list (multiple) - - [x] Updated `repertoire-index.php` — htmx hover attrs, `$studentWorks` map - - [x] Popover container + JS position/hide logic in `repertoire.php` - - [x] CSS in `repertoire.css` - -## File naming -- [x] Analyse current file saving in admin/add.php and partage/index.php -- [x] Implement author slug generation (`generateAuthorSlug`) -- [x] Modify `handleThesisFiles`: folder = `theses/{year}/{year}_{AUTHOR_NAME}/` -- [x] Modify `handleThesisFiles`: filename = `AUTHOR_NAME_sanitized_original.ext` -- [x] Ensure uniqueness within same year/author (suffix `_1`, `_2`, etc.) -- [x] Database path storage updated automatically via `insertThesisFile` -- [ ] Test with actual uploads -- [ ] Consider same changes for `handleCoverUpload` and `handleBannerUpload` +[ ] Describe commit +[ ] Squash/clean up if needed +[x] Commit and finalize diff --git a/app/src/Database.php b/app/src/Database.php index b4152f0..686edfa 100644 --- a/app/src/Database.php +++ b/app/src/Database.php @@ -1524,11 +1524,22 @@ class Database { * number. Must be called inside the same transaction that performs the INSERT so that * concurrent requests cannot produce duplicate identifiers. */ + /** + * Generate a unique identifier like "2025-003" for a new thesis. + * + * Uses the actual maximum sequence number for the given year (from + * existing identifiers) rather than the row count, so deletes don't + * cause identifier collisions. + * + * Must be called inside an open transaction. + */ public function generateThesisIdentifier(int $year): string { - $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM theses WHERE year = ?"); - $stmt->execute([$year]); - $count = (int)$stmt->fetchColumn() + 1; - return sprintf("%d-%03d", $year, $count); + $stmt = $this->pdo->prepare( + "SELECT COALESCE(MAX(CAST(SUBSTR(identifier, 6) AS INTEGER)), 0) FROM theses WHERE identifier LIKE ?" + ); + $stmt->execute([$year . '-%']); + $maxSeq = (int)$stmt->fetchColumn(); + return sprintf("%d-%03d", $year, $maxSeq + 1); } /** diff --git a/app/storage/posterg.db b/app/storage/posterg.db deleted file mode 100644 index 0c5c542..0000000 Binary files a/app/storage/posterg.db and /dev/null differ diff --git a/app/storage/test.db b/app/storage/test.db deleted file mode 100644 index 9a05446..0000000 Binary files a/app/storage/test.db and /dev/null differ