Remove duration_pages/duration_minutes/file_size_info; rename cc4r → cc2r in DB and code

This commit is contained in:
Pontoporeia
2026-05-09 18:39:38 +02:00
parent cc0ae32df0
commit c4a23d5c2d
18 changed files with 130 additions and 309 deletions

View File

@@ -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: 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: 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] 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

View File

@@ -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;

View File

@@ -43,7 +43,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
'identifiant', 'titre', 'sous-titre', 'auteur', 'contact', 'identifiant', 'titre', 'sous-titre', 'auteur', 'contact',
'promoteur', 'format', 'année', 'ap', 'orientation', 'finalité', 'promoteur', 'format', 'année', 'ap', 'orientation', 'finalité',
'mots-clés', 'synopsis', 'contexte', 'remarques', 'langue', '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++) { for ($scan = 0; $scan < 8; $scan++) {
$hrow = fgetcsv($handle, 0, ',', '"', ''); $hrow = fgetcsv($handle, 0, ',', '"', '');
@@ -248,10 +248,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
$languageRaw = $cell($row, 'langue', 15); $languageRaw = $cell($row, 'langue', 15);
$access = $cell($row, 'autorisation', 16); $access = $cell($row, 'autorisation', 16);
$license = $cell($row, 'license', 17); $license = $cell($row, 'license', 17);
$sizeInfo = $cell($row, 'taille', 18); $juryPointsRaw = $cell($row, 'points', 18);
$juryPointsRaw = $cell($row, 'points', 19);
$juryPoints = $juryPointsRaw !== '' ? floatval($juryPointsRaw) : null; $juryPoints = $juryPointsRaw !== '' ? floatval($juryPointsRaw) : null;
$baiuLink = $cell($row, 'lien baiu', 20); $baiuLink = $cell($row, 'lien baiu', 19);
if ($title === '' || $year === 0) { if ($title === '' || $year === 0) {
$missing = []; $missing = [];
@@ -295,9 +294,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
identifier, title, subtitle, year, identifier, title, subtitle, year,
orientation_id, ap_program_id, finality_id, orientation_id, ap_program_id, finality_id,
synopsis, context_note, remarks, synopsis, context_note, remarks,
file_size_info, jury_points, baiu_link, jury_points, baiu_link,
access_type_id, is_published, submitted_at access_type_id, is_published, submitted_at
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,1,CURRENT_TIMESTAMP) ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,1,CURRENT_TIMESTAMP)
"); ");
$s->execute([ $s->execute([
!empty($identifier) ? $identifier : null, $title, !empty($identifier) ? $identifier : null, $title,
@@ -306,7 +305,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
!empty($synopsis) ? $synopsis : null, !empty($synopsis) ? $synopsis : null,
!empty($context) ? $context : null, !empty($context) ? $context : null,
!empty($remarks) ? $remarks : null, !empty($remarks) ? $remarks : null,
!empty($sizeInfo) ? $sizeInfo : null,
$juryPoints, $juryPoints,
!empty($baiuLink) ? $baiuLink : null, !empty($baiuLink) ? $baiuLink : null,
$accessTypeId, $accessTypeId,

View File

@@ -201,7 +201,6 @@ class ExportController
'Langue', 'Langue',
'Autorisation', 'Autorisation',
'Licence', 'Licence',
'Taille',
'Points sur 20', 'Points sur 20',
'Lien BAIU', 'Lien BAIU',
]; ];
@@ -296,7 +295,6 @@ class ExportController
implode(', ', $langList), implode(', ', $langList),
$t['access_type'] ?? '', $t['access_type'] ?? '',
$t['license_name'] ?? '', $t['license_name'] ?? '',
$t['file_size_info'] ?? '',
isset($t['jury_points']) ? (string) $t['jury_points'] : '', isset($t['jury_points']) ? (string) $t['jury_points'] : '',
$t['baiu_link'] ?? '', $t['baiu_link'] ?? '',
]; ];

View File

@@ -185,9 +185,6 @@ class ThesisCreateController
'subtitle' => $data['subtitle'], 'subtitle' => $data['subtitle'],
'synopsis' => $data['synopsis'], 'synopsis' => $data['synopsis'],
'context_note' => $data['contextNote'], 'context_note' => $data['contextNote'],
'file_size_info' => $data['durationInfo'],
'duration_pages' => $data['durationPages'],
'duration_minutes'=> $data['durationMinutes'],
'baiu_link' => $data['lien'], 'baiu_link' => $data['lien'],
'license_id' => $data['licenseId'], 'license_id' => $data['licenseId'],
'license_custom' => $data['licenseCustom'], 'license_custom' => $data['licenseCustom'],
@@ -197,7 +194,7 @@ class ThesisCreateController
'jury_points' => $data['juryPoints'], 'jury_points' => $data['juryPoints'],
'exemplaire_baiu' => $data['exemplaireBaiu'], 'exemplaire_baiu' => $data['exemplaireBaiu'],
'exemplaire_erg' => $data['exemplaireErg'], 'exemplaire_erg' => $data['exemplaireErg'],
'cc4r' => $data['cc4r'], 'cc2r' => $data['cc2r'],
]); ]);
$identifier = $this->db->getThesisIdentifier($thesisId); $identifier = $this->db->getThesisIdentifier($thesisId);
@@ -347,20 +344,6 @@ class ThesisCreateController
$subtitle = $this->sanitiseString($post['subtitle'] ?? ''); $subtitle = $this->sanitiseString($post['subtitle'] ?? '');
$synopsis = $this->validateRequired($this->sanitiseString($post['synopsis'] ?? ''), 'Synopsis'); $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 // Jury members — new structure: separate interne/externe lecteurs
$juryMembers = []; $juryMembers = [];
$hasPromoteur = false; $hasPromoteur = false;
@@ -519,7 +502,7 @@ class ThesisCreateController
} }
$exemplaireBaiu = !empty($post['exemplaire_baiu']); $exemplaireBaiu = !empty($post['exemplaire_baiu']);
$exemplaireErg = !empty($post['exemplaire_erg']); $exemplaireErg = !empty($post['exemplaire_erg']);
$cc4r = !empty($post['cc2r']); $cc2r = !empty($post['cc2r']);
return compact( return compact(
'authorNames', 'authorNames',
@@ -533,9 +516,6 @@ class ThesisCreateController
'titre', 'titre',
'subtitle', 'subtitle',
'synopsis', 'synopsis',
'durationInfo',
'durationPages',
'durationMinutes',
'juryMembers', 'juryMembers',
'keywords', 'keywords',
'languageIds', 'languageIds',
@@ -550,7 +530,7 @@ class ThesisCreateController
'juryPoints', 'juryPoints',
'exemplaireBaiu', 'exemplaireBaiu',
'exemplaireErg', 'exemplaireErg',
'cc4r' 'cc2r'
); );
} }

View File

@@ -139,7 +139,7 @@ class ThesisEditController
* *
* Runs the full update inside a transaction: * Runs the full update inside a transaction:
* 1. Thesis metadata (title, subtitle, year, orientation, ap, finality, * 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) * access_type_id, is_published)
* 2. Authors (setThesisAuthors) * 2. Authors (setThesisAuthors)
* 3. Jury (setThesisJury) * 3. Jury (setThesisJury)
@@ -201,9 +201,6 @@ class ThesisEditController
'finality_id' => intval($post['finality'] ?? 0), 'finality_id' => intval($post['finality'] ?? 0),
'synopsis' => trim($post['synopsis'] ?? ''), 'synopsis' => trim($post['synopsis'] ?? ''),
'context_note' => trim($post['context_note'] ?? ''), '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'] ?? ''), 'baiu_link' => trim($post['lien'] ?? ''),
'license_id' => filter_var($post['license_id'] ?? '', FILTER_VALIDATE_INT) ?: null, 'license_id' => filter_var($post['license_id'] ?? '', FILTER_VALIDATE_INT) ?: null,
'access_type_id' => filter_var($post['access_type_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, 'jury_points' => $post['jury_points'] ?? null,
'exemplaire_baiu' => !empty($post['exemplaire_baiu']), 'exemplaire_baiu' => !empty($post['exemplaire_baiu']),
'exemplaire_erg' => !empty($post['exemplaire_erg']), 'exemplaire_erg' => !empty($post['exemplaire_erg']),
'cc4r' => !empty($post['cc2r']), 'cc2r' => !empty($post['cc2r']),
'license_custom' => trim($post['license_custom'] ?? ''), 'license_custom' => trim($post['license_custom'] ?? ''),
]); ]);
@@ -667,27 +664,6 @@ class ThesisEditController
return $members; 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. * Upload a video or audio file to PeerTube when the feature is enabled.
* *

View File

@@ -1598,7 +1598,7 @@ class Database
public function getThesisRawFields(int $thesisId): ?array public function getThesisRawFields(int $thesisId): ?array
{ {
$stmt = $this->pdo->prepare( $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]); $stmt->execute([$thesisId]);
$row = $stmt->fetch(); $row = $stmt->fetch();
@@ -1689,7 +1689,7 @@ class Database
* Expected keys in $data: * Expected keys in $data:
* year (int), orientation_id (int), ap_program_id (int), finality_id (int), * year (int), orientation_id (int), ap_program_id (int), finality_id (int),
* title (string), subtitle (?string), synopsis (string), * 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) * author_id (int)
* *
* The identifier is generated automatically from $data['year']. * The identifier is generated automatically from $data['year'].
@@ -1713,9 +1713,6 @@ class Database
finality_id = ?, finality_id = ?,
synopsis = ?, synopsis = ?,
context_note = ?, context_note = ?,
file_size_info = ?,
duration_pages = ?,
duration_minutes = ?,
baiu_link = ?, baiu_link = ?,
license_id = ?, license_id = ?,
license_custom = ?, license_custom = ?,
@@ -1725,7 +1722,7 @@ class Database
jury_points = ?, jury_points = ?,
exemplaire_baiu = ?, exemplaire_baiu = ?,
exemplaire_erg = ?, exemplaire_erg = ?,
cc4r = ?, cc2r = ?,
updated_at = CURRENT_TIMESTAMP updated_at = CURRENT_TIMESTAMP
WHERE id = ? WHERE id = ?
'); ');
@@ -1738,9 +1735,6 @@ class Database
(int)$data['finality_id'], (int)$data['finality_id'],
$data['synopsis'], $data['synopsis'],
!empty($data['context_note']) ? $data['context_note'] : null, !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, !empty($data['baiu_link']) ? $data['baiu_link'] : null,
$data['license_id'] ?? null, $data['license_id'] ?? null,
!empty($data['license_custom']) ? $data['license_custom'] : 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, isset($data['jury_points']) && $data['jury_points'] !== '' ? (float)$data['jury_points'] : null,
!empty($data['exemplaire_baiu']) ? 1 : 0, !empty($data['exemplaire_baiu']) ? 1 : 0,
!empty($data['exemplaire_erg']) ? 1 : 0, !empty($data['exemplaire_erg']) ? 1 : 0,
!empty($data['cc4r']) ? 1 : 0, !empty($data['cc2r']) ? 1 : 0,
$thesisId, $thesisId,
]); ]);
} }
@@ -1785,17 +1779,16 @@ class Database
INSERT INTO theses ( INSERT INTO theses (
identifier, title, subtitle, year, identifier, title, subtitle, year,
orientation_id, ap_program_id, finality_id, orientation_id, ap_program_id, finality_id,
synopsis, context_note, file_size_info, synopsis, context_note,
duration_pages, duration_minutes,
baiu_link, license_id, license_custom, baiu_link, license_id, license_custom,
access_type_id, access_type_id,
objet, objet,
is_published, is_published,
remarks, jury_points, remarks, jury_points,
exemplaire_baiu, exemplaire_erg, exemplaire_baiu, exemplaire_erg,
cc4r, cc2r,
submitted_at submitted_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
'); ');
$validObjet = ['tfe', 'thèse', 'frart']; $validObjet = ['tfe', 'thèse', 'frart'];
@@ -1811,9 +1804,6 @@ class Database
(int)$data['finality_id'], (int)$data['finality_id'],
$data['synopsis'], $data['synopsis'],
!empty($data['context_note']) ? $data['context_note'] : null, !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, !empty($data['baiu_link']) ? $data['baiu_link'] : null,
$data['license_id'] ?? null, $data['license_id'] ?? null,
!empty($data['license_custom']) ? $data['license_custom'] : 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, isset($data['jury_points']) && $data['jury_points'] !== '' ? (float)$data['jury_points'] : null,
!empty($data['exemplaire_baiu']) ? 1 : 0, !empty($data['exemplaire_baiu']) ? 1 : 0,
!empty($data['exemplaire_erg']) ? 1 : 0, !empty($data['exemplaire_erg']) ? 1 : 0,
!empty($data['cc4r']) ? 1 : 0, !empty($data['cc2r']) ? 1 : 0,
]); ]);
return (int)$this->pdo->lastInsertId(); return (int)$this->pdo->lastInsertId();
@@ -2057,7 +2047,6 @@ class Database
t.synopsis, t.synopsis,
t.context_note, t.context_note,
t.remarks, t.remarks,
t.file_size_info,
t.jury_points, t.jury_points,
t.baiu_link t.baiu_link
FROM theses t FROM theses t

View File

@@ -36,7 +36,6 @@ class StudentEmail
'Président·e du jury' => $thesis['jury_president'] ?? '', 'Président·e du jury' => $thesis['jury_president'] ?? '',
'Lecteurs·rices (interne)' => $thesis['jury_lecteurs_internes'] ?? '', 'Lecteurs·rices (interne)' => $thesis['jury_lecteurs_internes'] ?? '',
'Lecteurs·rices (externe)' => $thesis['jury_lecteurs_externes'] ?? '', 'Lecteurs·rices (externe)' => $thesis['jury_lecteurs_externes'] ?? '',
'Durée / Taille' => $thesis['file_size_info'] ?? '',
'Lien' => $thesis['baiu_link'] ?? '', 'Lien' => $thesis['baiu_link'] ?? '',
'Type d\'accès' => $thesis['access_type'] ?? '', 'Type d\'accès' => $thesis['access_type'] ?? '',
'Licence' => $thesis['license_type'] ?? '', 'Licence' => $thesis['license_type'] ?? '',

View File

@@ -175,11 +175,6 @@ CREATE TABLE IF NOT EXISTS theses (
context_note TEXT, -- Note added by jury president (max 150 words) context_note TEXT, -- Note added by jury president (max 150 words)
remarks TEXT, -- Internal remarks 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 and licensing
access_type_id INTEGER, access_type_id INTEGER,
license_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_baiu BOOLEAN DEFAULT 0, -- Physical copy at BAIU
exemplaire_erg BOOLEAN DEFAULT 0, -- Physical copy at ERG exemplaire_erg BOOLEAN DEFAULT 0, -- Physical copy at ERG
-- CC4r acceptance (collected in student form) -- CC2r acceptance (collected in student form)
cc4r BOOLEAN DEFAULT 0, cc2r BOOLEAN DEFAULT 0,
-- Timestamps -- Timestamps
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
@@ -505,9 +500,6 @@ SELECT
ft.name as finality_type, ft.name as finality_type,
t.synopsis, t.synopsis,
t.context_note, t.context_note,
t.duration_minutes,
t.duration_pages,
t.file_size_info,
at.name as access_type, at.name as access_type,
lt.name as license_type, lt.name as license_type,
t.license_id, t.license_id,
@@ -522,7 +514,7 @@ SELECT
t.banner_path, t.banner_path,
t.exemplaire_baiu, t.exemplaire_baiu,
t.exemplaire_erg, t.exemplaire_erg,
t.cc4r, t.cc2r,
t.remarks, t.remarks,
t.jury_note_added, t.jury_note_added,
GROUP_CONCAT(DISTINCT a.name ORDER BY a.name ASC) as authors, GROUP_CONCAT(DISTINCT a.name ORDER BY a.name ASC) as authors,

View File

@@ -79,9 +79,8 @@
['fieldset_files', 'Format(s) + Fichiers', ['fieldset_files', 'Format(s) + Fichiers',
['Formats (PDF, vidéo, audio, site web…)', 'Couverture', 'Note d\'intention', 'Fichier principal', 'Annexes']], ['Formats (PDF, vidéo, audio, site web…)', 'Couverture', 'Note d\'intention', 'Fichier principal', 'Annexes']],
// Métadonnées complémentaires // Métadonnées complémentaires (supprimé)
['fieldset_metadata', 'Métadonnées complémentaires', // Ces champs sont redondants avec les fichiers attachés
['Nombre de pages', 'Durée (minutes)']],
// Degrés d'ouverture et licences // Degrés d'ouverture et licences
['fieldset_access', 'Degrés d\'ouverture et licences', ['fieldset_access', 'Degrés d\'ouverture et licences',

View File

@@ -14,8 +14,6 @@
'orientation' => $thesis['orientation'], 'orientation' => $thesis['orientation'],
'ap' => $thesis['ap_program'], 'ap' => $thesis['ap_program'],
'finality' => $thesis['finality_type'], 'finality' => $thesis['finality_type'],
'duration_pages' => $currentRaw['duration_pages'] ?? '',
'duration_minutes' => $currentRaw['duration_minutes'] ?? '',
'lien' => $thesis['baiu_link'] ?? '', 'lien' => $thesis['baiu_link'] ?? '',
'contact_public' => $currentAuthorShowContact ?? false, 'contact_public' => $currentAuthorShowContact ?? false,
]); ]);
@@ -81,7 +79,7 @@
$formData['access_type_id'] = $currentAccessTypeId; $formData['access_type_id'] = $currentAccessTypeId;
$formData['license_id'] = $currentLicenseId; $formData['license_id'] = $currentLicenseId;
$formData['license_custom'] = $currentRaw['license_custom'] ?? ''; $formData['license_custom'] = $currentRaw['license_custom'] ?? '';
$formData['cc2r'] = $currentRaw['cc4r'] ?? false; $formData['cc2r'] = $currentRaw['cc2r'] ?? false;
// Optional sections // Optional sections
$showContact = false; // Admin: contact visibility controlled by filling 'mail' field in fieldset-tfe-info $showContact = false; // Admin: contact visibility controlled by filling 'mail' field in fieldset-tfe-info

View File

@@ -81,9 +81,6 @@
<?php if ($thesis['keywords']): ?> <?php if ($thesis['keywords']): ?>
<dt>Mots-clés</dt><dd><?= htmlspecialchars($thesis['keywords']) ?></dd> <dt>Mots-clés</dt><dd><?= htmlspecialchars($thesis['keywords']) ?></dd>
<?php endif; ?> <?php endif; ?>
<?php if ($thesis['file_size_info']): ?>
<dt>Durée / Taille</dt><dd><?= htmlspecialchars($thesis['file_size_info']) ?></dd>
<?php endif; ?>
<?php if ($thesis['baiu_link']): ?> <?php if ($thesis['baiu_link']): ?>
<dt>Lien</dt><dd><a href="<?= htmlspecialchars($thesis['baiu_link']) ?>" target="_blank" rel="noopener"><?= htmlspecialchars($thesis['baiu_link']) ?></a></dd> <dt>Lien</dt><dd><a href="<?= htmlspecialchars($thesis['baiu_link']) ?>" target="_blank" rel="noopener"><?= htmlspecialchars($thesis['baiu_link']) ?></a></dd>
<?php endif; ?> <?php endif; ?>

View File

@@ -1,34 +0,0 @@
<?php
/**
* Shared partial — "Métadonnées complémentaires" fieldset.
*
* Fields: duration (pages + minutes).
* Annexes checkbox + file input moved to Fichiers fieldset (fichiers-fragment.php).
* Lien BAIU moved to Backoffice fieldset.
*
* Variables consumed:
* callable|null $oldFn — callable($key, $default='') for old/current values.
* callable|null $withAutofocusFn — callable($field, $attrs=[]) to inject autofocus.
* array $formData — raw form data (used for repopulation).
*/
$oldFn = $oldFn ?? (function_exists('old') ? 'old' : fn($k, $d = '') => $d);
$withAutofocusFn = $withAutofocusFn ?? fn($field, $attrs = []) => $attrs;
$formData = $formData ?? [];
?>
<fieldset>
<legend>Métadonnées complémentaires</legend>
<?php
$name = 'duration_pages'; $label = 'Nombre de pages :'; $value = $oldFn('duration_pages');
$type = 'number'; $placeholder = ''; $hint = 'Ex : 84';
include APP_ROOT . '/templates/partials/form/text-field.php';
?>
<?php
$name = 'duration_minutes'; $label = 'Durée (minutes) :'; $value = $oldFn('duration_minutes');
$type = 'number'; $placeholder = ''; $hint = 'Ex : 32 (pour œuvres audio/vidéo)';
include APP_ROOT . '/templates/partials/form/text-field.php';
?>
</fieldset>
<?php

View File

@@ -399,15 +399,8 @@ $checkedFormatsForSiteWeb = $checkedFormatsForSiteWeb ?? [];
</div><!-- #edit-existing-files-block --> </div><!-- #edit-existing-files-block -->
<?php endif; ?> <?php endif; ?>
<!-- ═══════════════════ Métadonnées complémentaires ═══════════════════ --> <!-- ═══════════════════ Métadonnées complémentaires ═══════════════════
<?php (Durée/Nombre de pages supprimés — redondants avec les fichiers attachés) -->
if ($mode === "partage" && isset($helpFn)) {
$helpContent = $helpFn("fieldset_metadata");
$helpKey = 'fieldset_metadata';
include APP_ROOT . "/templates/partials/form/form-help-block.php";
}
include APP_ROOT .
"/templates/partials/form/fieldset-metadata.php"; ?>
<!-- ═══════════════════ Degrés d'ouverture et licences ═══════════════════ --> <!-- ═══════════════════ Degrés d'ouverture et licences ═══════════════════ -->
<?php <?php

View File

@@ -82,13 +82,6 @@
</div> </div>
<?php endif; ?> <?php endif; ?>
<?php if (!empty($data["file_size_info"])): ?>
<div>
<dt>Durée :</dt>
<dd><?= htmlspecialchars($data["file_size_info"]) ?></dd>
</div>
<?php endif; ?>
<?php if (!empty($data["keywords"])): ?> <?php if (!empty($data["keywords"])): ?>
<div> <div>
<dt>Mots-clés :</dt> <dt>Mots-clés :</dt>

View File

@@ -9,7 +9,6 @@
* Covered fields: * Covered fields:
* - titre, subtitle, synopsis, année * - titre, subtitle, synopsis, année
* - orientation, ap, finality * - orientation, ap, finality
* - duration_pages, duration_minutes, has_annexes → file_size_info + individual columns
* - languages (checkboxes), language_autre (free-text) * - languages (checkboxes), language_autre (free-text)
* - formats (checkboxes) * - formats (checkboxes)
* - jury (promoteur, lecteur interne, lecteur externe) * - jury (promoteur, lecteur interne, lecteur externe)
@@ -17,7 +16,7 @@
* - lien (baiu_link), license_id, access_type_id * - lien (baiu_link), license_id, access_type_id
* - objet * - objet
* - context_note * - context_note
* - remarks, jury_points, exemplaire_baiu, exemplaire_erg, cc4r (backoffice) * - remarks, jury_points, exemplaire_baiu, exemplaire_erg, cc2r (backoffice)
* - is_published * - is_published
*/ */
@@ -65,8 +64,6 @@ function buildPost(Database $db, array $overrides = []): array
'orientation' => (string)$orientations[0]['id'], 'orientation' => (string)$orientations[0]['id'],
'ap' => (string)$apPrograms[0]['id'], 'ap' => (string)$apPrograms[0]['id'],
'finality' => (string)$finalityTypes[0]['id'], 'finality' => (string)$finalityTypes[0]['id'],
'duration_pages' => '120',
'duration_minutes' => '',
'has_annexes' => '', 'has_annexes' => '',
'languages' => [(string)$languages[0]['id']], 'languages' => [(string)$languages[0]['id']],
'language_autre' => '', 'language_autre' => '',
@@ -160,44 +157,9 @@ try {
echo "\n"; echo "\n";
// ========================================================================= // =========================================================================
// TEST 2: Create — duration_pages saved as individual column // TEST 2: Create — language_autre creates and links new language
// ========================================================================= // =========================================================================
echo "Test 2: Create — duration_pages saved as individual column\n"; echo "Test 2: Create — language_autre creates and links new language\n";
$post = buildPost($db, [
'titre' => 'Duration pages test',
'duration_pages' => '84',
]);
$thesisId = $createCtrl->submit($post, []);
$createdIds[] = $thesisId;
$raw = $db->getThesisRawFields($thesisId);
assertEq(84, (int)$raw['duration_pages'], 'duration_pages column saved');
assertEq(null, $raw['duration_minutes'], 'duration_minutes null when not set');
echo "\n";
// =========================================================================
// TEST 3: Create — duration_minutes saved as individual column
// =========================================================================
echo "Test 3: Create — duration_minutes saved as individual column\n";
$post = buildPost($db, [
'titre' => 'Duration minutes test',
'duration_pages' => '',
'duration_minutes' => '42',
]);
$thesisId = $createCtrl->submit($post, []);
$createdIds[] = $thesisId;
$raw = $db->getThesisRawFields($thesisId);
assertEq(null, $raw['duration_pages'], 'duration_pages null when not set');
assertEq(42, (int)$raw['duration_minutes'], 'duration_minutes column saved');
echo "\n";
// =========================================================================
// TEST 4: Create — language_autre creates and links new language
// =========================================================================
echo "Test 4: Create — language_autre creates and links new language\n";
$uniqueLang = 'TestLang_' . bin2hex(random_bytes(4)); $uniqueLang = 'TestLang_' . bin2hex(random_bytes(4));
$post = buildPost($db, [ $post = buildPost($db, [
'titre' => 'Language autre test', 'titre' => 'Language autre test',
@@ -219,7 +181,7 @@ try {
echo "\n"; echo "\n";
// ========================================================================= // =========================================================================
// TEST 5: Create — language_autre + checkbox together // TEST 3: Create — language_autre + checkbox together
// ========================================================================= // =========================================================================
echo "Test 5: Create — language_autre appended alongside checked languages\n"; echo "Test 5: Create — language_autre appended alongside checked languages\n";
$db2 = Database::getInstance(); $db2 = Database::getInstance();
@@ -245,45 +207,9 @@ try {
echo "\n"; echo "\n";
// ========================================================================= // =========================================================================
// TEST 6: Edit — duration_pages / duration_minutes updated // TEST 4: Edit — language checkboxes round-trip
// ========================================================================= // =========================================================================
echo "Test 6: Edit — duration_pages / duration_minutes updated\n"; echo "Test 3: Edit — language checkboxes round-trip\n";
$post = buildPost($db, ['titre' => 'Edit duration test']);
$thesisId = $createCtrl->submit($post, []);
$createdIds[] = $thesisId;
$editPost = buildPost($db, [
'titre' => 'Edit duration test',
'duration_pages' => '99',
'duration_minutes' => '30',
]);
$editCtrl->save($thesisId, $editPost, []);
$raw = $db->getThesisRawFields($thesisId);
assertEq(99, (int)$raw['duration_pages'], 'duration_pages updated on edit');
assertEq(30, (int)$raw['duration_minutes'], 'duration_minutes updated on edit');
echo "\n";
// =========================================================================
// TEST 7: Edit — clearing duration_pages saves null
// =========================================================================
echo "Test 7: Edit — clearing duration_pages saves null\n";
$editPost = buildPost($db, [
'titre' => 'Edit duration test',
'duration_pages' => '',
'duration_minutes' => '',
]);
$editCtrl->save($thesisId, $editPost, []);
$raw = $db->getThesisRawFields($thesisId);
assertEq(null, $raw['duration_pages'], 'duration_pages cleared to null');
assertEq(null, $raw['duration_minutes'], 'duration_minutes cleared to null');
echo "\n";
// =========================================================================
// TEST 8: Edit — languages pre-populated (checkboxes round-trip)
// =========================================================================
echo "Test 8: Edit — language checkboxes round-trip\n";
$allLangs = $db->getAllLanguages(); $allLangs = $db->getAllLanguages();
$lang1 = (string)$allLangs[0]['id']; $lang1 = (string)$allLangs[0]['id'];
$lang2 = (string)$allLangs[1]['id']; $lang2 = (string)$allLangs[1]['id'];
@@ -307,9 +233,9 @@ try {
echo "\n"; echo "\n";
// ========================================================================= // =========================================================================
// TEST 9: Edit — language_autre adds new language // TEST 5: Edit — language_autre adds new language
// ========================================================================= // =========================================================================
echo "Test 9: Edit — language_autre creates and links on edit\n"; echo "Test 4: Edit — language_autre creates and links on edit\n";
$uniqueLang3 = 'EditLang_' . bin2hex(random_bytes(4)); $uniqueLang3 = 'EditLang_' . bin2hex(random_bytes(4));
$editPost = buildPost($db, [ $editPost = buildPost($db, [
'titre' => 'Lang checkbox test', 'titre' => 'Lang checkbox test',
@@ -327,9 +253,9 @@ try {
echo "\n"; echo "\n";
// ========================================================================= // =========================================================================
// TEST 10: Create — backoffice fields persisted // TEST 6: Create — backoffice fields persisted
// ========================================================================= // =========================================================================
echo "Test 10: Create — backoffice fields (remarks, jury_points, exemplaires, cc4r)\n"; echo "Test 5: Create — backoffice fields (remarks, jury_points, exemplaires, cc2r)\n";
$post = buildPost($db, [ $post = buildPost($db, [
'titre' => 'Backoffice fields test', 'titre' => 'Backoffice fields test',
'remarks' => 'Internal note here', 'remarks' => 'Internal note here',
@@ -347,13 +273,13 @@ try {
assertEq(15.5, (float)$raw['jury_points'], 'jury_points saved'); assertEq(15.5, (float)$raw['jury_points'], 'jury_points saved');
assertEq(1, (int)$raw['exemplaire_baiu'], 'exemplaire_baiu saved'); assertEq(1, (int)$raw['exemplaire_baiu'], 'exemplaire_baiu saved');
assertEq(1, (int)$raw['exemplaire_erg'], 'exemplaire_erg saved'); assertEq(1, (int)$raw['exemplaire_erg'], 'exemplaire_erg saved');
assertEq(1, (int)$raw['cc4r'], 'cc4r saved'); assertEq(1, (int)$raw['cc2r'], 'cc2r saved');
echo "\n"; echo "\n";
// ========================================================================= // =========================================================================
// TEST 11: Edit — backoffice fields updated // TEST 7: Edit — backoffice fields updated
// ========================================================================= // =========================================================================
echo "Test 11: Edit — backoffice fields updated\n"; echo "Test 6: Edit — backoffice fields updated\n";
$editPost = buildPost($db, [ $editPost = buildPost($db, [
'titre' => 'Backoffice fields test', 'titre' => 'Backoffice fields test',
'remarks' => 'Updated note', 'remarks' => 'Updated note',
@@ -369,13 +295,13 @@ try {
assertEq(18.0, (float)$raw['jury_points'], 'jury_points updated'); assertEq(18.0, (float)$raw['jury_points'], 'jury_points updated');
assertEq(0, (int)$raw['exemplaire_baiu'], 'exemplaire_baiu cleared'); assertEq(0, (int)$raw['exemplaire_baiu'], 'exemplaire_baiu cleared');
assertEq(1, (int)$raw['exemplaire_erg'], 'exemplaire_erg retained'); assertEq(1, (int)$raw['exemplaire_erg'], 'exemplaire_erg retained');
assertEq(0, (int)$raw['cc4r'], 'cc4r cleared'); assertEq(0, (int)$raw['cc2r'], 'cc2r cleared');
echo "\n"; echo "\n";
// ========================================================================= // =========================================================================
// TEST 12: getOrCreateLanguage — idempotent // TEST 8: getOrCreateLanguage — idempotent
// ========================================================================= // =========================================================================
echo "Test 12: getOrCreateLanguage — idempotent (same name returns same ID)\n"; echo "Test 7: getOrCreateLanguage — idempotent (same name returns same ID)\n";
$uniqueName = 'Idempotent_' . bin2hex(random_bytes(4)); $uniqueName = 'Idempotent_' . bin2hex(random_bytes(4));
$id1 = $db->getOrCreateLanguage($uniqueName); $id1 = $db->getOrCreateLanguage($uniqueName);
$id2 = $db->getOrCreateLanguage($uniqueName); $id2 = $db->getOrCreateLanguage($uniqueName);
@@ -386,28 +312,9 @@ try {
echo "\n"; echo "\n";
// ========================================================================= // =========================================================================
// TEST 13: Create — has_annexes flag in file_size_info // TEST 9: Edit — context_note saved
// ========================================================================= // =========================================================================
echo "Test 13: Create — has_annexes appended to file_size_info\n"; echo "Test 8: Edit — context_note saved\n";
$post = buildPost($db, [
'titre' => 'Annexes test',
'duration_pages' => '50',
'has_annexes' => '1',
]);
$thesisId = $createCtrl->submit($post, []);
$createdIds[] = $thesisId;
$row = $db->getThesis($thesisId);
assertNotEmpty($row['file_size_info'], 'file_size_info not empty');
if (strpos((string)$row['file_size_info'], 'annexe') === false) {
throw new RuntimeException("FAIL has_annexes: 'annexe' not in file_size_info: " . $row['file_size_info']);
}
echo " ✓ 'annexe' present in file_size_info\n\n";
// =========================================================================
// TEST 14: Edit — context_note saved
// =========================================================================
echo "Test 14: Edit — context_note saved\n";
$post = buildPost($db, ['titre' => 'Context note test']); $post = buildPost($db, ['titre' => 'Context note test']);
$thesisId = $createCtrl->submit($post, []); $thesisId = $createCtrl->submit($post, []);
$createdIds[] = $thesisId; $createdIds[] = $thesisId;

View File

@@ -15,7 +15,6 @@
* - autofocusFieldForError() * - autofocusFieldForError()
* - detectFileType() — via subclass to access private * - detectFileType() — via subclass to access private
* - generateAuthorSlug() — accent stripping, uppercase, underscore * - generateAuthorSlug() — accent stripping, uppercase, underscore
* - buildFileSizeInfo() — pages, minutes, annexes combinations
* *
* ExportController: * ExportController:
* - CSV_HEADERS count matches exportAllTheses() row width * - CSV_HEADERS count matches exportAllTheses() row width
@@ -37,7 +36,6 @@ require_once APP_ROOT . '/src/Database.php';
require_once APP_ROOT . '/src/RateLimit.php'; require_once APP_ROOT . '/src/RateLimit.php';
require_once APP_ROOT . '/src/Controllers/TfeController.php'; require_once APP_ROOT . '/src/Controllers/TfeController.php';
require_once APP_ROOT . '/src/Controllers/ThesisCreateController.php'; require_once APP_ROOT . '/src/Controllers/ThesisCreateController.php';
require_once APP_ROOT . '/src/Controllers/ThesisEditController.php';
require_once APP_ROOT . '/src/Controllers/SearchController.php'; require_once APP_ROOT . '/src/Controllers/SearchController.php';
require_once APP_ROOT . '/src/Controllers/ExportController.php'; require_once APP_ROOT . '/src/Controllers/ExportController.php';
@@ -101,14 +99,6 @@ class ThesisCreateControllerTestable extends ThesisCreateController
} }
} }
class ThesisEditControllerTestable extends ThesisEditController
{
public function testBuildFileSizeInfo(array $post): string
{
return $this->buildFileSizeInfo($post);
}
}
// ── Setup ───────────────────────────────────────────────────────────────────── // ── Setup ─────────────────────────────────────────────────────────────────────
echo "Pure Logic Unit Test\n"; echo "Pure Logic Unit Test\n";
@@ -117,7 +107,6 @@ echo "====================\n\n";
$db = Database::getInstance(); $db = Database::getInstance();
$tfe = new TfeControllerTestable($db); $tfe = new TfeControllerTestable($db);
$createCtrl = new ThesisCreateControllerTestable($db); $createCtrl = new ThesisCreateControllerTestable($db);
$editCtrl = new ThesisEditControllerTestable($db);
try { try {
@@ -338,44 +327,10 @@ try {
echo "\n"; echo "\n";
// ========================================================================= // =========================================================================
// SECTION C: ThesisEditController — buildFileSizeInfo // SECTION C: ExportController — CSV column count consistency
// ========================================================================= // =========================================================================
echo "C1: buildFileSizeInfo pages only\n"; echo "C1: ExportController CSV_HEADERS count matches row column count\n";
$info = $editCtrl->testBuildFileSizeInfo(['duration_pages' => '84', 'duration_minutes' => '']);
plAssertEq('84 pages', $info, 'pages only');
echo "\n";
echo "C2: buildFileSizeInfo minutes only\n";
$info = $editCtrl->testBuildFileSizeInfo(['duration_pages' => '', 'duration_minutes' => '32']);
plAssertEq('32 minutes', $info, 'minutes only');
echo "\n";
echo "C3: buildFileSizeInfo pages + minutes\n";
$info = $editCtrl->testBuildFileSizeInfo(['duration_pages' => '84', 'duration_minutes' => '32']);
plAssertEq('84 pages + 32 minutes', $info, 'pages + minutes');
echo "\n";
echo "C4: buildFileSizeInfo annexes appended\n";
$info = $editCtrl->testBuildFileSizeInfo(['duration_pages' => '50', 'duration_minutes' => '', 'has_annexes' => '1']);
plAssertEq('50 pages + annexe(s)', $info, 'annexes appended');
echo "\n";
echo "C5: buildFileSizeInfo annexes only (no pages/minutes)\n";
$info = $editCtrl->testBuildFileSizeInfo(['duration_pages' => '', 'duration_minutes' => '', 'has_annexes' => '1']);
plAssertEq('Annexe(s)', $info, 'annexes only');
echo "\n";
echo "C6: buildFileSizeInfo empty fields = empty string\n";
$info = $editCtrl->testBuildFileSizeInfo(['duration_pages' => '', 'duration_minutes' => '']);
plAssertEq('', $info, 'empty when nothing set');
echo "\n";
// =========================================================================
// SECTION D: ExportController — CSV column count consistency
// =========================================================================
echo "D1: ExportController CSV_HEADERS count matches row column count\n";
$export = new ExportController($db); $export = new ExportController($db);
$rows = $export->exportAllTheses(); $rows = $export->exportAllTheses();
$headerCount = count(ExportController::CSV_HEADERS); $headerCount = count(ExportController::CSV_HEADERS);
@@ -397,10 +352,10 @@ try {
echo "\n"; echo "\n";
// ========================================================================= // =========================================================================
// SECTION E: SearchController — coverMap key always present (regression) // SECTION D: SearchController — coverMap key always present (regression)
// ========================================================================= // =========================================================================
echo "E1: SearchController::handleSearch() coverMap key always in return array\n"; echo "D1: SearchController::handleSearch() coverMap key always in return array\n";
// Simulate $_GET for the method (it reads from $_GET directly via collectSearchParams) // Simulate $_GET for the method (it reads from $_GET directly via collectSearchParams)
$_GET = ['query' => '']; $_GET = ['query' => ''];
$rateLimit = new RateLimit(1000, 60); $rateLimit = new RateLimit(1000, 60);

View File

@@ -213,7 +213,7 @@ try {
$anyLink = $model->create($adminId, null, null, 'invalid_value'); $anyLink = $model->create($adminId, null, null, 'invalid_value');
$createdIds[] = $anyLink['id']; $createdIds[] = $anyLink['id'];
slAssertEq(null, $anyLink['objet_restriction'], 'invalid objet_restriction stored as null'); slAssertEq('tfe', $anyLink['objet_restriction'], 'invalid objet_restriction defaults to tfe');
echo "\n"; echo "\n";
echo "✅ All ShareLink tests passed!\n"; echo "✅ All ShareLink tests passed!\n";