diff --git a/TODO.md b/TODO.md index 5a7b488..5bf5985 100644 --- a/TODO.md +++ b/TODO.md @@ -12,3 +12,5 @@ - [x] Fix: format checkbox toggle clears file inputs — split into two blocks: #format-fichiers-block (stable: TFE/annexes/couverture/note) and #format-extras-block (swappable: website/video/audio extras) - [x] Fix: remove website label/legend input — website section now shows only URL field - [x] Fix: format-extras not appearing — moved #format-extras-block inside Fichiers fieldset (after annexes), uses hx-select to extract from response +- [x] Remove duration_pages, duration_minutes, file_size_info entirely (form, schema, DB, views, controllers, tests, CSV export, email) +- [x] Rename cc4r → cc2r everywhere (DB column, schema, PHP code) to fix pre-existing naming inconsistency diff --git a/app/migrations/applied/024_remove_duration_size_fields.sql b/app/migrations/applied/024_remove_duration_size_fields.sql new file mode 100644 index 0000000..e3d4486 --- /dev/null +++ b/app/migrations/applied/024_remove_duration_size_fields.sql @@ -0,0 +1,79 @@ +-- 024_remove_duration_size_fields.sql +-- Supprime les colonnes et la vue obsolètes pour durée / taille (pages, minutes, file_size_info). +-- Ces données sont redondantes : les fichiers eux-mêmes contiennent l'information. + +-- Supprimer d'abord la vue qui référence ces colonnes +DROP VIEW IF EXISTS v_theses_full; +DROP VIEW IF EXISTS v_theses_public; + +-- Recréer les vues sans duration_minutes, duration_pages, file_size_info +CREATE VIEW IF NOT EXISTS v_theses_full AS +SELECT + t.id, + t.identifier, + t.title, + t.subtitle, + t.year, + t.is_doctoral, + t.objet, + o.name as orientation, + ap.name as ap_program, + ft.name as finality_type, + t.synopsis, + t.context_note, + at.name as access_type, + lt.name as license_type, + t.license_id, + t.license_custom, + t.access_type_id, + t.jury_points, + t.submitted_at, + t.defense_date, + t.published_at, + t.is_published, + t.baiu_link, + t.banner_path, + t.exemplaire_baiu, + t.exemplaire_erg, + t.cc2r, + t.remarks, + t.jury_note_added, + GROUP_CONCAT(DISTINCT a.name ORDER BY a.name ASC) as authors, + GROUP_CONCAT(DISTINCT s.name) as supervisors, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'president' THEN s.name END) as jury_president, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' AND ts.is_ulb = 0 THEN s.name END) as jury_promoteurs, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' AND ts.is_ulb = 1 THEN s.name END) as jury_promoteurs_ulb, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' AND ts.is_external = 0 THEN s.name END) as jury_lecteurs_internes, + GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' AND ts.is_external = 1 THEN s.name END) as jury_lecteurs_externes, + GROUP_CONCAT(DISTINCT l.name) as languages, + GROUP_CONCAT(DISTINCT fmt.name) as formats, + GROUP_CONCAT(DISTINCT tg.name) as keywords, + -- First author's email and contact-visibility flag + (SELECT a2.email FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as author_email, + (SELECT a2.show_contact FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as author_show_contact +FROM theses t +LEFT JOIN orientations o ON t.orientation_id = o.id +LEFT JOIN ap_programs ap ON t.ap_program_id = ap.id +LEFT JOIN finality_types ft ON t.finality_id = ft.id +LEFT JOIN access_types at ON t.access_type_id = at.id +LEFT JOIN license_types lt ON t.license_id = lt.id +LEFT JOIN thesis_authors ta ON t.id = ta.thesis_id +LEFT JOIN authors a ON ta.author_id = a.id +LEFT JOIN thesis_supervisors ts ON t.id = ts.thesis_id +LEFT JOIN supervisors s ON ts.supervisor_id = s.id +LEFT JOIN thesis_languages tl ON t.id = tl.thesis_id +LEFT JOIN languages l ON tl.language_id = l.id +LEFT JOIN thesis_formats tf ON t.id = tf.thesis_id +LEFT JOIN format_types fmt ON tf.format_id = fmt.id +LEFT JOIN thesis_tags tt ON t.id = tt.thesis_id +LEFT JOIN tags tg ON tt.tag_id = tg.id +GROUP BY t.id; + +CREATE VIEW IF NOT EXISTS v_theses_public AS +SELECT * FROM v_theses_full +WHERE is_published = 1; + +-- Supprimer les colonnes de la table +ALTER TABLE theses DROP COLUMN duration_minutes; +ALTER TABLE theses DROP COLUMN duration_pages; +ALTER TABLE theses DROP COLUMN file_size_info; diff --git a/app/public/admin/index.php b/app/public/admin/index.php index 074d97f..d5beebd 100644 --- a/app/public/admin/index.php +++ b/app/public/admin/index.php @@ -43,7 +43,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) { 'identifiant', 'titre', 'sous-titre', 'auteur', 'contact', 'promoteur', 'format', 'année', 'ap', 'orientation', 'finalité', 'mots-clés', 'synopsis', 'contexte', 'remarques', 'langue', - 'autorisation', 'licence', 'license', 'taille', 'points', 'lien baiu', + 'autorisation', 'licence', 'license', 'points', 'lien baiu', ]; for ($scan = 0; $scan < 8; $scan++) { $hrow = fgetcsv($handle, 0, ',', '"', ''); @@ -248,10 +248,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) { $languageRaw = $cell($row, 'langue', 15); $access = $cell($row, 'autorisation', 16); $license = $cell($row, 'license', 17); - $sizeInfo = $cell($row, 'taille', 18); - $juryPointsRaw = $cell($row, 'points', 19); + $juryPointsRaw = $cell($row, 'points', 18); $juryPoints = $juryPointsRaw !== '' ? floatval($juryPointsRaw) : null; - $baiuLink = $cell($row, 'lien baiu', 20); + $baiuLink = $cell($row, 'lien baiu', 19); if ($title === '' || $year === 0) { $missing = []; @@ -295,9 +294,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) { identifier, title, subtitle, year, orientation_id, ap_program_id, finality_id, synopsis, context_note, remarks, - file_size_info, jury_points, baiu_link, + jury_points, baiu_link, access_type_id, is_published, submitted_at - ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,1,CURRENT_TIMESTAMP) + ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,1,CURRENT_TIMESTAMP) "); $s->execute([ !empty($identifier) ? $identifier : null, $title, @@ -306,7 +305,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) { !empty($synopsis) ? $synopsis : null, !empty($context) ? $context : null, !empty($remarks) ? $remarks : null, - !empty($sizeInfo) ? $sizeInfo : null, $juryPoints, !empty($baiuLink) ? $baiuLink : null, $accessTypeId, diff --git a/app/src/Controllers/ExportController.php b/app/src/Controllers/ExportController.php index e27f1e1..6e5464b 100644 --- a/app/src/Controllers/ExportController.php +++ b/app/src/Controllers/ExportController.php @@ -201,7 +201,6 @@ class ExportController 'Langue', 'Autorisation', 'Licence', - 'Taille', 'Points sur 20', 'Lien BAIU', ]; @@ -296,7 +295,6 @@ class ExportController implode(', ', $langList), $t['access_type'] ?? '', $t['license_name'] ?? '', - $t['file_size_info'] ?? '', isset($t['jury_points']) ? (string) $t['jury_points'] : '', $t['baiu_link'] ?? '', ]; diff --git a/app/src/Controllers/ThesisCreateController.php b/app/src/Controllers/ThesisCreateController.php index 331dc77..4ccc2f3 100644 --- a/app/src/Controllers/ThesisCreateController.php +++ b/app/src/Controllers/ThesisCreateController.php @@ -185,9 +185,6 @@ class ThesisCreateController 'subtitle' => $data['subtitle'], 'synopsis' => $data['synopsis'], 'context_note' => $data['contextNote'], - 'file_size_info' => $data['durationInfo'], - 'duration_pages' => $data['durationPages'], - 'duration_minutes'=> $data['durationMinutes'], 'baiu_link' => $data['lien'], 'license_id' => $data['licenseId'], 'license_custom' => $data['licenseCustom'], @@ -197,7 +194,7 @@ class ThesisCreateController 'jury_points' => $data['juryPoints'], 'exemplaire_baiu' => $data['exemplaireBaiu'], 'exemplaire_erg' => $data['exemplaireErg'], - 'cc4r' => $data['cc4r'], + 'cc2r' => $data['cc2r'], ]); $identifier = $this->db->getThesisIdentifier($thesisId); @@ -347,20 +344,6 @@ class ThesisCreateController $subtitle = $this->sanitiseString($post['subtitle'] ?? ''); $synopsis = $this->validateRequired($this->sanitiseString($post['synopsis'] ?? ''), 'Synopsis'); - $durationPages = $this->sanitiseString($post['duration_pages'] ?? ''); - $durationMinutes = $this->sanitiseString($post['duration_minutes'] ?? ''); - $durationInfo = ''; - if ($durationPages !== '' && $durationMinutes !== '') { - $durationInfo = $durationPages . ' pages + ' . $durationMinutes . ' minutes'; - } elseif ($durationMinutes !== '') { - $durationInfo = $durationMinutes . ' minutes'; - } elseif ($durationPages !== '') { - $durationInfo = $durationPages . ' pages'; - } - if (!empty($post['has_annexes'])) { - $durationInfo = $durationInfo ? $durationInfo . ' + annexe(s)' : 'Annexe(s)'; - } - // Jury members — new structure: separate interne/externe lecteurs $juryMembers = []; $hasPromoteur = false; @@ -519,7 +502,7 @@ class ThesisCreateController } $exemplaireBaiu = !empty($post['exemplaire_baiu']); $exemplaireErg = !empty($post['exemplaire_erg']); - $cc4r = !empty($post['cc2r']); + $cc2r = !empty($post['cc2r']); return compact( 'authorNames', @@ -533,9 +516,6 @@ class ThesisCreateController 'titre', 'subtitle', 'synopsis', - 'durationInfo', - 'durationPages', - 'durationMinutes', 'juryMembers', 'keywords', 'languageIds', @@ -550,7 +530,7 @@ class ThesisCreateController 'juryPoints', 'exemplaireBaiu', 'exemplaireErg', - 'cc4r' + 'cc2r' ); } diff --git a/app/src/Controllers/ThesisEditController.php b/app/src/Controllers/ThesisEditController.php index 61dc769..178e56f 100644 --- a/app/src/Controllers/ThesisEditController.php +++ b/app/src/Controllers/ThesisEditController.php @@ -139,7 +139,7 @@ class ThesisEditController * * Runs the full update inside a transaction: * 1. Thesis metadata (title, subtitle, year, orientation, ap, finality, - * synopsis, context_note, file_size_info, baiu_link, license_id, + * synopsis, context_note, baiu_link, license_id, * access_type_id, is_published) * 2. Authors (setThesisAuthors) * 3. Jury (setThesisJury) @@ -201,9 +201,6 @@ class ThesisEditController 'finality_id' => intval($post['finality'] ?? 0), 'synopsis' => trim($post['synopsis'] ?? ''), 'context_note' => trim($post['context_note'] ?? ''), - 'file_size_info' => $this->buildFileSizeInfo($post), - 'duration_pages' => trim($post['duration_pages'] ?? ''), - 'duration_minutes'=> trim($post['duration_minutes'] ?? ''), 'baiu_link' => trim($post['lien'] ?? ''), 'license_id' => filter_var($post['license_id'] ?? '', FILTER_VALIDATE_INT) ?: null, 'access_type_id' => filter_var($post['access_type_id'] ?? '', FILTER_VALIDATE_INT) ?: null, @@ -212,7 +209,7 @@ class ThesisEditController 'jury_points' => $post['jury_points'] ?? null, 'exemplaire_baiu' => !empty($post['exemplaire_baiu']), 'exemplaire_erg' => !empty($post['exemplaire_erg']), - 'cc4r' => !empty($post['cc2r']), + 'cc2r' => !empty($post['cc2r']), 'license_custom' => trim($post['license_custom'] ?? ''), ]); @@ -667,27 +664,6 @@ class ThesisEditController return $members; } - /** - * Build file_size_info from separate duration fields. - */ - protected function buildFileSizeInfo(array $post): string - { - $pages = trim($post['duration_pages'] ?? ''); - $minutes = trim($post['duration_minutes'] ?? ''); - $info = ''; - if ($pages !== '' && $minutes !== '') { - $info = $pages . ' pages + ' . $minutes . ' minutes'; - } elseif ($minutes !== '') { - $info = $minutes . ' minutes'; - } elseif ($pages !== '') { - $info = $pages . ' pages'; - } - if (!empty($post['has_annexes'])) { - $info = $info ? $info . ' + annexe(s)' : 'Annexe(s)'; - } - return $info; - } - /** * Upload a video or audio file to PeerTube when the feature is enabled. * diff --git a/app/src/Database.php b/app/src/Database.php index 642d72f..955ffe7 100644 --- a/app/src/Database.php +++ b/app/src/Database.php @@ -1598,7 +1598,7 @@ class Database public function getThesisRawFields(int $thesisId): ?array { $stmt = $this->pdo->prepare( - 'SELECT license_id, license_custom, access_type_id, context_note, remarks, jury_points, exemplaire_baiu, exemplaire_erg, cc4r, duration_pages, duration_minutes FROM theses WHERE id = ? LIMIT 1' + 'SELECT license_id, license_custom, access_type_id, context_note, remarks, jury_points, exemplaire_baiu, exemplaire_erg, cc2r FROM theses WHERE id = ? LIMIT 1' ); $stmt->execute([$thesisId]); $row = $stmt->fetch(); @@ -1689,7 +1689,7 @@ class Database * Expected keys in $data: * year (int), orientation_id (int), ap_program_id (int), finality_id (int), * title (string), subtitle (?string), synopsis (string), - * file_size_info (?string), baiu_link (?string), license_id (?int), + * baiu_link (?string), license_id (?int), * author_id (int) * * The identifier is generated automatically from $data['year']. @@ -1713,9 +1713,6 @@ class Database finality_id = ?, synopsis = ?, context_note = ?, - file_size_info = ?, - duration_pages = ?, - duration_minutes = ?, baiu_link = ?, license_id = ?, license_custom = ?, @@ -1725,7 +1722,7 @@ class Database jury_points = ?, exemplaire_baiu = ?, exemplaire_erg = ?, - cc4r = ?, + cc2r = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? '); @@ -1738,9 +1735,6 @@ class Database (int)$data['finality_id'], $data['synopsis'], !empty($data['context_note']) ? $data['context_note'] : null, - !empty($data['file_size_info']) ? $data['file_size_info'] : null, - isset($data['duration_pages']) && $data['duration_pages'] !== '' ? (int)$data['duration_pages'] : null, - isset($data['duration_minutes']) && $data['duration_minutes'] !== '' ? (int)$data['duration_minutes'] : null, !empty($data['baiu_link']) ? $data['baiu_link'] : null, $data['license_id'] ?? null, !empty($data['license_custom']) ? $data['license_custom'] : null, @@ -1750,7 +1744,7 @@ class Database isset($data['jury_points']) && $data['jury_points'] !== '' ? (float)$data['jury_points'] : null, !empty($data['exemplaire_baiu']) ? 1 : 0, !empty($data['exemplaire_erg']) ? 1 : 0, - !empty($data['cc4r']) ? 1 : 0, + !empty($data['cc2r']) ? 1 : 0, $thesisId, ]); } @@ -1785,17 +1779,16 @@ class Database INSERT INTO theses ( identifier, title, subtitle, year, orientation_id, ap_program_id, finality_id, - synopsis, context_note, file_size_info, - duration_pages, duration_minutes, + synopsis, context_note, baiu_link, license_id, license_custom, access_type_id, objet, is_published, remarks, jury_points, exemplaire_baiu, exemplaire_erg, - cc4r, + cc2r, submitted_at - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) '); $validObjet = ['tfe', 'thèse', 'frart']; @@ -1811,9 +1804,6 @@ class Database (int)$data['finality_id'], $data['synopsis'], !empty($data['context_note']) ? $data['context_note'] : null, - !empty($data['file_size_info']) ? $data['file_size_info'] : null, - isset($data['duration_pages']) && $data['duration_pages'] !== '' ? (int)$data['duration_pages'] : null, - isset($data['duration_minutes']) && $data['duration_minutes'] !== '' ? (int)$data['duration_minutes'] : null, !empty($data['baiu_link']) ? $data['baiu_link'] : null, $data['license_id'] ?? null, !empty($data['license_custom']) ? $data['license_custom'] : null, @@ -1823,7 +1813,7 @@ class Database isset($data['jury_points']) && $data['jury_points'] !== '' ? (float)$data['jury_points'] : null, !empty($data['exemplaire_baiu']) ? 1 : 0, !empty($data['exemplaire_erg']) ? 1 : 0, - !empty($data['cc4r']) ? 1 : 0, + !empty($data['cc2r']) ? 1 : 0, ]); return (int)$this->pdo->lastInsertId(); @@ -2057,7 +2047,6 @@ class Database t.synopsis, t.context_note, t.remarks, - t.file_size_info, t.jury_points, t.baiu_link FROM theses t diff --git a/app/src/StudentEmail.php b/app/src/StudentEmail.php index f8969e9..7584be1 100644 --- a/app/src/StudentEmail.php +++ b/app/src/StudentEmail.php @@ -36,7 +36,6 @@ class StudentEmail 'Président·e du jury' => $thesis['jury_president'] ?? '', 'Lecteurs·rices (interne)' => $thesis['jury_lecteurs_internes'] ?? '', 'Lecteurs·rices (externe)' => $thesis['jury_lecteurs_externes'] ?? '', - 'Durée / Taille' => $thesis['file_size_info'] ?? '', 'Lien' => $thesis['baiu_link'] ?? '', 'Type d\'accès' => $thesis['access_type'] ?? '', 'Licence' => $thesis['license_type'] ?? '', diff --git a/app/storage/schema.sql b/app/storage/schema.sql index 3c06ab4..5ffd815 100644 --- a/app/storage/schema.sql +++ b/app/storage/schema.sql @@ -175,11 +175,6 @@ CREATE TABLE IF NOT EXISTS theses ( context_note TEXT, -- Note added by jury president (max 150 words) remarks TEXT, -- Internal remarks - -- Duration/size - duration_minutes INTEGER, -- For audio/video works - duration_pages INTEGER, -- For written works - file_size_info TEXT, -- e.g., "128 pages", "78 pages + ?? minutes" - -- Access and licensing access_type_id INTEGER, license_id INTEGER, @@ -205,8 +200,8 @@ CREATE TABLE IF NOT EXISTS theses ( exemplaire_baiu BOOLEAN DEFAULT 0, -- Physical copy at BAIU exemplaire_erg BOOLEAN DEFAULT 0, -- Physical copy at ERG - -- CC4r acceptance (collected in student form) - cc4r BOOLEAN DEFAULT 0, + -- CC2r acceptance (collected in student form) + cc2r BOOLEAN DEFAULT 0, -- Timestamps created_at DATETIME DEFAULT CURRENT_TIMESTAMP, @@ -505,9 +500,6 @@ SELECT ft.name as finality_type, t.synopsis, t.context_note, - t.duration_minutes, - t.duration_pages, - t.file_size_info, at.name as access_type, lt.name as license_type, t.license_id, @@ -522,7 +514,7 @@ SELECT t.banner_path, t.exemplaire_baiu, t.exemplaire_erg, - t.cc4r, + t.cc2r, t.remarks, t.jury_note_added, GROUP_CONCAT(DISTINCT a.name ORDER BY a.name ASC) as authors, diff --git a/app/templates/admin/contenus.php b/app/templates/admin/contenus.php index 55674c0..bb99acf 100644 --- a/app/templates/admin/contenus.php +++ b/app/templates/admin/contenus.php @@ -79,9 +79,8 @@ ['fieldset_files', 'Format(s) + Fichiers', ['Formats (PDF, vidéo, audio, site web…)', 'Couverture', 'Note d\'intention', 'Fichier principal', 'Annexes']], - // Métadonnées complémentaires - ['fieldset_metadata', 'Métadonnées complémentaires', - ['Nombre de pages', 'Durée (minutes)']], + // Métadonnées complémentaires (supprimé) + // Ces champs sont redondants avec les fichiers attachés // Degrés d'ouverture et licences ['fieldset_access', 'Degrés d\'ouverture et licences', diff --git a/app/templates/admin/edit.php b/app/templates/admin/edit.php index d9fc8e9..d3cd9e5 100644 --- a/app/templates/admin/edit.php +++ b/app/templates/admin/edit.php @@ -14,8 +14,6 @@ 'orientation' => $thesis['orientation'], 'ap' => $thesis['ap_program'], 'finality' => $thesis['finality_type'], - 'duration_pages' => $currentRaw['duration_pages'] ?? '', - 'duration_minutes' => $currentRaw['duration_minutes'] ?? '', 'lien' => $thesis['baiu_link'] ?? '', 'contact_public' => $currentAuthorShowContact ?? false, ]); @@ -81,7 +79,7 @@ $formData['access_type_id'] = $currentAccessTypeId; $formData['license_id'] = $currentLicenseId; $formData['license_custom'] = $currentRaw['license_custom'] ?? ''; - $formData['cc2r'] = $currentRaw['cc4r'] ?? false; + $formData['cc2r'] = $currentRaw['cc2r'] ?? false; // Optional sections $showContact = false; // Admin: contact visibility controlled by filling 'mail' field in fieldset-tfe-info diff --git a/app/templates/admin/recapitulatif.php b/app/templates/admin/recapitulatif.php index 69a828f..8878a06 100644 --- a/app/templates/admin/recapitulatif.php +++ b/app/templates/admin/recapitulatif.php @@ -81,9 +81,6 @@