LydiaCMS se compose de 13 paquets Composer de production, noyau compris, et de trois outils de développement. Hormis le noyau, chaque paquet ajoute une capacité et s’installe séparément.
Paquets
- core — démarrage de l’application, DI, routage, permissions, traductions et base de l’administration
- menu, blog, forms, attributes, currencies, location, socials, units — modules de contenu, chacun avec ses propres entités, routes et migrations
- integration, data, api, backup — import depuis des services web, un modèle de données configurable avec historique des versions, l’interface REST/MCP, sauvegardes et restauration
- phpstan, rector, ecs — outils de développement, dont il est question dans la partie sur la qualité
Comment un paquet se branche
- Il s’enregistre par une seule extension Nette (DI) : entités, routes, services et migrations appartiennent à leur propre paquet.
- Chaque paquet a une version et des migrations idempotentes. La mise à jour de la base de données est une seule commande,
lydiacms:upgrade.
Génération de l’administration à partir des métadonnées (metadata-driven CRUD scaffolding)
Les grilles et les formulaires naissent des métadonnées des entités Doctrine (plus de 100 entités). Un gabarit personnalisé n’est écrit que là où les données ne sont pas plates : l’arbre du menu, le constructeur de formulaires ou les variantes de réseaux sociaux. Un détail comme une aide contextuelle ou un texte indicatif se règle par un attribut sur le champ.
Multilinguisme et SEO dans le modèle de données
Chaque enregistrement existe en variantes linguistiques (aujourd’hui CS, EN, DE, FR, ES et SK) et chaque variante est un enregistrement distinct dans la base de données. Ajouter une langue ne demande donc aucune modification du code. Les données SEO (titre, description, image et slug) se définissent séparément pour chaque enregistrement et chaque langue.
Les adresses des pages sont stockées dans la base de données avec le chemin complet à travers les ancêtres. Cette page vit par exemple à /projets/lydiacms/architecture. Une adresse raccourcie sans les ancêtres est redirigée de façon permanente (301) vers le chemin complet. Quand je change le slug d’une page, l’ancienne adresse est redirigée vers la nouvelle.
Les permissions s’héritent le long de l’arbre des contextes
Les contextes forment un arbre (système → frontend, admin, API → paquet → sous-module → enregistrement) et chacun est une source d’ACL. Une règle par défaut se définit une seule fois pour tout l’espace de noms (l’administration et l’API sont fermées, le frontend est ouvert) et tout ce qui se trouve dessous en hérite. Un nouveau sous-module ou enregistrement n’a donc besoin d’aucune règle propre. La règle d’un paquet vaut pour tous ses sous-modules, et la règle d’un sous-module, qu’elle autorise ou interdise, la remplace.
- L’accès à l’administration se déduit des règles. Quiconque a le droit d’afficher quoi que ce soit dans l’administration y accède. Il n’existe aucun autre interrupteur.
- Un plafond de permissions. Personne ne peut autoriser ni attribuer plus qu’il n’a lui-même, si bien que personne ne peut augmenter ses propres droits.
- Un préréglage pour le travail éditorial complète en un clic les règles pour les pages, le blog, le menu et les médias, et n’accorde jamais la suppression, l’export, les paramètres ni la gestion des utilisateurs et des rôles. Le résultat, ce sont des règles ordinaires que l’on peut continuer à modifier dans la matrice.
Une permission (afficher, créer, modifier, supprimer, changer l’état, exporter) a une portée admin, frontend ou API et peut être limitée à des contextes par un motif avec jokers, par exemple api.core.**. La même ACL s’applique à l’administration et à l’interface pour l’IA.
Médias et tâches cron dans l’administration
La médiathèque indique pour chaque fichier où il est utilisé, si bien que l’on voit ce que sa suppression casserait. Les tâches cron ont un enregistrement propre pour chaque exécution, avec son résultat et l’heure de la prochaine.