Si vous utilisez composer pour gérer votre instance de Drupal, vous avez parfois besoin d'appliquer un patch (de votre conception ou depuis drupal.org) que ce soit pour un module tiers ou pour le core.
Si on est "à l'ancienne" on a le core et les module sous gestionnaire de version (git par exemple), cela reste simple, vous appliquez le patch et commitez le tout.
En utilisant composer, nous avons uniquement le "cutom" qui est versionné, avec les fichiers composer.json et composer.lock qui contiennent la liste des modules utilisés et leurs version spécifique. Donc pas possible d'appliquer un patch comme plus haut.
Par contre on peut à l'aide d'un dépendance spécifier les patchs que l'on veut utiliser directement dans le fichier composer.json, regardez si ça ce trouve le module est déjà installé; il s'agit de cweagans/composer-patches.
s'il n'est pas présent :
composer require cweagans/composer-patches
ensuite pour appliquer un patch, on doit ajouter les éléments suivants dans la partie "extra" du fichier composer.json :
En théorie
"patches": {
"package": {
"description libre": "Url du patch"
}
}
Un patch simple
exemple pour un patch pour mimemail :
"patches": {
"drupal/mimemail": {
"Fix mimemail error on admin form": "https://www.drupal.org/files/issues/mime-mail-error-message-on-admin-form-with-webprorfiler-2719981-3.patch"
}
}
Plusieurs patchs pour un même module
Si vous avez plusieurs patchs pour un même module, séparez-les par une virgule :
"patches": {
"drupal/mimemail": {
"Fix mimemail error on admin form": "https://www.drupal.org/files/issues/mime-mail-error-message-on-admin-form-with-webprorfiler-2719981-3.patch",
"patch 2": "https://www.drupal.org/files/issues/mime-mail-error-message-on-admin-form-with-webprorfiler-2719981-3qdqsdqsd.patch"
}
}
Plusieurs patchs pour plusieurs modules
Si vous avez plusieurs modules à patcher, même principe :
"patches": {
"drupal/mimemail": {
"Fix mimemail error on admin form": "https://www.drupal.org/files/issues/mime-mail-error-message-on-admin-form-with-webprorfiler-2719981-3.patch",
"patch 2": "https://www.drupal.org/files/issues/mime-mail-error-message-on-admin-form-with-webprorfiler-2719981-3qdqsdqsd.patch"
},
"drupal/monautremodule": {
"ma description du patch": "https://www.drupal.org/files/issues/mimhfhmin-form-with-webprorfiler-2719981-3.patch",
}
}
Patcher le core, ou un de ses modules
Pour patcher le core ou un module du core (views par exemple), comme précisé par Mika dans les commentaires, il faut utiliser la clé : 'drupal/core'
"patches": {
"drupal/core": {
"patch 1": "https://www.drupal.org/Url-du-patch1.patch",
"patch 2": "https://www.drupal.org/Url-du-patch2.patch"
}
}
Patch « local »
Voyons maintenant le cas d'un patch local, car parfois on créé nos propres patchs sans forcement les proposer sur drupal.org.
Ici, on suppose que le patch est stocké dans un dossier "patchs", au même niveau que le fichier composer.json :
"patches": {
"drupal/monmodule": {
"Patch custom stocké localement": "patchs/patch-custom-stocke-localement.patch"
}
}
Installation et application des patchs
Enfin update et install pour que le(s) modules patchés soient supprimés, re-téléchargés et enfin patchés.
composer update
composer install
«Patching is disabled. Skipping.»
Si vous obtenez ce message, c'est peut-être car vous n'avez pas ajouté la section "patches" dans la section "extra" du fichier composer.json.
Commentaires
Petit commentaire pour ceux qui aurons mon problème.
Je voulais patcher le core et j'ai essayé plusieurs choses afin de réussir.
Lorsqu'on patch un module contrib il faut en effet mettre "drupal/mymodule" mais quand il s'agit d'un module du core (exemple: views) core il faut mettre "drupal/core".
J'en ai essayé des choses "drupal/views" "drupal/core/views" "core/views" .... et j'ai essayé "drupal/core" un peu en désespoirs, et comme par hasard c'est la bonne ^^
Je n'ai pas trouver ce détail sur internet donc je le poste ici et sur d'autres forums qui ne parle.
Merci ! j'ai précisé ça dans le post du coup !
Salut Kgaut,
Merci pour ton Blog bien utile, tu as inversé les 2 blocs de code entre "même module" et "plusieurs modules à patcher"...
Ma question: connaîtrais-tu la commande pour générer un patch pour un module ?
Par exemple le module 'image_widget_crop' dont il faudrait modifier la ligne :
"require": {
"drupal/crop": "1.0.0"
},
en
"require": {
"drupal/crop": "1.x"
},
dans sont fichier "composer.json" pour que le module "crop" puis s'installer via composer sans soucis.
Merci, c'est corrigé.
Pour créer un patch pour un module, généralement, je "git clone" le module dans un autre dossier. J'effectue mes modifications puis enfin je génère le patch avec
Et j'utilise ensuite ce patch dans mon composer.json
Super ! merci
Hello,
Merci pour ton post.
SImple question, si un même patch concerne plusieurs packages, y'a un truc particulier à faire?
Je copie le même patch pour les deux packages?
Etant donné qu'un git apply est fait, je peux le laisser que dans un seul module? Quel est la meilleure manière de faire?
Je te remercie!
Bonjour, quels packages sont concernés ? si ce sont des modules du core c'est alors drupal/core, pour une distribution drupal/nom_distrib.
Bonjour, merci de ta réponse.
A vrai dire, ça n'est pas pour du drupal mais plus de la curiosité générale sur un plugin que je vais essayer.
Admettons que j'ai deux dépendances sur deux modules différents dans mon projet, mais, pour une raison tierce, un patch affecte ces deux modules à la fois.
Comment ça se matérialiserait? Dans la mesure ou de ce que j'ai vu, le composer ne fait qu'un "git apply" sur le patch au final, ça signifierait que je ne mettrais le patch que sur l'un des deux modules dans les extra et ça patcherait l'autre de la même manière.
J'ai bon?
En tout cas sympa ton article :)
Salut, tuto très utile. c'est normal qu'après le composer update " - Removing cweagans/composer-patches (1.6.5)" .
J'en profite de poser ma question, j'ai fais la mise à jour et je suis sur drush 9. La commande drush delete-all m'affiche un message bien rouge en me disant que delete-all n'existe pas. J'ai trouvé le patch du module que certains avaient déclaré fonctionnel, mais rien n'y fait.
Si tu as une solution je suis preneur, et je te remercie d'avance.
Merci pour cette mine d'infos !
Est-ce qu'il y a moyen de procéder à un update un peu plus ciblé, qui donc n'applique que les patches et pas toutes les MAJ, dans le cas ou quelques modules ne seraient pas à jour et qu'on souhaiterait juste appliquer le patch ?
du genre :
Il est possible de lancer les update uniquement pour le module que l'on a patché via
Ben oui évidemment ! Suis-je bête ! 😅
Merci !
Bonjour Kgaut,
Aurait-tu une bonne pratique ou simplement un moyen de supprimer correctement un patches appliquer via composer ?
Merci
Ajouter un commentaire