From 89067a521fe06661d6bcdc56eb75385e6d770c0e Mon Sep 17 00:00:00 2001 From: Pontoporeia Date: Mon, 6 Apr 2026 14:25:54 +0200 Subject: [PATCH] Extract TfeController from public/tfe.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit src/TfeController.php (new, 195 lines): - Dedicated controller for the public TFE detail page - create(): Database singleton injection, ready-to-use factory - handle(): validates id param (redirect to index.php on missing/invalid/404), loads thesis via getThesisById(), fetches access type via getThesisAccessTypeId() - buildMetaDescription(): strip_tags + 160-char mb_substr truncation - resolveOgImage(): banner_path → first image file → empty string resolution - buildOgTags(): full og:type/title/description/url/image/image_alt/site_name + article:author / article:published_time assembly - collectCaptionPaths(): ordered list of VTT paths for N-th-video pairing - returns flat array of all view variables including ogTags, captionFiles, pageTitle, metaDescription, isInterdit, bodyClass, extraCss, currentNav public/tfe.php (271 → 206 lines): - Reduced to 9-line dispatcher: require TfeController, create(), handle(), extract() - $db reference removed from view layer entirely - Inline OG tag block (~20 lines) removed - Inline meta-description block (~5 lines) removed - Inline caption-collection loop (~10 lines) removed - $captionFiles replaces $_captionFiles in the video pairing section todo/02-php-components.md: - TfeController extraction marked done - 'Move OG tag construction into controller logic' marked done - Remaining item narrowed to public/index.php home-page controller --- TODO.md | 2 + public/tfe.php | 78 ++------------- src/TfeController.php | 205 ++++++++++++++++++++++++++++++++++++++ todo/02-php-components.md | 5 +- 4 files changed, 217 insertions(+), 73 deletions(-) create mode 100644 src/TfeController.php 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';