TLR-002 — Système de layout par page
Sélection du layout dans le CMS, templates dans le bundle — mécanisme générique réutilisable sur
adoption-app.
Table des matières
- Contexte
- Périmètre lot 1
- Entité CmsContent — champ layout
- Migration
- Formulaire BO
- Résolution du template
- Templates bundle
- Nettoyage
- PHPUnit
- Ordre d'implémentation
Contexte
La livraison staging de TLR-002 (6d33521) implémentait un layout 3-cols uniquement pour /docs. Le besoin réel : toute page CMS (y compris la homepage) doit pouvoir choisir son layout. Mécanisme générique, réutilisable sur adoption-app.
État actuel pertinent :
CmsFrontController(/{slug}) →cms/show.html.twig→ étendsite.layoutTemplate(per-site, pas per-page)DocsCmsController(/docs+/docs/{slug}) →docs/cms-layout.html.twig(3-col hardcodé)FrontController(/) → sisite.homeSlugdéfini → forwarde versCmsFrontController; sinon →front/index.html.twig(placeholder "nope" actuellement)tlr/symfony-bundle: pas encore de dossiertemplates/— premier ajout
Périmètre lot 1
In scope : champ layout sur CmsContent · dropdown BO · 2 layouts (default, three-col) · templates dans le bundle · homepage par défaut bundle · pages d'erreur bundle.
Out of scope : création de layouts via l'UI · plus de 2 layouts.
1. Entité CmsContent — champ layout (bundle tlr-symfony)
public const string LAYOUT_DEFAULT = 'default'; public const string LAYOUT_THREE_COL = 'three-col'; public const array LAYOUTS = [self::LAYOUT_DEFAULT, self::LAYOUT_THREE_COL]; #[ORM\Column(length: 50, nullable: true)] private ?string $layout = null;
Getter/setter classiques. null et 'default' sont équivalents côté rendu.
2. Migration
ALTER TABLE cms_content ADD layout VARCHAR(50) DEFAULT NULL;
Convention nommage : Version20260616120000.
3. Formulaire BO — CmsContentType (telaria-app)
->add('layout', ChoiceType::class, [ 'label' => 'Mise en page', 'required' => false, 'placeholder' => 'Par défaut', 'choices' => array_combine( array_map(fn($l) => ucfirst(str_replace('-', ' ', $l)), CmsContent::LAYOUTS), CmsContent::LAYOUTS ), ])
4. Résolution du template
Helper partagé (méthode privée ou service léger) :
private function resolveLayout(CmsContent $page): string { return match ($page->getLayout()) { CmsContent::LAYOUT_THREE_COL => 'cms/layouts/three-col.html.twig', default => 'cms/layouts/default.html.twig', }; }
Variables injectées :
default→page,body_html,page_seothree-col→ idem +docs(findDocNavBySite($site)) +current_slug
CmsFrontController (/{slug}) : adopte resolveLayout().
DocsCmsController (/docs + /docs/{slug}) : garde les deux routes (le "doc" est dans le nom, c'est son périmètre). /docs/{slug} adopte resolveLayout() à la place du template hardcodé.
5. Templates bundle (tlr-symfony/templates/)
Premier dossier templates/ du bundle. Surcharge app : templates/bundles/TlrSymfonyBundle/.
cms/layouts/default.html.twig
Layout simple, contenu centré, pas de nav ni chatbot.
{% extends 'html.twig' %} {% block doc_title %}{{ page.title }}{% endblock %} {% block main %} <main class="cms-default-layout"> <div class="container py-4"> <h1 class="h3 mb-4">{{ page.title }}</h1> {{ body_html|raw }} </div> </main> {% endblock %}
cms/layouts/three-col.html.twig
Reprend docs/cms-layout.html.twig (6d33521). Variables : page, body_html, docs, current_slug. Route nav : docs.show (garder pour lot 1).
front/index.html.twig — homepage par défaut
Affiché quand site.homeSlug est null. Filet de sécurité pour nouvelles installs (adoption-app).
{% extends 'html.twig' %} {% block main %} <main> <div class="container text-center py-5"> <h1 class="display-6">Bienvenue</h1> <p class="text-muted">Ce site est en cours de configuration.</p> </div> </main> {% endblock %}
Pages d'erreur
bundles/TwigBundle/Exception/error404.html.twigbundles/TwigBundle/Exception/error500.html.twig
Pages minimalistes, compatibles html.twig. Pas de dépendance à site (peut être null en contexte d'erreur).
6. Nettoyage (telaria-app)
templates/docs/cms-layout.html.twig→ supprimer (remplacé par le template bundle)DocsCmsController: garder tel quel structurellement, remplacer le template hardcodé parresolveLayout()
7. PHPUnit
DocsCmsControllerTest:/docs/{slug}→ 200, templatethree-colCmsFrontControllerTest: tester layoutdefaultETthree-col(page en base avec champ renseigné)- Homepage :
GET /avecsite.homeSlug = null→ 200, template bundle "Bienvenue" (pas de redirect login)
8. Ordre d'implémentation
- Bundle
tlr-symfony: champlayout+ migration + templates (cms/layouts/+front/index.html.twig+ error pages) - App
telaria-app: dropdown BO +resolveLayout()dansCmsFrontControlleretDocsCmsController+ suppressiondocs/cms-layout.html.twig - PHPUnit vert →
dev(poseidon) →staging→ récap inbox Chef