From 4131fc07e9bc972027374394e8d580fe37aa409d Mon Sep 17 00:00:00 2001 From: Pontoporeia Date: Mon, 23 Mar 2026 11:03:19 +0100 Subject: [PATCH] docs: add admin tag management UI task to TODO --- TODO.md | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index 27ce8b6..0d5f3bb 100644 --- a/TODO.md +++ b/TODO.md @@ -100,7 +100,99 @@ Goal: rename the tables and column to the canonical M2M pattern (`tags`, `thesis - [ ] `public/tfe.php`: `$data['keywords']` → `$data['tags']` (view column rename) - [ ] `templates/search-bar.php` (if applicable): update any hardcoded `keyword` param refs -### 5 — Tests +### 5 — Admin tag management UI (`/admin/tags.php`) + +The goal is a dedicated page for viewing, renaming, merging, and deleting tags, with +full referential-integrity awareness (no orphan `thesis_tags` rows, no broken search +results). + +#### 5a — `src/Database.php` — new tag-management methods + +- [ ] `getAllTagsWithCount(): array` — return all tags with a `thesis_count` column: + ```sql + SELECT t.id, t.name, + COUNT(tt.thesis_id) AS thesis_count + FROM tags t + LEFT JOIN thesis_tags tt ON t.id = tt.tag_id + GROUP BY t.id ORDER BY t.name + ``` +- [ ] `renameTag(int $id, string $newName): void` — UPDATE `tags SET name = ? WHERE id = ?`; + unique-constraint violation must be caught and re-thrown as a user-readable + `InvalidArgumentException` +- [ ] `mergeTag(int $sourceId, int $targetId): void` — within a transaction: + 1. INSERT OR IGNORE into `thesis_tags(tag_id, thesis_id)` for every row in + `thesis_tags WHERE tag_id = $sourceId` (re-point to target, skip dupes) + 2. DELETE FROM `thesis_tags WHERE tag_id = $sourceId` + 3. DELETE FROM `tags WHERE id = $sourceId` +- [ ] `deleteTag(int $id): void` — within a transaction: + DELETE FROM `thesis_tags WHERE tag_id = ?` first (FK cascade may handle this + after the schema migration, but an explicit delete is safer), then + DELETE FROM `tags WHERE id = ?`; reject with exception if `thesis_count > 0` + and the caller did not pass `$force = true` + +#### 5b — `public/admin/tags.php` — list + inline-edit view + +- [ ] Auth guard: `AdminAuth::requireLogin()` at top; CSRF token in session +- [ ] Page title: `"Gestion des mots-clés"` (reuses `$pageTitle` for `head.php`) +- [ ] Load `getAllTagsWithCount()` for display +- [ ] Table columns: **Mot-clé** (editable inline) · **Nb de TFE** · **Actions** +- [ ] Each row has: + - An inline `
` (POST to `actions/tag.php`, action=`rename`) pre-filled with + the current tag name, so the admin can edit in-place and submit per row + - A **Fusionner →** button that reveals a `