Drupal 8 et Composer, un mariage réussi

Mercredi 9 novembre 2016 -

Tuto
Drupal 8 et composer

La puissance de Composer

L’utilisation de librairies/bibliothèques externes (PHP, Javascript) n'a toujours été facile sous Drupal. Heureusement, des modules ont permis de pallier à cette difficulté de manière plus ou moins automatique : librairies, composer_manager ou encore xautoload.

Mais lorsque l’on souhaitait créer un bridge avec une librairie externe PHP, difficile de savoir comment gérer l’autoloader, comme les dépendances … un vrai casse tête.

Pour le plus grand bonheur des développeurs, Symfony 2 se repose naturellement sur composer, pour accéder à une bibliothèque de librairies (packagist.org), gère l’autoloader ainsi que les dépendances en cascade.

Les premières moutures de Drupal 8 n’avaient pas encore un couplage fort avec composer, c'est maintenant le cas pour la version 8.2. Il est, maintenant, possible d’installer Drupal par une simple ligne de commande: ‘composer create-project’, ou en utilisant un mécanisme de template. Il est aussi possible d’installer les modules eux-mêmes via composer, sans module supplémentaire, un vrai régal.

 

Les Repositories/ les dépôts

Historiquement, Drupal a toujours fourni un dépôt (ou repository) pour héberger les développements des modules communautaires, ainsi qu’un espace de documentation et de bugs/demandes, hébergé sur drupal.org. Or, les développeurs Symfony travaillent habituellement sur des repositories Github, qui possèdent les mêmes types d’options.

L'univers Symfony 2 rencontrant l'univers de Drupal, permet d'enrichir les eco-systèmes. Cette confrontation pourrait être à l’origine d’une dispersion des modules (ex: Rules est hébergé sur Github comme sur Drupal.org).

Quel lien avec composer ?

De manière automatique, les modules Drupal 7 et Drupal 8, hébergés sur Drupal.org, sont exposés dans un annuaire dédié. Cela facilite la recherche et normalise leur utilisation.

En revanche, la publication d’une librairie sur packagist, sans être complexe, n’est pas automatique. Par conséquent tout le monde peut faire un peu ce qu’il veut en règle de nommage, de versionning ...

L’idée retenue a été de créer une bibliothèque parallèle : packagist.drupal-composer.org

 

A des fins de simplifications et surtout pour éviter de mixer sur un même projet des modules en version 7 et en version 8, ce dépôt expirera (début 2017) au profit de 2 autres, qui semblent déjà accessibles :

 

Ajouter des dépôts

 

Pour ajouter le support à ces nouveaux repository, il faut déclarer la version qui convient dans le composer.json de votre projet :

$ composer config repositories.drupal composer https://packages.drupal.org/8

Le fichier se verra ajouté la section suivante :


    "repositories": { 
        "drupal": {
            "type": "composer",
            "url": "https://packages.drupal.org/8" 
        }
    }
}

Pour ajouter un module à votre projet :

$ composer require drupal/rules

ou avec :

$ composer require “drupal/rules ~3.0”

 

Cette ligne de commande (ajout du repository), n'est pas naturelle/habituelle. A cet effet, DrupalConsole facilite cela enchaînant ces deux opérations en une seule ligne :

$ drupal module:download drupal/rules --composer

 

Utilisation d’un template

Pour se simplifier encore un peu plus la vie, un projet permet de partir d’un template de site avec un fichier composer.json évolué et quelques ajustements en terme d’arborescence des fichiers : https://github.com/drupal-composer/drupal-project

$ composer create-project drupal-composer/drupal-project:8.x-dev some-dir --stability dev --no-interaction

Il sera, prochainement, également possible de réaliser la même chose avec DrupalConsole, de la manière suivante :

$ drupal site:new some-dir --composer

Ce template apporte quelques optimisations intéressantes :

  • un répertoire web dans lequel Drupal sera placé, vendor est placé à l’extérieur, tout comme les scripts et fonctions drush
  • les modules, thèmes et profiles communautaires sont placés dans un sous-répertoire ‘contrib’
  • les droits d’accès aux fichiers de settings sont modifiés
  • les applications drush et drupal dans vendor/bin sont téléchargées

 

Gestion des patchs

Le dernier point à ne surtout pas négliger est l’utilisation de patchs pour les modules communautaires.

Dans un contexte professionnel, il est habituel d’utiliser un fichier ‘project.make’ dans lequel on liste les modules, leur version et parfois les patchs à appliquer.  La commande ‘drush make’ fait alors le travaille de construction à partir de la liste.

Avec composer

Il faut utiliser une librairie supplémentaire : https://github.com/cweagans/composer-patches

$ composer require “cweagans/composer-patches”:”~1.0"

 

Deux autres opérations sont nécessaires :

 

  • Modifier le fichier ‘composer.json’ :


{
  "require": {
    "cweagans/composer-patches": "~1.0",
    "drupal/drupal": "8.0.*@dev"
  },
  "config": {
    "preferred-install": "source"
  },
  "extra": {
    "enable-patching": true,
    "patches-file": “composer.patches.json”
  }
}

  • Créer un fichier dédié pour y stocker tous les patchs : composer.patches.json

{
  "patches": {
    "drupal/project1": {
      "Patch title #1": "http://example.com/url/to/patch.patch",
      "Patch title #2": "http://example.com/url/to/patch.patch"
    }
  }
}

La commande ‘composer update’ réalisera ensuite la construction.

 

Note : si les patchs sont accessibles sur des urls en simple HTTP, il sera nécessaire d’ajouter une ligne de configuration pour lever une sécurité :

{
  "config": {
    "secure-http": false
  }
}

Source : https://github.com/cweagans/composer-patches#using-patches-from-http-urls

 

Pour résumer

Sentir la puissance de composer avant même d’avoir touché à Drupal 8 rassure énormément.

Alors que nous utilisions des ‘drush make’, en tâtonnant pour configurer l’import des librairies externes, combiner des fichiers composer.json manuellement ou avec des scripts, en priant pour que l’autoloader fonctionne bien ... tout cela se fait proprement et de manière fiable. Alors, place au développement !
 

 

Auteur : Sébastien Malot , CTO Actualys