Aller au contenu

Domain Config

Le module Domain Config fournit des surcharges de configuration par domaine. Il permet à chaque domaine d'avoir son propre nom de site, ses paramètres de thème, sa page d'accueil par défaut ou toute autre configuration -- le tout depuis une seule installation Drupal.

Ce module ne couvre que les surcharges par domaine. Les surcharges par langue qui s'y ajoutent (indexées par couple (domain, langcode)) sont fournies par le sous-module optionnel Domain Config Language, où elles sont décrites.

Architecture : 2.x vs 3.x

Domain Config 3.x est une refonte complète de la manière dont les surcharges de configuration par domaine sont stockées et résolues. La version 2.x utilisait une solution interne personnalisée, tandis que la 3.x s'appuie sur l'API native Config Collections de Drupal.

L'approche 2.x (legacy)

Dans Domain 2.x, les surcharges par domaine étaient stockées en tant qu'objets de configuration séparés dans la collection par défaut, selon une convention de nommage :

domain.config.{domain_id}.{config_name}

Par exemple, pour surcharger le nom du site sur one_example_com :

domain.config.one_example_com.system.site

Ces objets coexistaient avec toutes les autres configurations dans le stockage par défaut. Au moment de l'exécution, un résolveur personnalisé interceptait les chargements de configuration, détectait le domaine actif, construisait le nom de la surcharge, tentait de le charger, puis fusionnait le résultat par-dessus la configuration de base.

Limitations de cette approche :

  • Les objets de configuration polluaient l'espace de noms de la collection par défaut.
  • Le schéma de nommage était fragile -- l'expression régulière pour extraire l'identifiant du domaine et le nom de configuration à partir d'une chaîne plate était sujette aux erreurs.
  • Aucune intégration avec ConfigFactoryOverrideInterface de Drupal -- le mécanisme de surcharge était entièrement personnalisé.
  • L'export/import de configuration ne reconnaissait pas ces objets comme des surcharges -- ils apparaissaient comme des objets de configuration ordinaires.
  • Les événements de configuration (save, delete, rename) nécessitaient une propagation manuelle.

L'approche 3.x (config collections)

Domain Config 3.x stocke les surcharges dans des config collections Drupal -- une fonctionnalité Drupal de premier ordre conçue exactement pour cet usage. Les collections sont des partitions virtuelles du stockage de configuration qui partagent le même backend (système de fichiers, base de données, etc.) mais sont logiquement séparées.

Nommage des collections :

Type Format Exemple
Domaine seul domain.{domain_id} domain.one_example_com

Au sein d'une collection, l'objet de configuration conserve son nom d'origine. Par exemple, la surcharge du nom du site pour one_example_com est stockée sous le nom system.site dans la collection domain.one_example_com -- et non sous un nom aplati et altéré.

Avantages clés :

  • Séparation nette entre la configuration de base et les surcharges.
  • API Drupal standard (ConfigFactoryOverrideInterface).
  • Support correct de l'export/import de configuration -- les collections sont exportées sous forme de sous-répertoires.
  • Les événements de configuration (save, delete, rename) sont gérés automatiquement.

Le sous-module optionnel Domain Config Language ajoute une seconde collection (domain.{domain_id}.language.{lang_code}) au-dessus de celle par domaine, pour les sites qui ont besoin de surcharges indexées à la fois par domaine et par langue.

Fonctionnement à l'exécution

Résolution des surcharges

Lorsque Drupal charge un objet de configuration (par ex., system.site), la config factory demande à tous les services de surcharge enregistrés de fournir leurs surcharges. Domain Config enregistre un service de surcharge :

  • domain.config_factory_override (priorité -253) -- charge la surcharge par domaine depuis la collection domain.{domain_id}.

Le résultat final fusionné suit cette cascade :

Configuration de base (collection par défaut)
  ↓ fusionnée avec
Surcharge par domaine (collection domain.{domain_id})
  = Configuration finale au runtime

Exemple avec system.site sur le domaine two_example_com :

# Configuration de base (collection par défaut) :
system.site:
  name: "My Site"

# Surcharge par domaine (collection domain.two_example_com) :
system.site:
  name: "Two"        # remplace "My Site" par "Two"

# Résultat final au runtime : name = "Two"

Lorsque domain_config_language est également installé, une couche supplémentaire (domain, langcode) s'ajoute à cette cascade -- voir la documentation de Domain Config Language.

Contexte de domaine

Le domaine actif est déterminé par DomainNegotiationContext, qui est injecté dans le service de surcharge. Le contexte est défini lors de l'événement kernel request par DomainSubscriber et peut également être modifié programmatiquement (par ex., par Domain Config lui-même lorsqu'il compare les configurations entre domaines).

Lorsqu'aucun domaine n'est actif (par ex., lors de commandes Drush sans contexte de domaine), aucune surcharge n'est appliquée et la configuration de base est utilisée.

Négociation anticipée pour les middlewares

Si des middlewares tiers ont besoin des surcharges domain_config avant que l'événement kernel request ne se déclenche, installez le module Domain Early Negotiation (domain_early_negotiation) du projet Domain Extras. Voir la documentation Domain pour plus de détails.

Mise en cache

Le service de surcharge fournit un suffixe de cache basé sur l'identifiant du domaine courant. Cela garantit que les objets de configuration mis en cache pour un domaine ne sont pas servis à un autre.

Les métadonnées de cache incluent le cache context domain, de sorte que le rendu qui dépend d'une configuration spécifique à un domaine est correctement diversifié.

Enregistrement des surcharges

Quand on enregistre une surcharge, DomainConfigOverrideEditable::save() ne garde que les clés dont la valeur change vraiment par rapport à la base. Le reste est ignoré : la surcharge ne contient que les différences.

Cela fonctionne pareil pour les deux façons d'écrire dans la config :

  • ConfigFormBase, qui appelle set() clé par clé,
  • ConfigEntityStorage::doSave(), qui appelle setData() avec toute la config d'un coup.

Le résultat stocké est le même : une surcharge minimale.

Deux conséquences utiles à retenir :

  • remettre une clé à sa valeur de base la retire de la surcharge ;
  • modifier une autre clé sur une config déjà surchargée (par exemple changer la région d'un bloc dont seul le label est surchargé) ne touche pas à la surcharge existante : la nouvelle différence vient simplement s'y ajouter.

À l'inverse, la lecture sans surcharge (ConfigEntityStorage::loadMultipleOverrideFree()) est un problème différent et n'est pas traitée ici. Voir #3587744 et le sous-module domain_config_entity_ui prévu dans domain_extras.

Limitation connue : raccourcir une liste

Une surcharge par domaine ne peut pas raccourcir une sequence : les éléments présents au-delà de la longueur de la surcharge dans la base restent visibles. Cette limite vient du core de Drupal, pas de domain_config.

Exemple. La base contient allowed_tags: ['a', 'em', 'strong', 'p']. La surcharge la remplace par ['a', 'em', 'strong'] — on souhaite retirer 'p'. À la lecture, le core fusionne via NestedArray::mergeDeepArray([$base, $override], TRUE). La fusion parcourt les tableaux clé par clé, donc 'p' (à l'index 3) reste, et le visiteur voit toujours les quatre éléments.

Le format des surcharges ne sait pas dire « ignore l'index N de la base ». domain_config ne peut donc pas corriger ce comportement sans s'éloigner de la façon dont les autres surcharges Drupal fonctionnent (settings.php, surcharges de modules, etc.).

Selon votre cas, plusieurs solutions existent :

  • si vous contrôlez le schéma, remplacer la sequence par un mapping associatif : les surcharges fonctionnent normalement sur les maps associatives ;
  • surcharger plutôt la clé parente et y écrire la liste complète voulue via du code ;
  • modifier directement la configuration de base.

Événements du cycle de vie de la configuration

Domain Config 3.x gère correctement les événements du cycle de vie de la configuration afin de maintenir les surcharges de domaine synchronisées avec la configuration de base :

Événement Comportement
Config save Pour chaque domaine, si une surcharge de domaine existe pour la configuration sauvegardée, elle est filtrée pour supprimer les valeurs identiques à la nouvelle configuration de base (en ne conservant que les surcharges effectives).
Config delete Si la configuration de base est supprimée, la surcharge de domaine correspondante est supprimée de toutes les collections de domaine.
Config rename Si la configuration de base est renommée, la surcharge est renommée dans toutes les collections de domaine pour correspondre.

Export et import de configuration

Comme les surcharges résident dans de véritables collections Drupal, elles s'intègrent au système d'export/import de configuration :

Structure du répertoire d'export :

Le FileStorage de Drupal convertit les points dans les noms de collection en séparateurs de répertoire. La collection domain.one_example_com devient le répertoire domain/one_example_com/ :

config/sync/
  system.site.yml                              # Configuration de base
  domain/
    one_example_com/
      system.site.yml                          # Surcharge par domaine
    two_example_com/
      system.site.yml

Les modules peuvent également fournir des surcharges de domaine par défaut en utilisant la même convention dans leur répertoire config/install/ :

mymodule/config/install/
  domain/
    one_example_com/
      system.site.yml
    two_example_com/
      system.site.yml

Lorsqu'une nouvelle entité de domaine est créée, installDomainOverrides() appelle ConfigInstallerInterface::installCollectionDefaultConfig() de Drupal pour installer les valeurs par défaut fournies par les modules pour la collection de ce domaine.

Lorsque domain_config_language est installé, le même schéma s'étend avec un sous-répertoire language/{langcode}/ sous chaque dossier de domaine -- voir la documentation de Domain Config Language.

Domain Config UI

Le module optionnel Domain Config UI fournit une interface utilisateur pour gérer les surcharges par domaine directement depuis les formulaires de configuration existants.

Voir la documentation Domain Config UI pour plus de détails sur :

  • L'activation/désactivation des surcharges par configuration et par domaine.
  • Le bouton de bascule intégré dans les formulaires d'administration.
  • Les configurations non autorisées.
  • Le contrôle programmatique via des alter hooks.

Migration de 2.x vers 3.x

La migration 2.x → 3.x est portée par domain_config_language parce que chaque site 2.x ayant des surcharges par domaine avait également le module language activé, et le format de stockage hérité était le même que des surcharges par langue soient impliquées ou non. domain_config_update_10002() installe automatiquement domain_config_language pendant drush updatedb quand language est activé, et la migration s'exécute depuis domain_config_language_install().

Voir la documentation de Domain Config Language pour les étapes de migration complètes et les notes de retour arrière.

Services

Service Classe Rôle
domain.config_factory_override DomainConfigFactoryOverride Surcharges de configuration par domaine (priorité -253)
domain_config.library.discovery.collector DomainConfigLibraryDiscoveryCollector Décore la découverte de bibliothèques pour varier par domaine

Issues associées