Drupal theme api : Hook into the theme (partie 1)

Drupal_logo

Je vous propose une série d'articles qui ont pour but de discuter de l'api Drupal dédiée au rendu et à l'affichage, afin de mieux comprendre ce processus et la manière dont s'articulent les nombreux hooks et fonctions à disposition du développeur et du thémeur.

Ces articles sont basés sur la version 7.x de Drupal. Sachez cependant qu'un certain nombre d'éléments restent très similaires voire identiques en ce qui concerne la version 8.x.

Ce premier article présentera la theme api : comment sont générés des éléments html grâce aux fonctions de thème et comment les surcharger. Un second article, toujours sur la theme layer, se focalisera sur les templates et les fonctions de preprocess. D'autres articles sont prévus afin de discuter de la render api et autres subtilités.

Introduction

Créons pour commencer un nouveau thème vierge.

Plaçons ce fichier dans un dossier du même nom : /sites/all/themes/footheme/footheme.info

Remarque : de la même manière que Drupal scanne récursivement les répertoires sites/*/modules à la recherche de .info et de .module pour les modules, il scanne le répertoire sites/*/themes à la recherche de .info pour les thèmes.

Voici le minimum pour créer un thème et l'activer en BO. Une fois activé on se retrouve avec un site totalement épuré. Si on regarde le code source html, on constate pourtant une structure html déjà construite et des fichiers css/js déjà chargés alors que notre thème ne déclare rien de tout cela.

C'est que le theme system gère en effet déjà tout cela. Le thème que nous venons de céer n'est qu'une manière propre de mettre en forme des éléments déjà produits.

Le theme system représente toute l'api des fonctions qui permettent le rendu final et altérable par l'utilisateur à différents niveaux de l'application. La plupart se trouvent dans les fichiers theme.inc et theme.api.php avec leur lot de helpers (liste des thèmes, chemin du thème actif, ...). Nous allons ici nous focaliser sur une fonction centrale : theme().

Theme layer

La fonction "theme()" centralise toutes les requêtes d'affichage, qu'elles doivent passer par des templates ou non.

Cette fonction s'utilise avec 2 paramètres : theme($hook, $variables = array())

- $hook représente le composant de thème à appeller, ou "theme hook"
- $variables représente un tableau de données à traiter

Theme() délègue ainsi son travail à un theme hook qui est responsable de générer le html attendu. Celui-ci peut être une fonction - c'est à dire une fonction de thème - ou un template. Chaque élément Drupal vient ainsi avec sa propre structure html. En fait, chaque fois qu'un développeur doit produire un affichage particulier, il est recommandé et usuel de passer par une fonction de thème ou un template, afin de séparer la logique de l'affichage et faciliter la vie des thémeurs qui n'auront pas à toucher au module, et sûrement pas au core !

Dans la documentation Drupal, les différentes fonctions et hooks à utiliser pour se greffer à la theme layer peuvent être assez confus au premier abord : theme(), theme_HOOK(), hook_theme()... Clarifions tout cela en commençant par hook_theme().

hook_theme()

On utilise cette fonction chaque fois qu'on souhaite créer un nouveau theme hook. C'est le point d'entrée avec la theme layer. Imaginons que je développe un module "Foo". Alors comme avec n'importe quel autre "hook", on implémentera hook_theme() dans le fichier foo.module :

Fonctions de thème : theme_HOOK()

Nous avons déclaré ici un nouveau theme hook identifié par "bar" et dont la fonction de thème s'appellera, selon la convention en vigueur, theme_bar(). Déclarons-la, toujours dans notre fichier foo.module :

Ici ce qu'il faut retenir, c'est que la fonction theme_HOOK() doit retourner une "string" avec son balisage html. Pour s'en servir, on pourra alors l'appeler avec theme() : $html = theme('bar', $variables).

Toutes les fonctions natives de thème de Drupal sont définies ainsi. L'implémentation de hook_theme() par Drupal - cf. fonction drupal_common_theme() dans le fichier common.inc - déclare ainsi tous les theme hooks usuels : "table", "breadcrumb", "menu_tree", etc. Leurs fonctions de thème sont, respectivement, theme_table(), theme_breadcrumb(), theme_menu_tree(), etc.

On peut ainsi facilement générer une table html avec $table = theme('table', array('header' => $header, 'rows' => $rows)) ou un fil d'ariane avec $breadcrumb = theme('breadcrumb', array('breadcrumb' => $breadcrumb).

Remarque : La documentation précise qu'il faut éviter d'avoir recours à theme() directement et préférer la fonction render(). Nous verrons plus tard pourquoi dans un article dédié à la render api. En attendant, sachez qu'il est parfaitement valide d'utiliser theme() dans ses modules et parfois aussi dans ses templates !

Cependant, le html généré peut ne pas toujours correspondre à nos besoins. Il est très courant par exemple de vouloir modifier le fil d'ariane, comme c'est le cas du thème Garland (fourni en standard avec Drupal).

Se pose donc la question de surcharger ces fonctions de thème. Jusqu'ici nous avons appris d'où elles viennent et nous savons également comment en créer de nouvelles depuis un module. Voyons comment les modifier grâce à un thème.

Surcharge de fonctions de thème

Reprenons notre thème Footheme et ajoutons à côté de footheme.info un nouveau fichier nommé template.php.

Son but est de contenir toutes les implémentations de hooks et/ou de fonctions de thème que l'on souhaitera overrider. Ainsi, pour surcharger theme_bar() il suffira d'y déclarer :

Nous pouvons alors apporter les modifications voulues, voire modifier complètement le fonctionnement de la fonction de thème originale.

Résumé

En résumé, nous avons vu ensemble les différents hooks et fonctions qui permettent d'utiliser la theme layer de Drupal afin de générer du html grâce aux fonctions de thème et comment les modifier.

Il est aussi possible de réécrire les fonctions de thème via des templates au nommage spécifique, et de passer aux theme hooks autre chose que des variables. Je vous invite pour en savoir plus à lire la suite consacrée aux templates et aux fonctions de preprocess.

Resources

La theme layer : https://www.drupal.org/node/933976
Liste des fonctions de theme.inc : https://api.drupal.org/api/drupal/includes%21theme.inc/7.x

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.