Ajoute une fonction SQLite UDF accfold() (app/src/AccentFolding.php) qui plie les caractères accentués latin vers leur base ASCII (é→e, ç→c, …), et l'applique à chaque condition de recherche côté colonne ET côté terme (accfold(column) LIKE accfold(:term)). Comme le runtime n'a ni intl (Normalizer) ni iconv, le repli passe par une map de translitération manuelle (Western Latin-1 + Latin Extended-A, NULL-safe). Couvert : - recherche publique (searchTheses / countSearchResults) : titre, sous-titre, synopsis, auteurs, promoteurs, tags ; - popover étudiant (getThesesByAuthorName / getThesesForAuthors) : a.name ; - recherche backoffice (getThesesList / getThesesListCount) : titre, sous-titre, identifiant, auteur. L'UDF est enregistré dans Database::registerSqliteFunctions() (appelé par le constructeur et par le harnais de test TestDatabaseInstance). Évite aussi la dépréciation PHP 8.5 de PDO::sqliteCreateFunction() : la connexion est créée via \Pdo\Sqlite quand disponible (createFunction()) avec repli sur PDO (sqliteCreateFunction()) sur les anciens runtimes ; les tests passent de @dataProvider docblock à l'attribut #[DataProvider] (fin de la dépréciation PHPUnit). Détache .php-cs-fixer.cache (gitignoré) pour ne plus polluer le working copy. 294 tests PHPUnit verts sans dépréciation, phpstan niveau 5 OK.
4.5 KiB
Search & Répertoire — Documentation
Two public browsing surfaces, both handled by app/src/Controllers/SearchController.php
and routed by app/src/Dispatcher.php:
| Route | Handler | Purpose |
|---|---|---|
/search, /search.php |
handleSearch() |
Full-text query + classic single filters |
/repertoire, /repertoire.php |
handleRepertoire() |
Browseable directory with multi-select filters |
Both only ever expose published theses (is_published = 1).
HandleSearch (/search)
handleSearch() reads from $_GET and renders app/templates/public/search.php
with the results fragment (app/templates/partials/search-results.php).
Searchable text fields (via Database::searchTheses()):
- Title, subtitle, synopsis, author names, supervisor names, tags/keywords.
Single-value filters (collectSearchParams()):
query— free textyear— exact yearorientation— artistic orientationap_program— AP programfinality— finality typeformat— formatkeyword— tag/keyword
Results are paginated (limit = 20 default); the search bar
(app/templates/partials/search-bar.php) submits a GET form to /search.
HandleRepertoire (/repertoire)
handleRepertoire() reads multi-select filter arrays from $_GET and renders
app/templates/public/repertoire.php, which uses the shared results partial
and app/templates/partials/repertoire-index.php.
Multi-select filters (collectFilterParams(), each an array, _GET keys):
fy[]— years (validated to 1900–2100)ap[]— AP program namesor[]— orientationsfi[]— finalitieskw[]— keywords/tags
Each value is trimmed, length-capped (≤ 100), de-duplicated, and passed through as sanitised strings — no direct user input reaches SQL.
There is also an HTMX student preview popover at
/repertoire/student-preview (handleStudentPreview() → student-preview.php).
Rate limiting
Search is rate-limited via app/src/RateLimit.php. See the nginx config
(nginx/xamxam.conf) for the matching server-side limits.
Database access
- Full-text + single filters:
Database::searchTheses(array $params, $limit, $offset)andDatabase::countSearchResults(array $params). - Keyword/tag autocomplete:
Database::searchTags(string $query). - Supervisor autocomplete:
Database::searchSupervisors($query, $role). - Language autocomplete:
Database::searchLanguages(string $query).
Queries operate on v_theses_public; keyword matching joins the thesis_tags /
tags tables (keywords are stored as lowercase-normalised tags, not a
keywords/thesis_keywords set — see database.md).
All queries use PDO prepared statements and escape %/_ for LIKE
(Database::escapeLikeString) to prevent wildcard injection.
Accent-insensitive matching
Text searches on the public search bar, the student-preview popover, and
the admin list search are all diacritic-insensitive: Théophile and
Theophile, sévère and severe return the same results.
This is implemented via a SQLite user-defined function accfold()
(app/src/AccentFolding.php, registered in Database::registerSqliteFunctions()), which
strips precomposed accented Latin characters to their ASCII base (é → e,
ç → c, …). Search conditions compare the folded column against the folded
term (accfold(column) LIKE accfold(:term)), so both sides are normalised the
same way. The function is NULL-safe and registered on the production and test
connections alike; the public path uses searchTheses()/countSearchResults(),
the student popover getThesesByAuthorName(), and the admin list
getThesesList()/getThesesListCount().
Note: intl/Normalizer and iconv are not available on the runtime, so
folding uses a hand-maintained transliteration map (Western Latin-1 +
Latin Extended-A).
Performance notes
- Critical text/filter columns and the junction tables are indexed
(
idx_theses_pub_year,idx_theses_*,idx_thesis_tags_*, …). v_theses_publicpre-computes the joins for the common read path.- The repertoire filters operate on indexed lookup columns.
Future enhancements (not yet implemented)
The historical search.md listed potential automplete/faceted-search/export
ideas. Status:
- Auto-complete for tags exists at the form level (
searchTags) - Faceted counts, saved searches, result export, and advanced boolean operators are not implemented