admin/thanks.php:
- <div style="margin-top:1.5rem;display:flex;gap:.75rem;flex-wrap:wrap;"> → class="admin-action-bar"
- <p style="color:var(--text-secondary);"> → class="admin-muted"
admin/pages.php:
- Éditer button style="font-size:.8rem;padding:.3rem .75rem;" → class="admin-btn admin-btn--sm"
admin.css (Thesis info sections block):
- Added .admin-action-bar { margin-top:1.5rem; display:flex; gap:0.75rem; flex-wrap:wrap }
- Added .admin-muted { color: var(--text-secondary) }
The only remaining inline style in any admin PHP file is the dynamic
--disk-pct/--disk-color custom properties on the disk bar in system.php,
which carry PHP runtime values and cannot be moved to static CSS.
14 KiB
TODO
Pending tasks have been split into topic files under todo/:
| File | Topic |
|---|---|
| todo/01-css-semantic-refactor.md | CSS class audit, semantic HTML (public + admin), inline style extraction, favicon |
| todo/02-php-components.md | Form field partials, shared UI partials, controller extraction, backend maintenance |
| todo/03-system-cache.md | system_cache table, SystemCache class, system.php refactor |
| todo/04-accessibility.md | WCAG 2.1 AA - remaining failures grouped by success criterion |
Recently completed (this session)
-
admin/thanks.php+admin/pages.php+admin.css— extracted last 3 inlinestyle=attributes from admin PHP templates:<div style="margin-top:1.5rem;display:flex;gap:.75rem;flex-wrap:wrap;">inthanks.php→class="admin-action-bar"(.admin-action-barrule added to CSS);<p style="color:var(--text-secondary);">inthanks.php→class="admin-muted"(.admin-mutedrule added);style="font-size:.8rem;padding:.3rem .75rem;"on Éditer button inpages.php→class="admin-btn admin-btn--sm"(uses existing modifier). Only the dynamic--disk-pct/--disk-colorCSS custom properties on the disk bar insystem.phpremain (carry PHP runtime values — legitimate). -
variables.css+search.css— public dark-mode support via@media (prefers-color-scheme: dark)scoped tobody:not(.admin-body): all semantic tokens (--bg-*,--text-*,--border-*,--accent-*, status colours) overridden with dark equivalents;--accent-primarylightened to#b87fd4for WCAG contrast on dark backgrounds;--search-error-*variables added to replace hardcoded#fff0f0/#c00in.search-error; admin pages unaffected -
src/ThesisCreateController.php— extracted all validation, DB writes, and file-upload handling fromadmin/actions/formulaire.phpinto a dedicated controller;make()factory instantiatesDatabase;loadFormData()returns all lookup tables for the add-form view;submit(post, files)runs the full creation flow: validates/sanitises all POST fields, callsfindOrCreateAuthor, inserts thesis row viacreateThesis, links jury/languages/formats/tags inside a transaction, then processes cover image, banner, and multi-file uploads outside the transaction;autofocusFieldForError()maps exception messages to WCAG 3.3.1 autofocus field hints;actions/formulaire.phpreduced 346→45 lines (CSRF guard + onesubmit()call);admin/add.phplookup-table block replaced withThesisCreateController::make()->loadFormData();Database::setPublished()andDatabase::bulkSetPublished()added, eliminating raw SQL fromactions/publish.php(100→65 lines); no raw PDO calls remain in any action handler file -
src/HomeController.php— extracted all data-fetching logic frompublic/index.phpinto a dedicated controller class;create()returns a ready instance withDatabasesingleton injected;handle()parsespage/yearGET params, determines display mode (default-random-latest / year-filtered / paginated-all), runs the appropriate DB queries (getLatestPublishedYear,getLatestYearTheses,searchTheses+countSearchResults,getPublishedTheses+countPublishedTheses), batch-loads cover images viagetCoverPathsForTheses, assembles OG/meta tags, and returns a flat view-variable array;public/index.phpreduced 100→71 lines (6-line dispatcher + pure view template);todo/02-php-components.md“Extract remaining controllers” task marked done -
src/TfeController.php— extracted all data-fetching, OG-tag assembly, and view-variable construction frompublic/tfe.phpinto a dedicated controller class;create()returns a ready instance withDatabasesingleton injected;handle()validates theidparam (redirects on missing/invalid), loads the thesis row viagetThesisById(), callsgetThesisAccessTypeId()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$ogTagsarray (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;captionFilesreplaces inline$_captionFilesarray in the view;$dbreference removed fromtfe.phpentirely;tfe.phpreduced 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 -
src/ThesisEditController.php— extracted all data-fetching and mutation logic fromadmin/edit.phpandadmin/actions/edit.phpinto a dedicated controller class;load(int $thesisId): arrayfetches the thesis row, current language/format/jury selections, and all lookup tables for the view;save(int $thesisId, array $post, array $files): voidvalidates and persists thesis metadata, authors, jury, languages, formats, tags, and banner in a transaction with proper rollback on error; staticautofocusFieldForError(string $msg): ?stringcentralises WCAG 3.3.1 field-name mapping;admin/edit.phpreduced 191→162 lines (pure dispatcher + view template);actions/edit.phpreduced 153→53 lines (CSRF guard + one controller call) -
src/SystemController.php— extracted all data-fetching logic fromadmin/system.phpandadmin/system-fragment.phpinto 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.phpreduced 582→282 lines;system-fragment.phpreduced 213→137 lines with allfrag_*-prefixed duplicated helpers removed; both files now purely dispatch to the controller and render view templates -
src/SearchController.php— extracted all data-fetching logic frompublic/search.phpinto 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.phpreduced from 285 lines to 162 lines (pure dispatcher + view template) -
admin/system.php+assets/js/system.js+assets/css/system.css— extracted the large$extraJsInlineheredoc (≈130 lines) into a staticpublic/assets/js/system.jsloaded via$extraJs; replaced 4 inlinestyle=attributes with named CSS modifier classes (srv-section-title--compact,srv-section-title--sub,php-grid--flush,log-toolbar labelrule); only the dynamic--disk-pct/--disk-colorCSS custom properties remain inline because they carry PHP runtime values -
src/App.php— removed dead legacy flash key fallback chains fromconsumeFlash(): theerror,admin_error,edit_error,form_error,success,admin_success,edit_successsession keys were never written by any code; all callers already useApp::flash()→_flash_error/_flash_success. Method is now 4 lines instead of 18. -
admin/import.php+admin.css— extracted all 4 remaining inlinestyle=attributes fromimport.phpinto named CSS classes (admin-error-list,admin-file-hint,admin-import-results,admin-import-results__title) in the Import page section ofadmin.css. No more inline styles inimport.php. -
WCAG 3.3.1
autofocuson first invalid field —App::flashAutofocus()/consumeAutofocus()added;actions/formulaire.phpmaps exception messages → field names and stores the autofocus hint in$_SESSION['_flash_autofocus'];actions/edit.phpdoes the same;add.phpconsumes it via awithAutofocus()helper and injectsautofocus => trueinto$attrsfortext-field.php/select-field.phpincludes;edit.phpuses inline ternary for the same;text-field.phpandselect-field.phppartials now support booleantruevalues in$attrs(emit bare attribute names forautofocus,required, etc.) -
config/apropos.php— extracted hardcoded contacts (Laurent Leprince, Xavier Gorgol, Brigitte Ledune) and credits into a config array (contacts[],credits[],erg_url);public/apropos.phpnow loops over the config withhtmlspecialcharsinstead of embedding names/emails in HTML -
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.phpconsolidation,RateLimitcache dir placement, andapropos.phpcontacts extraction -
WCAG 4.1.2
<video>captions —tfe.phpnow emits<track kind="captions">for each MP4 when a.vttsidecar exists (N-th VTT paired with N-th video).formulaire.phpaccepts.vttuploads (file_type='caption', MIME normalised).media.phpservestext/vttwith correct headers and visibility gating. Adminadd.phpfile-field hint documents the.vttupload convention. -
admin/edit.php— WCAG 4.1.2: removedmb_strimwidthtruncation from$accessOptionsmapping; access type<select>options now include full description text (name — description) so the accessible name is unambiguous for screen readers -
public/assets/favicon.svg— created public favicon: brand-purple (#9557b5) rounded square with white "P" lettermark; distinct fromadmin_favicon.svg(archive-restore icon in#c104fc) -
templates/head.php— favicon<link>now selectsfavicon.svg(public) vsadmin_favicon.svg(admin) based on$isAdmin; closestodo/01-css-semantic-refactor.mdfavicon task -
todo/04-accessibility.md— marked WCAG 3.1.1 lang audit and WCAG 4.1.2 select truncation items as done -
todo/01-css-semantic-refactor.md— marked favicon task as done -
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) -
admin.css- fixed undefined--admin-purplevariable in pagination hover; replaced with--accent-primary(same#9557b5value) -
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.cssclass replacements,search.cssselector,login.php/edit.phpinline styles,admin-alertreplacement, form partial hints) -
todo/04-accessibility.md- marked WCAG 1.4.1 admin nav and--admin-purpleaudit items as completed -
admin/index.php- server-side pagination (25/page);Database::getThesesListCount()added;getThesesList()extended with$limit/$offset;access_typeJOIN added to query (was missing); result-count meta line added;.pagination-wrap+.pagination-btn+.pagination-infostyles added toadmin.css -
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) -
admin.css- replaced.admin-checkbox-listwith.admin-body fieldset.admin-checkbox-group > ulsemantic selectors; addedspan.admin-row-labelas visible label column counterpart -
login.php- wrapped content in<main id="main-content">landmark -
account.php-<div class="admin-account-status">→<dl>;__rowdivs kept;__labelspans →<dt>;admin-danger-zone__descriptiondiv →<p> -
index.php- maintenance bar<div>→<aside role="status" aria-label="Statut du site"> -
add.php/edit.php-autocomplete="name"on author field,autocomplete="email"on contact field -
tags.php- all inlinestyle=attributes removed; sizing/spacing moved to CSS (.admin-input--inline,.admin-select--inline,.admin-inline-form + .admin-inline-form,.admin-tags-count) -
Marked already-done items in todo files: stats
<dl>,thanks.php<section>,scope="col"on both tables,tfe.phpinline styles,role="alert"on flash messages -
admin-submit-wrap→admin-form-footerrename: updated all 6 admin templates (add.php,edit.php,login.php,account.php,import.php,pages-edit.php) and all 8 CSS selectors inadmin.css(.admin-form > div:not(...)exclusion guards,.admin-login-boxoverrides). Closestodo/01-css-semantic-refactor.mdsubmit-wrap task. -
Marked
status-badge.phppartial and WCAG 1.3.1 status-badge items as already-done intodo/02-php-components.mdandtodo/04-accessibility.md(partial + CSS were fully implemented; TODO had not been updated) -
public/index.php— WCAG 2.4.4: home page cards now append<span class="sr-only">, YEAR</span>to each card’s<p>link text so screen readers get unique link names when two theses share the same title -
todo/04-accessibility.md— WCAG 2.4.3: marked back-link focus-order item as already done (tfe-back-linkis already the first DOM element in.tfe-left, before<h1>) -
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 -
jury-fieldset.php— WCAG 4.1.2: all "Externe" checkboxes (promoteur + each lecteur row, static + dynamically added via JS) now carryaria-label="[Role] — externe"providing group context without visible redundancy -
jury-fieldset.php— WCAG 2.1.1: jury remove buttons verified to have descriptivearia-label="Supprimer le lecteur·ice N"on all rows (static + dynamic) -
admin.css— added.admin-body fieldset fieldset.admin-jury-lecteursrule: strips border/background on the nested lecteur fieldset so it renders as a visual sub-group, not a double-bordered card -
todo/04-accessibility.md— WCAG 1.4.4 + 1.4.12 audited and marked done: all font-sizes arerem; nooverflow:hiddenon essential text content