refactor form structure per new spec + fix

- split jury into interne/externe/ULB,
- remove president from student form,
- add language_autre,
- split duration into pages+minutes+annexes,
- move licence to degrés d'ouverture with CC2r,
- add license_custom,
- filter PACS from student AP list,
- editable généralités help block,
- Libre toggle per settings

Fix:
- missing comma after cc4r column in schema.sql
- remove duplicate form footer from partage template
- remove couverture from student files fieldset; add promoteur ULB conditional disable via JS on Approfondi
- promoteur ULB: remove 'si applicable', make required when visible
This commit is contained in:
Pontoporeia
2026-05-07 19:43:43 +02:00
parent dce0e0b301
commit 24d68dda59
21 changed files with 694 additions and 381 deletions
+53 -16
View File
@@ -183,8 +183,9 @@ class ThesisCreateController
'synopsis' => $data['synopsis'],
'file_size_info' => $data['durationInfo'],
'baiu_link' => $data['lien'],
'license_id' => $data['licenseId'],
'access_type_id' => $data['accessTypeId'],
'license_id' => $data['licenseId'],
'license_custom' => $data['licenseCustom'],
'access_type_id' => $data['accessTypeId'],
'objet' => $data['objet'],
]);
@@ -310,31 +311,65 @@ class ThesisCreateController
$subtitle = $this->sanitiseString($post['subtitle'] ?? '');
$synopsis = $this->validateRequired($this->sanitiseString($post['synopsis'] ?? ''), 'Synopsis');
$durationInfo = $this->sanitiseString($post['duration_info'] ?? '');
// Jury members
$juryMembers = [];
if (!empty(trim($post['jury_president'] ?? ''))) {
$juryMembers[] = ['name' => trim($post['jury_president']), 'role' => 'president', 'is_external' => 0];
$durationInfo = $this->sanitiseString($post['duration_pages'] ?? '');
$durationMinutes = $this->sanitiseString($post['duration_minutes'] ?? '');
if ($durationInfo !== '' && $durationMinutes !== '') {
$durationInfo = $durationInfo . ' pages + ' . $durationMinutes . ' minutes';
} elseif ($durationMinutes !== '') {
$durationInfo = $durationMinutes . ' minutes';
} elseif ($durationInfo !== '') {
$durationInfo = $durationInfo . ' pages';
}
if (!empty($post['has_annexes'])) {
$durationInfo = $durationInfo ? $durationInfo . ' + annexe(s)' : 'Annexe(s)';
}
// Jury members — new structure: separate interne/externe lecteurs
$juryMembers = [];
if (!empty(trim($post['jury_promoteur'] ?? ''))) {
$juryMembers[] = [
'name' => trim($post['jury_promoteur']),
'role' => 'promoteur',
'is_external' => isset($post['jury_promoteur_ext']) ? 1 : 0,
'is_ulb' => isset($post['jury_promoteur_ulb']) ? 1 : 0,
'is_external' => 0,
'is_ulb' => 0,
];
}
foreach ($post['jury_lecteurs'] ?? [] as $i => $name) {
if (!empty(trim($post['jury_promoteur_ulb_name'] ?? ''))) {
$juryMembers[] = [
'name' => trim($post['jury_promoteur_ulb_name']),
'role' => 'promoteur',
'is_external' => 1,
'is_ulb' => 1,
];
}
foreach ($post['jury_lecteur_interne'] ?? [] as $name) {
$name = trim($name);
if ($name !== '') {
$juryMembers[] = [
'name' => $name,
'role' => 'lecteur',
'is_external' => isset($post['jury_lecteurs_ext'][$i]) ? 1 : 0,
];
$juryMembers[] = ['name' => $name, 'role' => 'lecteur', 'is_external' => 0];
}
}
foreach ($post['jury_lecteur_externe'] ?? [] as $name) {
$name = trim($name);
if ($name !== '') {
$juryMembers[] = ['name' => $name, 'role' => 'lecteur', 'is_external' => 1];
}
}
// Keep backwards compat with old jury_lecteurs (from old-style forms)
if (empty($juryMembers) || isset($post['jury_lecteurs'])) {
foreach ($post['jury_lecteurs'] ?? [] as $i => $name) {
$name = trim($name);
if ($name !== '') {
$juryMembers[] = [
'name' => $name,
'role' => 'lecteur',
'is_external' => isset($post['jury_lecteurs_ext'][$i]) ? 1 : 0,
];
}
}
}
if (!empty(trim($post['jury_president'] ?? ''))) {
$juryMembers[] = ['name' => trim($post['jury_president']), 'role' => 'president', 'is_external' => 0];
}
// Keywords (max 10)
$tagRaw = $this->sanitiseString($post['tag'] ?? '');
@@ -357,6 +392,7 @@ class ThesisCreateController
: [];
$licenseId = filter_var($post['license_id'] ?? '', FILTER_VALIDATE_INT) ?: null;
$licenseCustom = trim($post['license_custom'] ?? '');
// Access type — must be one of the enabled types; default 2 (Interne)
$accessTypeId = filter_var($post['access_type_id'] ?? '', FILTER_VALIDATE_INT);
@@ -404,6 +440,7 @@ class ThesisCreateController
'languageIds',
'formatIds',
'licenseId',
'licenseCustom',
'lien',
'accessTypeId',
'objet'
+72 -19
View File
@@ -175,7 +175,7 @@ class ThesisEditController
'finality_id' => intval($post['finality'] ?? 0),
'synopsis' => trim($post['synopsis'] ?? ''),
'context_note' => trim($post['context_note'] ?? ''),
'file_size_info' => trim($post['duration_info'] ?? ''),
'file_size_info' => $this->buildFileSizeInfo($post),
'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,
@@ -184,7 +184,8 @@ class ThesisEditController
'jury_points' => $post['jury_points'] ?? null,
'exemplaire_baiu' => !empty($post['exemplaire_baiu']),
'exemplaire_erg' => !empty($post['exemplaire_erg']),
'cc4r' => !empty($post['cc4r']),
'cc4r' => !empty($post['cc2r']),
'license_custom' => trim($post['license_custom'] ?? ''),
]);
// ── 2. Authors (alphabetically sorted) ─────────────────────────────
@@ -545,6 +546,43 @@ class ThesisEditController
{
$members = [];
// Promoteur interne
if (!empty(trim($post['jury_promoteur'] ?? ''))) {
$members[] = [
'name' => trim($post['jury_promoteur']),
'role' => 'promoteur',
'is_external' => 0,
'is_ulb' => 0,
];
}
// Promoteur ULB
if (!empty(trim($post['jury_promoteur_ulb_name'] ?? ''))) {
$members[] = [
'name' => trim($post['jury_promoteur_ulb_name']),
'role' => 'promoteur',
'is_external' => 1,
'is_ulb' => 1,
];
}
// Lecteurs internes
foreach ($post['jury_lecteur_interne'] ?? [] as $name) {
$name = trim($name);
if ($name !== '') {
$members[] = ['name' => $name, 'role' => 'lecteur', 'is_external' => 0];
}
}
// Lecteurs externes
foreach ($post['jury_lecteur_externe'] ?? [] as $name) {
$name = trim($name);
if ($name !== '') {
$members[] = ['name' => $name, 'role' => 'lecteur', 'is_external' => 1];
}
}
// President (optional, admin-only)
if (!empty(trim($post['jury_president'] ?? ''))) {
$members[] = [
'name' => trim($post['jury_president']),
@@ -553,26 +591,41 @@ class ThesisEditController
];
}
if (!empty(trim($post['jury_promoteur'] ?? ''))) {
$members[] = [
'name' => trim($post['jury_promoteur']),
'role' => 'promoteur',
'is_external' => isset($post['jury_promoteur_ext']) ? 1 : 0,
'is_ulb' => isset($post['jury_promoteur_ulb']) ? 1 : 0,
];
}
foreach ($post['jury_lecteurs'] ?? [] as $i => $name) {
$name = trim($name);
if ($name !== '') {
$members[] = [
'name' => $name,
'role' => 'lecteur',
'is_external' => isset($post['jury_lecteurs_ext'][$i]) ? 1 : 0,
];
// Backwards compat: old jury_lecteurs[]
if (isset($post['jury_lecteurs'])) {
foreach ($post['jury_lecteurs'] ?? [] as $i => $name) {
$name = trim($name);
if ($name !== '') {
$members[] = [
'name' => $name,
'role' => 'lecteur',
'is_external' => isset($post['jury_lecteurs_ext'][$i]) ? 1 : 0,
];
}
}
}
return $members;
}
/**
* Build file_size_info from separate duration fields.
*/
private 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;
}
}