Clean up flash key legacy code and extract import.php inline styles

App::consumeFlash() had 18-line legacy fallback chains reading from seven old
session keys (error, admin_error, edit_error, form_error, success,
admin_success, edit_success) that were written by no code in the codebase.
All action handlers have used App::flash() -> _flash_error / _flash_success
since the App class was introduced. Removed the dead fallbacks; consumeFlash()
is now 4 lines.

admin/import.php was the last admin template with inline style= attributes.
Extracted four of them to named CSS classes in admin.css:
- admin-error-list   — error <ul> spacing (was style="margin:.5rem 0 0;padding-left:1.2rem")
- admin-file-hint    — <small> display + margin (was style="margin-top:.5rem")
- admin-import-results        — results panel margin (was style="margin-top:2rem")
- admin-import-results__title — <h2> typography (was multi-property inline style)

Closes the 'unify flash message keys' item in todo/02-php-components.md and
the import.php inline style item in todo/01-css-semantic-refactor.md.
This commit is contained in:
Pontoporeia
2026-04-04 12:31:08 +02:00
parent c2eff75789
commit 9637114f6b
6 changed files with 41 additions and 30 deletions

View File

@@ -11,6 +11,9 @@ Pending tasks have been split into topic files under [`todo/`](todo/README.md):
## Recently completed (this session)
- [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

View File

@@ -326,7 +326,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
<?php if (!empty($errors)): ?>
<div role="alert" data-type="error">
<strong>⚠ Erreurs :</strong>
<ul style="margin:.5rem 0 0;padding-left:1.2rem;">
<ul class="admin-error-list">
<?php foreach ($errors as $err): ?>
<li><?= htmlspecialchars($err) ?></li>
<?php endforeach; ?>
@@ -345,7 +345,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
<label>Fichier CSV :</label>
<div class="admin-file-input">
<input type="file" id="csv_file" name="csv_file" accept=".csv" required>
<small style="margin-top:.5rem;">
<small class="admin-file-hint">
Colonnes attendues : Identifiant, Titre, Sous-titre, Auteur·ice(s), Contact, Promoteur·ice(s), Format, Année, AP, Orientation, Finalité, Mots-clés, Synopsis, Contexte, Remarques, Langue, Autorisation, License, taille, Points sur 20, lien BAIU<br>
— Deux premières lignes ignorées (en-tête) — Séparateur : virgule — Encodage : UTF-8
</small>
@@ -358,8 +358,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
</form>
<?php if (!empty($importResults)): ?>
<div style="margin-top:2rem;">
<h2 style="font-size:1rem;font-weight:600;margin-bottom:.75rem;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.06em;">Résultats de l'import</h2>
<div class="admin-import-results">
<h2 class="admin-import-results__title">Résultats de l'import</h2>
<div class="info-message">
<pre><?php foreach ($importResults as $r) echo htmlspecialchars($r) . "\n"; ?></pre>
</div>

View File

@@ -746,6 +746,34 @@
gap: 1.5rem;
}
/* Error list inside role="alert" (import page) */
.admin-error-list {
margin: 0.5rem 0 0;
padding-left: 1.2rem;
}
/* Hint text under the file input (import page) */
.admin-file-hint {
display: block;
margin-top: 0.5rem;
}
/* Import results panel */
.admin-import-results {
margin-top: 2rem;
}
.admin-import-results__title {
font-size: 1rem;
font-weight: 600;
margin-bottom: 0.75rem;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.06em;
border: none;
padding: 0;
}
/* ── Jury fieldset ──────────────────────────────────────────────────────── */
/* Nested lecteur·ices fieldset sits inside the outer jury fieldset:

View File

@@ -106,36 +106,14 @@ class App
/**
* Consume and return flash messages, then clear them from the session.
*
* Also drains the legacy per-page keys (error, success, admin_error,
* admin_success, edit_error, edit_success, form_error) so the transition
* to unified keys can happen incrementally.
*
* @return array{error: ?string, success: ?string}
*/
public static function consumeFlash(): array
{
// Unified keys first, fall back to any legacy key that is set.
$error = $_SESSION['_flash_error']
?? $_SESSION['error']
?? $_SESSION['admin_error']
?? $_SESSION['edit_error']
?? $_SESSION['form_error']
?? null;
$error = $_SESSION['_flash_error'] ?? null;
$success = $_SESSION['_flash_success'] ?? null;
$success = $_SESSION['_flash_success']
?? $_SESSION['success']
?? $_SESSION['admin_success']
?? $_SESSION['edit_success']
?? null;
// Clear all variants.
unset(
$_SESSION['_flash_error'], $_SESSION['_flash_success'],
$_SESSION['error'], $_SESSION['success'],
$_SESSION['admin_error'], $_SESSION['admin_success'],
$_SESSION['edit_error'], $_SESSION['edit_success'],
$_SESSION['form_error']
);
unset($_SESSION['_flash_error'], $_SESSION['_flash_success']);
// Note: autofocus is consumed separately via consumeAutofocus().
return ['error' => $error, 'success' => $success];

View File

@@ -53,6 +53,8 @@
- [x] **`login.php`**: Wrap login content in `<main>` (currently no main landmark)
- [x] **`login.php`**: Extract inline styles on `.admin-form-row` and `.admin-form-footer``login.php` has no `style=` attributes; `.admin-login-box` modifier in `admin.css` already handles the compact layout
- [x] **`admin/import.php` inline styles** — extracted 4 inline `style=` attributes to CSS classes: `admin-error-list` (error `<ul>` margins), `admin-file-hint` (`<small>` display block + margin), `admin-import-results` (results panel `margin-top`), `admin-import-results__title` (results `<h2>` typography). All rules added to `admin.css` Import page section.
## Favicon
- [x] **`admin_favicon.svg` used as public-facing favicon** — created `public/assets/favicon.svg` (brand purple `#9557b5` lettermark “P”); `templates/head.php` now serves `favicon.svg` on public pages and `admin_favicon.svg` on admin pages

View File

@@ -21,7 +21,7 @@
- [ ] Extract `ThesisEditController` — merges `edit.php` + `actions/edit.php`, deduplicates jury fieldset
- [ ] Extract remaining controllers one by one
- [ ] Consolidate action handlers into controller methods
- [ ] Unify flash message keys project-wide to `_flash_error` / `_flash_success`
- [x] Unify flash message keys project-wide to `_flash_error` / `_flash_success` — all callers already use `App::flash()`; removed dead legacy-key fallback chains (`error`, `admin_error`, `edit_error`, `form_error`, `success`, `admin_success`, `edit_success`) from `consumeFlash()`
- [ ] Move OG tag construction into controller logic
- [ ] Extract inline CSS/JS from `system.php` into separate assets