Contrôler l’ordre d’exécution des hooks dans Drupal

Contexte

Drupal et son mécanisme de hook permet de modifier le comportement par défaut du core ou d’autres modules depuis ses propres modules.

Pour chaque appel à une fonction hookable Drupal va rechercher dans tous les modules activés si ce module implémente ou non ce hook. Si un ou des modules implémentent le hook, Drupal va automatiquement les appeler.

Dans la majorité des cas, tout se passe bien, mais il arrive qu’on ait besoin de contrôler l’ordre d’exécution de ces hooks. Par exemple, lorsqu’un module A ajoute une fonctionnalité via un hook et qu’on souhaite modifier cet ajout dans un autre module B. Dans ce cas, il faut impérativement que le hook du module B soit appelé après celui du module A.

Mécanisme “standard”

Par défaut, pour définir l’ordre dans lequel les hooks vont être appelés, Drupal va utiliser la notion de poids (weight) des modules. Les hooks dont les modules ont le poids le plus faible seront appelés en premier. Pour les modules d’un même poids, l’ordre alphabétique du nom du module sera utilisé.

Malheureusement le poids d’un module n’est pas facilement modifiable. On peut le faire en allant mettre à jour directement la table system en base de données mais ce n’est ni très pratique, ni portable (la modification devra être effectuée sur tous les différents environnements sur lesquels le site est déployé).

Il est possible d’automatiser cette mise à jour de la base en exécutant automatiquement un script SQL lors de l’installation du module, mais il faut bien connaître le poids des autres modules et être sûr que ceux-ci ne changeront pas.

De plus, l’utilisation du poids du module aura un effet global sur l’ensemble des hooks. On ne pourra pas contrôler l’ordre d’exécution pour un hook particulier.

Solution

Drupal 7 nous apporte une solution pour traiter “proprement” et avec un bon degré de paramétrage cette problématique grâce à l’introduction du hook_module_implements_alter().

Ce hook prend deux paramètres : $implementations et $hook. Le paramètre $hook indique le type de hook (ex : form_alter, node_view_alter,…). On peut donc facilement ne modifier l’ordre que pour un type de hook donné.

Le paramètre $implementations contient la liste des implémentations de ce hook. C’est ce tableau qu’il faut modifier pour jouer sur l’ordre. On peut par exemple forcer le hook de notre module à s’exécuter en dernier en enlevant l’élément correspondant du tableau et en le remettant ensuite à la fin. Par exemple :

Grâce à ce hook, on peut gérer finement l’ordre d’exécution de différents modules et le personnaliser pour chaque type de hook. On peut même désactiver une implémentation si cela est nécessaire en l’enlevant du tableau.

Vous aurez peut-être remarqué que le hook_module_implements_alter() est lui-même un hook. Reste à savoir si on peut contrôler l’ordre d’exécution de ce hook_module_implements_alter()… 🙂

Développement web ,

Leave a Reply

Your email address will not be published. Required fields are marked *