feat: extract MediaController, wire into Dispatcher, delete media.php

This commit is contained in:
Pontoporeia
2026-04-17 11:44:08 +02:00
parent b03be51b92
commit 75f808bee4
157 changed files with 1713 additions and 452 deletions

View File

@@ -0,0 +1,166 @@
<?php
/**
* ExportController
*
* Centralises all export logic for admin-facing data dumps.
*
* Responsibilities:
* - Export the full SQLite database as a .sqlite file download
* - Export TFE listings as CSV (the reverse of the CSV import)
*
* The class has NO output side-effects; the thin dispatcher files
* (public/admin/actions/…) perform headers and echo.
*/
class ExportController
{
private Database $db;
public function __construct(Database $db)
{
$this->db = $db;
}
public static function create(): self
{
require_once APP_ROOT . '/src/Database.php';
return new self(Database::getInstance());
}
// ── Database export ──────────────────────────────────────────────────
/**
* Return the absolute path of the live database file.
*/
public function getDatabasePath(): string
{
return $this->db->getDatabasePath();
}
// ── CSV export ───────────────────────────────────────────────────────
/**
* Column headers matching the import format.
*/
public const CSV_HEADERS = [
'Identifiant',
'Titre',
'Sous-titre',
'Auteur·ice(s)',
'Contact',
'Promoteur·ice(s)',
'Format(s)',
'Année',
'AP',
'Orientation',
'Finalité',
'Mots-clés',
'Synopsis',
'Contexte',
'Remarques',
'Langue',
'Autorisation',
'Licence',
'Taille',
'Points sur 20',
'Lien BAIU',
];
/**
* Fetch all theses and their related data, then return a list of rows
* shaped to match the import CSV column order.
*
* Uses batch queries (one per related table) to avoid N+1.
*
* @return list<list<string>> Each inner list has CSV_HEADERS_COUNT elements.
*/
public function exportAllTheses(): array
{
// 1) Base thesis data
$theses = $this->db->getAllThesesForExport();
if ($theses === []) {
return [];
}
// 2) Load related data in batches
$byThesis = function (array $rows): array {
$map = [];
foreach ($rows as $r) {
$tid = (int) $r['thesis_id'];
$map[$tid][] = $r;
}
return $map;
};
$authors = $byThesis($this->db->getAllThesisAuthorsForExport());
$supervisors = $byThesis($this->db->getAllThesisSupervisorsForExport());
$tags = $byThesis($this->db->getAllThesisTagsForExport());
$languages = $byThesis($this->db->getAllThesisLanguagesForExport());
$formats = $byThesis($this->db->getAllThesisFormatsForExport());
// 3) Build CSV rows
$csvRows = [];
foreach ($theses as $t) {
$tid = (int) $t['id'];
// Authors + contact (first author with email)
$authorList = [];
$contact = '';
foreach (($authors[$tid] ?? []) as $a) {
$authorList[] = $a['name'];
if ($contact === '' && !empty($a['email'])) {
$contact = $a['email'];
}
}
// Supervisors
$supList = [];
foreach (($supervisors[$tid] ?? []) as $s) {
$supList[] = $s['name'];
}
// Tags
$tagList = [];
foreach (($tags[$tid] ?? []) as $tg) {
$tagList[] = $tg['name'];
}
// Languages
$langList = [];
foreach (($languages[$tid] ?? []) as $l) {
$langList[] = $l['name'];
}
// Formats
$fmtList = [];
foreach (($formats[$tid] ?? []) as $f) {
$fmtList[] = $f['name'];
}
$csvRows[] = [
$t['identifier'] ?? '',
$t['title'] ?? '',
$t['subtitle'] ?? '',
implode(', ', $authorList),
$contact,
implode(', ', $supList),
implode(', ', $fmtList),
$t['year'] ?? '',
$t['ap_program'] ?? '',
$t['orientation'] ?? '',
$t['finality_type'] ?? '',
implode(', ', $tagList),
$t['synopsis'] ?? '',
$t['context_note'] ?? '',
$t['remarks'] ?? '',
implode(', ', $langList),
$t['access_type'] ?? '',
$t['license_name'] ?? '',
$t['file_size_info'] ?? '',
isset($t['jury_points']) ? (string) $t['jury_points'] : '',
$t['baiu_link'] ?? '',
];
}
return $csvRows;
}
}