Créer un profil d'installation pour Drupal 8

Un immeuble en verre

Après avoir découvert le principe des profils d'installation de Drupal 8, qui permettent d'industrialiser la production de sites (n'hésitez pas à contacter un développeur Drupal 8 pour connaître plus en détail le potentiel de ces solutions), nous allons explorer plus en détail la création d'un profil.

La création d'un profil d'installation ressemble à s'y méprendre à la création d'un module. On peut noter les quelques différences notables suivantes :

  • Le profil d'installation doit être créé dans le répertoire /profiles situé à la racine de Drupal 8
  • Le fichier [nom].module est remplacé par le fichier [nom].profile

Pour créer notre profil d'installation, nous allons donc créer le répertoire uas (qui sera le nom de notre profil), et allons créer deux fichiers

  • uas.info.yml, qui est le fichier de déclaration du profil
  • uas.profile, qui contiendra les différentes altérations du formulaire d'installation, mais aussi peut contenir toute fonction altérant le comportement de Drupal à l'instar d'un module classique

Ces deux fichiers sont les éléments obligatoires à minima pour créer un profil d'installation. Celui-ci pourra contenir également les fichiers

  • uas.install, pour effectuer certaines taches lors de l'installation initiale de votre profil
  • uas.services.yml, pour déclarer des services
  • uas.routing.yml, pour déclarer des routes spécifiques
  • uas.librairies.yml, pour déclarer des librairies à charger
  • uas.permissions.yml, pour déclarer des permissions spécifiques
  • etc. etc. bref, tout fichier de configuration que l'on peut retrouver dans un module Drupal 8 classique

La déclaration du profil d'installation

Nous créons le fichier uas.info.yml.

name: UAS
type: profile
description: Website factory.
core: 8.x

dependencies:
  #Core modules
  - node
  - block
  - ckeditor
  - config
  - contact
  - etc.

  #Contrib modules
  - token
  - ctools
  - admin_toolbar
  - admin_toolbar_tools
  - pathauto
  - etc.

  #Custom modules
  - uas_image
  - uas_taxonomy

themes:
  - uas_base
  - bootstrap
  - seven

Ce fichier, outre la déclaration du profil d'installation, nous permet de déclarer quels modules et thèmes seront activés et utilisables sur notre site, et durant la phase d'installation. Ce fichier peut nous permettre d'ajouter également des paramètres supplémentaires, par exemple, des fonctionnalités optionnelles à choisir lors du processus d'installation. Par exemple :

configurable_module:
  uas_publication:
      label: Publication
      description: Provide publication content type.
      enabled: true
  uas_slider:
        label: Slider
        description: Provide slider bloc.
        enabled: true

Paramètres que nous pourrons utiliser par la suite pour construire les étapes de configuration de notre profil.

Les deux principaux fichiers que nous allons utiliser pour initier le profil d'installation, outre tous les autres fichiers de configuration possibles, sont :

  • uas.profile : pour pouvoir modifier les étapes de configuration du processus d'installation
  • uas.install : pour procéder à certaines configurations du site lors de son installation

Personnalisation des étapes de configuration du profil d'installation

Si le fichier uas.profile est similaire au fichier .module d'un module classique, et donc qu'il est tout à fait possible d'y inclure des hook pour altérer le comportement du site, il est conseillé de conserver les contenus de ces fichiers essentiellement orientés vers l'installation et la configuration initiale du profil d'installation et de fournir toute altération, nécessaire au fonctionnement du site, au moyen d'un module inclus dans le profil. En effet, il sera plus aisée à moyen terme de maintenir un module spécifique, plutôt que le profil d'installation lui-même.

Dans l'exemple ci-dessous nous allons altérer le formulaire de configuration par défaut du site et ajouter quelques étapes supplémentaires permettant de personnaliser la configuration du site au moment de son installation.

/**
 * @file
 * Uas profile.
 */

use Drupal\Core\Form\FormStateInterface;
use Drupal\contact\Entity\ContactForm;

/**
 * Implements hook_form_FORM_ID_alter() for install_configure_form().
 *
 * Allows the profile to alter the site configuration form.
 */
function uas_form_install_configure_form_alter(&$form, FormStateInterface $form_state) {
  $form['site_information']['site_name']['#attributes']['placeholder'] = t('Developpement Drupal');
  $form['site_information']['site_name']['#default_value'] = 'Flocon de toile - freelance expert Drupal';
  $form['site_information']['site_mail']['#default_value'] = 'contact@website.name';

  $form['regional_settings']['site_default_country']['#default_value'] = 'FR';
  $form['regional_settings']['date_default_timezone']['#default_value'] = 'Europe/Paris';

  $form['update_notifications']['update_status_module']['#default_value'] = array();

  $form['#submit'][] = 'uas_form_install_configure_submit';
}

/**
 * Submission handler to sync the contact.form.feedback recipient.
 */
function uas_form_install_configure_submit($form, FormStateInterface $form_state) {
  $site_mail = $form_state->getValue('site_mail');
  ContactForm::load('feedback')->setRecipients([$site_mail])->trustData()->save();
}

/**
 * Implements hook_install_tasks().
 */
function uas_install_tasks(&$install_state) {
  return [
    'configurable_profile_dependencies' => [
      'display_name' => t('Additionnals features'),
      'display' => TRUE,
      'type' => 'form',
      'function' => 'Drupal\uas\Form\ConfigurableProfileDependenciesForm',
    ],
    'webmestre_account' => [
      'display_name' => t('Webmestre account'),
      'display' => TRUE,
      'type' => 'form',
      'function' => 'Drupal\uas\Form\WebmestreAccountForm',
    ],
  ];
}

Nous définissons ici quelques paramètres par défaut pour le formulaire de configuration et ajoutons une fonction de Callback supplémentaire pour configurer le formulaire de contact (installé par défaut) avec l'adresse mail saisie. 

Et nous ajoutons 2 étapes supplémentaires dans le processus d'installation et de configuration de Drupal 8 : une première étape pour permettre l'ajout de fonctionnalités supplémentaires et une autre étape pour permettre la création d'un compte pour le gestionnaire du site, qui ne sera donc pas le super administrateur. 

Il ne nous restera plus alors qu'à implémenter nos formulaires déclarés, et par exemple, pour l'étape du choix de fonctionnalités optionnelles, parcourir le fichier uas.info.yml pour y lire les différentes options possibles à proposer à l'utilisateur, que nous avons définies plus haut sous la clé configurable_module

La configuration initiale du site

Le fichier uas.install va nous permettre (par convention) d'implémenter hook_intall() et réaliser ainsi toutes les opérations de configuration initiales qui ne serons pas fournies par des fichiers de configuration .yml.

Nous avons donc deux possibilités pour fournir des configurations initiales :

  • via les fichiers de configuration placés sous le répertoire config/install ou config/optionnal
  • via l'implémentation de hook_install()

La configuration avec les fichiers

En plaçant par exemple le fichier system.theme.yml dans le répertoire config/install, nous configurerons le thème par défaut et le thème d'administration.

admin: seven
default: uas_base
langcode: en

Vous pouvez vous inspirer du profil standard fourni par le coeur de Drupal pour configurer votre site selon cette technique. Vous pouvez aussi utiliser le module Configuration development qui vous permettra d'exporter les configurations sélectionnées dans votre profil avec Drush. Cette méthode permet ainsi de paramétrer progressivement votre site puis d'exporter simplement votre configuration dans votre profil ou un de ses modules.

La configuration par le code

L'implémentation de hook_install() peut vous permettre d'effectuer des configurations similaires à celles fournies par des fichiers de configuration (comme la définition du thème par défaut, si la modification d'un contenu doit utiliser le thème d'administration ou non, de définir des permissions, de paramétrer les comptes utilisateurs, de positionner des blocs, etc).

Elle va permettre aussi de fournir des configurations qu'on ne souhaite pas fournir par des fichiers. Si vous souhaitez fournir une configuration par défaut lors de votre installation, mais ne souhaitez pas la maîtriser en permanence depuis vos fichiers de configuration (nous parlerons dans un prochain billet de cet aspect). Cette approche permettra à l'administrateur du site de modifier ces configurations sans générer de faux positif. Par exemple, le module Pathauto peut être configuré en créant des Pattern pour chaque entité / type de contenu de cette façon.

/**
 * Implements hook_install().
 */
function uas_install() {
  // Instanciate Uas utility class.
  $uas = New Uas();
  $pattern = $uas->createPattern('page', 'node', '[node:title]', ['page' => 'page']);
}

Ceci est également vrai pour les menus. A la fois faisant partie de la configuration, mais surtout étant partie intégrante du contenu et donc susceptibles d'être modifiés par les utilisateurs. Pour ce type de configuration, il convient de recourir alors exclusivement à leur création par ce biais. Surtout si vous souhaitez pouvoir maîtriser la configuration des sites générés par le profil d'installation depuis ses fichiers de configuration sans écraser les modifications effectuées.

function uas_install() {
  $uas->createMenuLink($node->title, 'entity:node/' . $node->id(), 2, 'footer');
}

Un autre cas de figure peut imposer de recourir à hook_install() pour fournir une configuration par défaut. Celui où la configuration fournie par un module est concentrée dans un seul fichier, pour toutes les entités  / types de contenus concernés. Ne connaissant pas à l'avance ce qui sera créé par le profil d'installation, il n'est pas possible de recourir à un fichier de configuration personnalisé. Il faut donc fournir des configurations dynamiques. C'est le cas par exemple du module simple_sitemap dont toute la configuration est stockée dans un fichier unique. Il faudra alors pour chaque fonctionnalité créée, charger la configuration, ajouter les nouveaux éléments de configuration, puis la sauver.

$sitemap = \Drupal::service('simple_sitemap.generator');
// Get current entity type sitemap settings.
$entity_types = $sitemap->getConfig('entity_types');
$entity_types['node_type']['event'] = ['index' => 1, 'priority' => '0.9'];
// Save new entity type settings.
$sitemap->saveConfig('entity_types', $entity_types);

Enfin, un dernier cas d'usage de l'implémentation de hook_install() consiste à générer des contenus par défaut, de démonstration, afin de disposer non seulement d"un site déjà configuré, mais contenant aussi tous les contenus pertinents, offrant ainsi au gestionnaire du site un aperçu immédiat de son fonctionnement, et la possibilité de travailler tout de suite sur son contenu sans passer par une phase d'appropriation plus ou moins longue.

function uas_install() {
  $node = $uas->createNode('page', 'Legal terms', $langcode, '',  '2', $fields);
}

Où la méthode createNode est fournie par la Class $uas.

public function createNode ($type, $title, $langcode, $pattern ='' , $uid = '1', $fields = [], $promote = FALSE, $status = TRUE){
  // Add trailing slash to the pattern and build the path
  $pattern = empty($pattern) ? '' : $pattern . '/';
  $path = '/' . $pattern . $this->cleanAlias($title, $langcode);

  /** @var \Drupal\node\Entity\Node $node */
  $node = Node::create(array(
    'type' => $type,
    'title' => $title,
    'uid' => $uid,
    'status' => $status,
    'promote' => $promote,
    'langcode' => $langcode,
    'path' => $path,
  ));

  if (empty($fields)) {
    $node->save();
    return $node;
  }
  
  else {
    foreach ($fields as $field_name => $value) {
      if ($node->hasField($field_name)) {
        $node->set($field_name, $value);
      }
    }

    $node->save();
    return $node;
  }
}

Bien sûr, il convient d'effectuer chacune des configurations relatives à une fonctionnalité dans le module qui l'installera, ou le profil lui-même si cette configuration est prise en charge directement par le profil et non les modules qu'il peut embarquer.

Que choisir : fichier ou code ?

Le choix va dépendre à la fois du type de configuration (simple ou complexe), et du niveau de maîtrise désirée sur cette configuration une fois qu'elle sera déployée : d'une absence totale de maîtrise à une totale maîtrise, en passant par tous les spectres intermédiaires envisageables. Les 2 méthodes peuvent permettre de faire évoluer les configurations déployées, que ce soit par la simple modification d'un fichier YAML ou l'implémentation d'un hook_update_N().

Pour découvrir encore le potentiel de Drupal 8 pour l'industrialisation de sites, nous aborderons plus en détail, dans un prochain billet, la création d'un package fonctionnel et son intégration dans le profil d'installation.

 

Commentaires

Soumis par Florian (non vérifié) le 20/07/2017 à 23:04 - Permalien

Je bosse en ce moment sur le développement d'un profil, mais un aspect me gène lors d'une nouvelle installation D8 (8.3.5) le choix des différents profils n'est plus proposé, mon nouveau profil est choisit par défaut, est-ce le fonctionnent normal ou une config manquante?

Soumis par fabrice le 20/07/2017 à 23:25 - Permalien

Bonjour, tu n'aurais pas par hasard mis la clé distribution: (avec name et langcode comme propriétés) dans le fichier info.yml de ton profil ? Ce qui permet de squizzer cette étape de choix de la langue et du profil.

Oui j' ai rapidement lu cette doc, mais c'est un parcours du combattant pour récup les infos, je ne vois pas comment on peut deviner les couples clé: valeur que l'on peut utiliser dans les fichiers yml >< en tout cas merci pour les infos et cet article qui m'a fait progresser ;)

Ajouter un commentaire