diff --git a/TODO.md b/TODO.md index 4cc91b7..aaa6bef 100644 --- a/TODO.md +++ b/TODO.md @@ -11,6 +11,8 @@ Pending tasks have been split into topic files under [`todo/`](todo/README.md): ## Recently completed (this session) +- [x] `src/TfeController.php` — extracted all data-fetching, OG-tag assembly, and view-variable construction from `public/tfe.php` into a dedicated controller class; `create()` returns a ready instance with `Database` singleton injected; `handle()` validates the `id` param (redirects on missing/invalid), loads the thesis row via `getThesisById()`, calls `getThesisAccessTypeId()` for visibility gating, builds the meta description (strip_tags + 160-char truncation), resolves the OG image (banner_path → first image file → empty), assembles the full `$ogTags` array (type/title/description/url/image/image_alt/site_name/article_author/article_published_time), collects WebVTT caption paths for N-th-video pairing, and returns a flat view-variable array; `captionFiles` replaces inline `$_captionFiles` array in the view; `$db` reference removed from `tfe.php` entirely; `tfe.php` reduced 271→206 lines (9-line dispatcher + pure view template); `todo/02-php-components.md` “Extract remaining controllers” and “Move OG tag construction into controller logic” tasks updated + - [x] `src/ThesisEditController.php` — extracted all data-fetching and mutation logic from `admin/edit.php` and `admin/actions/edit.php` into a dedicated controller class; `load(int $thesisId): array` fetches the thesis row, current language/format/jury selections, and all lookup tables for the view; `save(int $thesisId, array $post, array $files): void` validates and persists thesis metadata, authors, jury, languages, formats, tags, and banner in a transaction with proper rollback on error; static `autofocusFieldForError(string $msg): ?string` centralises WCAG 3.3.1 field-name mapping; `admin/edit.php` reduced 191→162 lines (pure dispatcher + view template); `actions/edit.php` reduced 153→53 lines (CSRF guard + one controller call) - [x] `src/SystemController.php` — extracted all data-fetching logic from `admin/system.php` and `admin/system-fragment.php` into a dedicated controller class; centralises: system status checks (nginx, php-fpm, HTTP ping, SQLite DB, storage dir, maintenance flag) with 2-min TTL caching, PHP environment info (1-hour TTL), disk usage (5-min TTL), log file reading (`readLogTail`), nginx config reading, and the shared CSS-class classifier methods (`logLineClass`, `nginxLineClass`, `statusLabel`, `statusClass`, `humanBytes`, `diskColor`); `system.php` reduced 582→282 lines; `system-fragment.php` reduced 213→137 lines with all `frag_*`-prefixed duplicated helpers removed; both files now purely dispatch to the controller and render view templates diff --git a/public/tfe.php b/public/tfe.php index 89844fe..e759568 100644 --- a/public/tfe.php +++ b/public/tfe.php @@ -1,63 +1,12 @@ getThesisById($thesisId); - if (!$data) { header('Location: index.php'); exit; } - } catch (Exception $e) { - error_log("Error loading thesis: " . $e->getMessage()); - header('Location: index.php'); exit; - } -} else { - header('Location: index.php'); exit; -} +// Build controller (loads thesis, enforces visibility, builds OG tags; redirects on 404) +$ctrl = TfeController::create(); -$currentNav = ''; -$_tfeAuthor = $data['authors'] ?? ''; -$pageTitle = $data['title'] . (!empty($_tfeAuthor) ? ' – ' . $_tfeAuthor : '') . ' – Posterg'; -// Build meta description: strip markdown/HTML from synopsis, truncate to ~160 chars -$_synopsisRaw = strip_tags($data['synopsis'] ?? ''); -$metaDescription = mb_strlen($_synopsisRaw) > 160 - ? mb_substr($_synopsisRaw, 0, 157) . '…' - : (empty($_synopsisRaw) ? 'Mémoire de fin d\'études – Posterg, répertoire des TFE de l\'erg.' : $_synopsisRaw); -unset($_tfeAuthor, $_synopsisRaw); - -// --- Open Graph / Twitter Card tags ------------------------------------------ -$_ogBaseUrl = 'https://posterg.erg.be'; -// Resolve OG image: banner → first image file → none -$_ogImage = ''; -if (!empty($data['banner_path'])) { - $_ogImage = $_ogBaseUrl . '/media.php?path=' . rawurlencode($data['banner_path']); -} elseif (!empty($data['files'])) { - foreach ($data['files'] as $_f) { - $_ext = strtolower(pathinfo($_f['file_path'], PATHINFO_EXTENSION)); - if (in_array($_ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) { - $_ogImage = $_ogBaseUrl . '/media.php?path=' . rawurlencode($_f['file_path']); - break; - } - } - unset($_f, $_ext); -} -$ogTags = [ - 'type' => 'article', - 'title' => $data['title'] . (!empty($data['authors']) ? ' – ' . $data['authors'] : ''), - 'description' => $metaDescription, - 'url' => $_ogBaseUrl . '/tfe.php?id=' . $thesisId, - 'image' => $_ogImage, - 'image_alt' => $data['title'] . (!empty($data['authors']) ? ' par ' . $data['authors'] : ''), - 'site_name' => 'Posterg – ERG', - 'article_author' => $data['authors'] ?? '', - 'article_published_time' => !empty($data['year']) ? $data['year'] . '-01-01' : '', -]; -unset($_ogBaseUrl, $_ogImage); -// --- End Open Graph ---------------------------------------------------------- - -$extraCss = ['/assets/css/tfe.css']; -$bodyClass = 'tfe-body'; +// Collect all view variables +extract($ctrl->handle()); ?> @@ -194,21 +143,8 @@ $bodyClass = 'tfe-body';