Files
xamxam/TODO.md
Pontoporeia 9a58b97cb8 Extract SearchController from public/search.php
Move all data-fetching and request logic out of the 285-line search page
into src/SearchController.php:

- SearchController::create() — static factory; builds RateLimit + Database
  dependencies, sends HTTP 429 (and exits) if rate limit is exceeded,
  runs probabilistic cleanup, returns ready instance
- SearchController::handle() — sanitises GET params (query/year/orientation/
  ap_program/keyword), runs all DB queries (searchTheses, countSearchResults,
  getAvailableYears, getAllOrientations, getAllAPPrograms, getUsedTags,
  getPublishedAuthors), builds alphabetical author→id map, assembles
  OG/meta tags, returns a flat array of view variables
- Rate-limit 429 HTML response moved into private sendRateLimitResponse()

public/search.php is now a 6-line dispatcher:
  require SearchController; extract(SearchController::create()->handle());
followed by the unchanged view template (162 lines total, was 285).

The view template is byte-for-byte equivalent: same HTML, same variable
names, same pagination partial include.
2026-04-06 15:33:08 +02:00

66 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TODO
Pending tasks have been split into topic files under [`todo/`](todo/README.md):
| File | Topic |
|------|-------|
| [todo/01-css-semantic-refactor.md](todo/01-css-semantic-refactor.md) | CSS class audit, semantic HTML (public + admin), inline style extraction, favicon |
| [todo/02-php-components.md](todo/02-php-components.md) | Form field partials, shared UI partials, controller extraction, backend maintenance |
| [todo/03-system-cache.md](todo/03-system-cache.md) | `system_cache` table, `SystemCache` class, `system.php` refactor |
| [todo/04-accessibility.md](todo/04-accessibility.md) | WCAG 2.1 AA - remaining failures grouped by success criterion |
## Recently completed (this session)
- [x] `src/SearchController.php` — extracted all data-fetching logic from `public/search.php` into a dedicated controller class; `SearchController::create()` handles rate-limit enforcement (429 response + exit) and returns a ready instance; `handle()` sanitises GET params, runs all DB queries (`searchTheses`, `countSearchResults`, `getAvailableYears`, `getAllOrientations`, `getAllAPPrograms`, `getUsedTags`, `getPublishedAuthors`), builds the alphabetical author map, assembles OG/meta tags, and returns a flat view-variable array; `public/search.php` reduced from 285 lines to 162 lines (pure dispatcher + view template)
- [x] `admin/system.php` + `assets/js/system.js` + `assets/css/system.css` — extracted the large `$extraJsInline` heredoc (≈130 lines) into a static `public/assets/js/system.js` loaded via `$extraJs`; replaced 4 inline `style=` attributes with named CSS modifier classes (`srv-section-title--compact`, `srv-section-title--sub`, `php-grid--flush`, `log-toolbar label` rule); only the dynamic `--disk-pct`/`--disk-color` CSS custom properties remain inline because they carry PHP runtime values
- [x] `src/App.php` — removed dead legacy flash key fallback chains from `consumeFlash()`: the `error`, `admin_error`, `edit_error`, `form_error`, `success`, `admin_success`, `edit_success` session keys were never written by any code; all callers already use `App::flash()``_flash_error` / `_flash_success`. Method is now 4 lines instead of 18.
- [x] `admin/import.php` + `admin.css` — extracted all 4 remaining inline `style=` attributes from `import.php` into named CSS classes (`admin-error-list`, `admin-file-hint`, `admin-import-results`, `admin-import-results__title`) in the Import page section of `admin.css`. No more inline styles in `import.php`.
- [x] WCAG 3.3.1 `autofocus` on first invalid field — `App::flashAutofocus()` / `consumeAutofocus()` added; `actions/formulaire.php` maps exception messages → field names and stores the autofocus hint in `$_SESSION['_flash_autofocus']`; `actions/edit.php` does the same; `add.php` consumes it via a `withAutofocus()` helper and injects `autofocus => true` into `$attrs` for `text-field.php` / `select-field.php` includes; `edit.php` uses inline ternary for the same; `text-field.php` and `select-field.php` partials now support boolean `true` values in `$attrs` (emit bare attribute names for `autofocus`, `required`, etc.)
- [x] `config/apropos.php` — extracted hardcoded contacts (Laurent Leprince, Xavier Gorgol, Brigitte Ledune) and credits into a config array (`contacts[]`, `credits[]`, `erg_url`); `public/apropos.php` now loops over the config with `htmlspecialchars` instead of embedding names/emails in HTML
- [x] `todo/02-php-components.md` — audited and marked 8 stale items as already done: all 5 form field partials (`text-field`, `select-field`, `checkbox-list`, `file-field`, `jury-fieldset`), `admin-alert.php`/`flash-messages.php` consolidation, `RateLimit` cache dir placement, and `apropos.php` contacts extraction
- [x] WCAG 4.1.2 `<video>` captions — `tfe.php` now emits `<track kind="captions">` for each MP4 when a `.vtt` sidecar exists (N-th VTT paired with N-th video). `formulaire.php` accepts `.vtt` uploads (`file_type='caption'`, MIME normalised). `media.php` serves `text/vtt` with correct headers and visibility gating. Admin `add.php` file-field hint documents the `.vtt` upload convention.
- [x] `admin/edit.php` — WCAG 4.1.2: removed `mb_strimwidth` truncation from `$accessOptions` mapping; access type `<select>` options now include full description text (`name — description`) so the accessible name is unambiguous for screen readers
- [x] `public/assets/favicon.svg` — created public favicon: brand-purple (`#9557b5`) rounded square with white "P" lettermark; distinct from `admin_favicon.svg` (archive-restore icon in `#c104fc`)
- [x] `templates/head.php` — favicon `<link>` now selects `favicon.svg` (public) vs `admin_favicon.svg` (admin) based on `$isAdmin`; closes `todo/01-css-semantic-refactor.md` favicon task
- [x] `todo/04-accessibility.md` — marked WCAG 3.1.1 lang audit and WCAG 4.1.2 select truncation items as done
- [x] `todo/01-css-semantic-refactor.md` — marked favicon task as done
- [x] `admin.css` - added `[aria-current="page"]` rule for admin nav links (`border-bottom: 2px solid currentColor; padding-bottom: 1px`) fixing WCAG 1.4.1 (active nav link had no non-colour indicator)
- [x] `admin.css` - fixed undefined `--admin-purple` variable in pagination hover; replaced with `--accent-primary` (same `#9557b5` value)
- [x] `todo/01-css-semantic-refactor.md` - audited all CSS/HTML refactor tasks; marked ~15 items as already-done (`.admin-main`, `.admin-page-title`, `.admin-form-row`, `.admin-label`, `.admin-input/select/textarea`, `.admin-table`, `.admin-fieldset`, `tfe.css` class replacements, `search.css` selector, `login.php`/`edit.php` inline styles, `admin-alert` replacement, form partial hints)
- [x] `todo/04-accessibility.md` - marked WCAG 1.4.1 admin nav and `--admin-purple` audit items as completed
- [x] `admin/index.php` - server-side pagination (25/page); `Database::getThesesListCount()` added; `getThesesList()` extended with `$limit`/`$offset`; `access_type` JOIN added to query (was missing); result-count meta line added; `.pagination-wrap` + `.pagination-btn` + `.pagination-info` styles added to `admin.css`
- [x] `checkbox-list.php` - replaced `<div class="admin-checkbox-list">` with `<fieldset class="admin-checkbox-group"><legend class="sr-only">...</legend><ul>` (WCAG 1.3.1 fix)
- [x] `admin.css` - replaced `.admin-checkbox-list` with `.admin-body fieldset.admin-checkbox-group > ul` semantic selectors; added `span.admin-row-label` as visible label column counterpart
- [x] `login.php` - wrapped content in `<main id="main-content">` landmark
- [x] `account.php` - `<div class="admin-account-status">``<dl>`; `__row` divs kept; `__label` spans → `<dt>`; `admin-danger-zone__description` div → `<p>`
- [x] `index.php` - maintenance bar `<div>``<aside role="status" aria-label="Statut du site">`
- [x] `add.php` / `edit.php` - `autocomplete="name"` on author field, `autocomplete="email"` on contact field
- [x] `tags.php` - all inline `style=` attributes removed; sizing/spacing moved to CSS (`.admin-input--inline`, `.admin-select--inline`, `.admin-inline-form + .admin-inline-form`, `.admin-tags-count`)
- [x] Marked already-done items in todo files: stats `<dl>`, `thanks.php` `<section>`, `scope="col"` on both tables, `tfe.php` inline styles, `role="alert"` on flash messages
- [x] `admin-submit-wrap``admin-form-footer` rename: updated all 6 admin templates (`add.php`, `edit.php`, `login.php`, `account.php`, `import.php`, `pages-edit.php`) and all 8 CSS selectors in `admin.css` (`.admin-form > div:not(...)` exclusion guards, `.admin-login-box` overrides). Closes `todo/01-css-semantic-refactor.md` submit-wrap task.
- [x] Marked `status-badge.php` partial and WCAG 1.3.1 status-badge items as already-done in `todo/02-php-components.md` and `todo/04-accessibility.md` (partial + CSS were fully implemented; TODO had not been updated)
- [x] `public/index.php` — WCAG 2.4.4: home page cards now append `<span class="sr-only">, YEAR</span>` to each cards `<p>` link text so screen readers get unique link names when two theses share the same title
- [x] `todo/04-accessibility.md` — WCAG 2.4.3: marked back-link focus-order item as already done (`tfe-back-link` is already the first DOM element in `.tfe-left`, before `<h1>`)
- [x] `jury-fieldset.php` — WCAG 3.3.2: replaced bare `<label>Lecteur·ices :</label>` with `<fieldset class="admin-jury-lecteurs"><legend>Lecteur·ices</legend>` so the lecteur group has a proper programmatic label
- [x] `jury-fieldset.php` — WCAG 4.1.2: all "Externe" checkboxes (promoteur + each lecteur row, static + dynamically added via JS) now carry `aria-label="[Role] — externe"` providing group context without visible redundancy
- [x] `jury-fieldset.php` — WCAG 2.1.1: jury remove buttons verified to have descriptive `aria-label="Supprimer le lecteur·ice N"` on all rows (static + dynamic)
- [x] `admin.css` — added `.admin-body fieldset fieldset.admin-jury-lecteurs` rule: strips border/background on the nested lecteur fieldset so it renders as a visual sub-group, not a double-bordered card
- [x] `todo/04-accessibility.md` — WCAG 1.4.4 + 1.4.12 audited and marked done: all font-sizes are `rem`; no `overflow:hidden` on essential text content