Commit Graph

10 Commits

Author SHA1 Message Date
Pontoporeia
d588ae004d Reintroduce TFE duration metadata: DB columns, form fields, controllers, views, and migration
Add 'unsafe-eval' to CSP script-src directives (htmx requires Function())
2026-06-15 15:56:52 +02:00
Pontoporeia
99125cc8e3 Add autosave draft system for partage form with HTMX-based session persistence
- New fragment endpoint POST/GET /partage/fragments/draft.php:
  saves all form fields to PHP session, excludes file/csrf/slug fields
  GET returns JSON for JS hydration on page load
  rotates both global CSRF and share CSRF tokens in sync

- form.php accepts optional $formExtraAttrs and $showAutosaveStatus:
  allows injecting HTMX attributes and 'Brouillon enregistré' indicator

- renderShareLinkForm adds hx-post with change/input debounce trigger,
  loads autosave-handler.js, hydrate fields from draft on page load

- Draft cleared on successful form submission in handleShareLinkSubmission

- autosave-handler.js now also updates share_link_token hidden input
  when rotating CSRF token (partage form uses both csrf_token and share_link_token)

- Added .autosave-status CSS to form.css (was admin.css-only)

- Updated fragment routing to accept GET requests (needed for draft hydration)
2026-06-11 11:04:49 +02:00
Pontoporeia
e17246c850 Add field-level aria-errormessage, aria-invalid, and aria-describedby across the TFE form
WCAG 3.3.1 (Error Identification): failing fields now get
aria-errormessage pointing to the flash-error container and
aria-invalid="true". WCAG 3.3.3 (Error Suggestion): <small>
hint text on inputs, selects, and file fields is now linked via
aria-describedby (always, not just on error).

Changes:
- text-field.php, select-field.php, checkbox-list.php: accept
  $errorFieldName; add aria-errormessage/aria-invalid on match;
  add id to <small> and aria-describedby on the control
- fieldset-tfe-info.php: aria-invalid on synopsis textarea
- fichiers-fragment.php: aria-describedby on cover, note
  d'intention, TFE, annexes, and website inputs; aria-invalid
  on format checkboxes when error matches 'formats'
- form.php: id="flash-error" + tabindex="-1" on flash-error
  div; accept $errorFieldName from callers
- admin/add.php: set $errorFieldName, wire $withAutofocusFn
  (was identity default)
- admin/edit.php: set $errorFieldName
- partage/index.php: consume autofocus field, wire autofocus
  function, add App::flashAutofocus() in submit catch block

Also fixes WCAG standards issue: removed invalid 'required'
HTML attribute from <fieldset> elements in checkbox-list.php
and fichiers-fragment.php (only aria-required stays). Added
role="group" for explicit ARIA semantics.
2026-06-11 10:23:47 +02:00
Pontoporeia
317547ac93 Fix #4 v2: decouple contact_interne from contact_visible in ThesisCreateController
validateAndSanitise() no longer cross-contaminates:
- contact_interne overwrote mail, which then copied to contact_visible
- Fixed: contactInterne from contact_interne (admin) or confirmation_email (student)
- Fixed: contactVisible from contact_visible (admin) or mail (student)
- Fixed: submit() uses contactInterne as author email, not mail
2026-06-10 00:18:49 +02:00
Pontoporeia
3d524226a1 formulaire: correctifs identifiant/année, contact, fichiers optionnels
- Identifiant: mise à jour automatique quand l'année change en back-office (updateThesis + ThesisEditController)
- Contact: hint enrichi (1 seul contact, formatage Instagram/Mastodon)
- Fichiers: TFE rendu optionnel pour Site web/Performance/Installation (note d'intention reste obligatoire)
2026-06-10 00:17:00 +02:00
Pontoporeia
ae66c2baad Integrate Monolog: replace four logging systems with single PSR-3 factory
- Add monolog/monolog dependency (^3.10)  
- Create app/Logger.php central factory with channels: app, admin, error, audit
- Each channel gets RotatingFileHandler (30-day retention) with pass-through LineFormatter
  preserving existing JSON format contracts
- Rewrite AppLogger as thin facade delegating to Logger::get('app')
- Rewrite ErrorHandler::log() to delegate to Logger::get('error')
- Rewrite AdminLogger file output to delegate to Logger::get('admin'), keep DB writes
- Add Monolog file shadow to Audit via Logger::get('audit') (Option A per monolog-plan)
- Log level controlled by LOG_LEVEL env var (defaults: DEBUG in cli-server, WARNING otherwise)
- Graceful NullHandler fallback when log directory is not writable
- Update SystemController LOG_FILES: remove php_error, add app/admin/error/audit
- JSON app logs parsed to readable one-liners in the log viewer
- Remove nginx config tab (parametres + fragment + template + css)
- Friendly empty-state message when app log files don't exist yet (notYet)
- PHP tail fallback when exec() unavailable
- All 228 PHPUnit tests pass, no call sites changed
2026-05-20 12:28:31 +02:00
Pontoporeia
a6e0aa5887 Add code coverage configuration (phpunit.xml source filter), baseline coverage report (21.27% lines), gitignore coverage/ and .phpunit.result.cache; remove deprecated setAccessible() calls 2026-05-20 02:08:42 +02:00
Pontoporeia
a047062d87 Phase 4 cleanup: migrate old tests to PHPUnit, add ErrorHandler/PureLogic/SearchController tests, remove app/tests/, update justfile test target 2026-05-20 01:55:58 +02:00
Pontoporeia
93625d09b5 Add integration tests (Phase 2: DatabaseExtended, ShareLinkExtended, RateLimitExtended) and controller validation tests (Phase 3: ThesisCreate, ThesisEdit, AutofocusField) 2026-05-20 01:51:41 +02:00
Pontoporeia
7a4d0fafb2 Add PHPUnit setup (Phase 0) and pure-logic tests (Phase 1): Crypto, EmailObfuscator, SystemController helpers, StudentEmail, TfeController OG tags 2026-05-20 01:35:56 +02:00