mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
standardise multi-author support across all forms
- ThesisCreateController: comma-split auteurice, sort alphabetically, use setThesisAuthors() instead of hardcoded createThesis() author_id - Database::createThesis(): removed author_id param and hardcoded insert - Database::findDuplicateThesis(): accepts array of author names, matches any shared author via IN + DISTINCT - ThesisEditController::save(): sort authors alphabetically on save - File folder naming: slug from all authors alphabetically sorted - v_theses_full GROUP_CONCAT: ORDER BY a.name ASC for deterministic display - Migration 012_author_view_order.sql: rebuilds view with alphabetical order
This commit is contained in:
@@ -146,7 +146,7 @@ class ThesisCreateController
|
||||
|
||||
// ── 1b. Duplicate detection ───────────────────────────────────────────
|
||||
require_once APP_ROOT . '/src/DuplicateThesisException.php';
|
||||
$duplicate = $this->db->findDuplicateThesis($data['titre'], $data['auteurName'], $data['annee']);
|
||||
$duplicate = $this->db->findDuplicateThesis($data['titre'], $data['authorNames'], $data['annee']);
|
||||
if ($duplicate !== null) {
|
||||
throw new DuplicateThesisException(
|
||||
$duplicate['id'],
|
||||
@@ -157,9 +157,17 @@ class ThesisCreateController
|
||||
);
|
||||
}
|
||||
|
||||
// ── 2. Find / create author ───────────────────────────────────────────
|
||||
$authorId = $this->db->findOrCreateAuthor($data['auteurName'], $data['mail'] ?: null, $data['showContact']);
|
||||
error_log("ThesisCreateController: author ID $authorId");
|
||||
// ── 2. Build author entries (alphabetically sorted) ───────────────────
|
||||
$authorEntries = [];
|
||||
foreach ($data['authorNames'] as $i => $name) {
|
||||
$authorEntries[] = [
|
||||
'name' => $name,
|
||||
'email' => $i === 0 ? ($data['mail'] ?: null) : null,
|
||||
'show_contact' => $i === 0 ? $data['showContact'] : false,
|
||||
];
|
||||
}
|
||||
$allAuthorsStr = implode(', ', $data['authorNames']);
|
||||
$authorSlug = $this->generateAuthorSlug($allAuthorsStr);
|
||||
|
||||
// ── 3–4. DB writes in a transaction ───────────────────────────────────
|
||||
$this->db->beginTransaction();
|
||||
@@ -178,12 +186,12 @@ class ThesisCreateController
|
||||
'license_id' => $data['licenseId'],
|
||||
'access_type_id' => $data['accessTypeId'],
|
||||
'objet' => $data['objet'],
|
||||
'author_id' => $authorId,
|
||||
]);
|
||||
|
||||
$identifier = $this->db->getThesisIdentifier($thesisId);
|
||||
error_log("ThesisCreateController: created thesis #$thesisId ($identifier)");
|
||||
error_log("ThesisCreateController: created thesis #$thesisId ($identifier) with " . count($authorEntries) . " author(s)");
|
||||
|
||||
$this->db->setThesisAuthors($thesisId, $authorEntries);
|
||||
$this->db->setThesisJury($thesisId, $data['juryMembers']);
|
||||
$this->db->setThesisLanguages($thesisId, $data['languageIds']);
|
||||
$this->db->setThesisFormats($thesisId, $data['formatIds']);
|
||||
@@ -199,7 +207,7 @@ class ThesisCreateController
|
||||
// ── 5. File uploads (outside transaction — filesystem ops) ────────────
|
||||
$this->handleCoverUpload($thesisId, $files['couverture'] ?? null);
|
||||
$this->db->handleBannerUpload($thesisId, $files['banner'] ?? null);
|
||||
$this->handleThesisFiles($thesisId, $data['annee'], $identifier, $files['files'] ?? null, $data['auteurName'], $post);
|
||||
$this->handleThesisFiles($thesisId, $data['annee'], $identifier, $files['files'] ?? null, $authorSlug, $post);
|
||||
|
||||
return $thesisId;
|
||||
}
|
||||
@@ -263,10 +271,17 @@ class ThesisCreateController
|
||||
*/
|
||||
private function validateAndSanitise(array $post): array
|
||||
{
|
||||
$auteurName = $this->validateRequired(
|
||||
$this->sanitiseString($post['auteurice'] ?? ''),
|
||||
'Nom/Prénom/Pseudo'
|
||||
);
|
||||
// Split authors by comma, trim, filter empty, sort alphabetically.
|
||||
$authorRaw = $this->sanitiseString($post['auteurice'] ?? '');
|
||||
$authorNames = [];
|
||||
if ($authorRaw !== '') {
|
||||
$authorNames = array_filter(array_map('trim', explode(',', $authorRaw)), fn($n) => $n !== '');
|
||||
$authorNames = array_values($authorNames);
|
||||
sort($authorNames, SORT_NATURAL);
|
||||
}
|
||||
if (empty($authorNames)) {
|
||||
throw new Exception("Le champ 'Nom/Prénom/Pseudo' est requis.");
|
||||
}
|
||||
|
||||
$mail = !empty($post['mail']) ? $this->sanitiseString($post['mail']) : '';
|
||||
$showContact = !empty($post['contact_public']) ? true : false;
|
||||
@@ -371,7 +386,7 @@ class ThesisCreateController
|
||||
}
|
||||
|
||||
return compact(
|
||||
'auteurName',
|
||||
'authorNames',
|
||||
'mail',
|
||||
'showContact',
|
||||
'confirmationEmail',
|
||||
@@ -445,16 +460,14 @@ class ThesisCreateController
|
||||
* @param int $year Used for the storage sub-directory path.
|
||||
* @param string $identifier Thesis identifier slug (e.g. "2024-003").
|
||||
* @param array|null $uploads Multi-file $_FILES entry (may be null).
|
||||
* @param string $authorName Author name for folder and file naming.
|
||||
* @param string $authorSlug Pre-computed author slug for folder and file naming.
|
||||
*/
|
||||
private function handleThesisFiles(int $thesisId, int $year, string $identifier, ?array $uploads, string $authorName, array $post = []): void
|
||||
private function handleThesisFiles(int $thesisId, int $year, string $identifier, ?array $uploads, string $authorSlug, array $post = []): void
|
||||
{
|
||||
if (!$uploads || !is_array($uploads['name'] ?? null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate author slug and unique folder name
|
||||
$authorSlug = $this->generateAuthorSlug($authorName);
|
||||
$folderName = $this->ensureUniqueFolder($year, $authorSlug);
|
||||
$uploadDir = STORAGE_ROOT . "/theses/{$year}/{$folderName}/";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user