Changer de thème Drupal à la volée

Le changement de thème à la volée est un must pour tous site un peu évolué. Dans sa version basique cela consiste à séparer le thème d'administration (backoffice) de celui du site lui-même (frontoffice). De manière plus évoluée cela permet de gérer proprement différents jeux de régions (entre la page d'accueil et les pages intérieurs par exemple), ou encore de proposer un thème spécifique pour les navigateurs mobiles.

À partir de sa version 6 (5?) Drupal propose une séparation de sélectionner un thème pour le backoffice avec la possibilité d'englober les formulaires d'édition de contenu. Pour aller plus loin dans la logique de sélection d'un thème en fonction de l'url, du user-agent ou de la position de la lune, il faut passer par du code custom.

A la mode Drupal 6

En Drupal 6 ou 7, tout commence par la création dans votre projet d'un module custom que nous appellerons ici mon_module.

Ensuite, dans le fichier mon_module.module il nous faut implémenter un hook_init. Ce hook est appelé à chaque démarrage de drupal, juste après l'activation du module, et avant toute autre opération. C'est donc l'endroit idéal pour opérer notre changement de thème.

/** Implémentation du hook_init. */
function mon_module_init() {
}
Le module de base

Maintenant pour le changement du thème en lui-même, attention, c'est super compliqué :

/** Implémentation du hook_init. */
function mon_module_init() {
  // Si l'URL est node/*/track
  if (drupal_match_path($_GET['q'], 'node/*/track') {
     // On bascule sur le thème défini dans admin/settings/admin
     $GLOBALS['custom_theme'] = variable_get('admin_theme', 'garland');
  } elseif
  // Sinon, si le nom de domaine est m.XXXX (site mobile)
  if (preg_match('#^m(.*).(.*)$#i', $_SERVER['HTTP_HOST'])) {
     // On bascule sur le thême mobile
     $GLOBALS['custom_theme'] = 'mon_theme_mobile';
  }
}
Le module de base

En fait non, cela n'a rien de compliqué du tout, et c'est ici un bon exemple de l'intérêt à coder ses propres modules plutôt que d'utiliser systématique des brouettes de modules contribs dont il faudra gérer les bugs.

Comme vous l'aurez compris, la variable globale custom_theme (après on se moquera de WordPress et de son usage des Globals ;-) est utilisé par Drupal pour basculer sur un autre thème que le thème principal, sous réserve que celui-ci soit activé ou paramétré comme thème de maintenance.

Au passage notez la fonction drupal_match_path bien pratique pour valider une chaîne de caractères par rapport à une liste de motifs (séparés par des \r\n) et variable_get('admin_theme', 'garland') permettant de lire dans la configuration le thème d'administration configuré dans admin/settings/admin.

A la mode Drupal 7

Avec Drupal 7 le principe est strictement le même sur ses fondamentaux mise à part que l'usage de hook_init est à remplacer par un hook spécialisé pour cet usage :

/**
 * implémentation du hook_custom_theme.
 */

function mon_module_custom_theme() {
  // Si l'URL est node/*/track
  if (drupal_match_path($_GET['q'], 'node/*/track') {
     // On bascule sur le thème défini dans admin/settings/admin
     return variable_get('admin_theme', 'garland');
  } elseif
  // Sinon, si le nom de domaine est m.XXXX (site mobile)
  if (preg_match('#^m(.*).(.*)$#i', $_SERVER['HTTP_HOST'])) {
     // On bascule sur le thême mobile
     return 'mon_theme_mobile';
  }
}
Implémentation de hook_custom_theme

Comme vous le voyez c'est encore plus simple grâce à hook_custom_theme qui remplace notre bricolage avec hook_init. Son fonctionnement est très simple, il suffit de faire nos tests et de renvoyer le nom du thème sélectionné.

Conclusion

Voilà donc, c'est à peu prés tout. Alors c'est vrai que les modules qui permettent de faire ce "travail" peuvent avoir leur utilité dans le cadre d'une utilisation "wordpressienne" de Drupal, mais pour un projet professionnel où il est rare de ne pas avoir au moins un module custom, cela fait l'économe d'un poignée de modules en échange d'un hook et d'une dizaine de lignes de code, plutôt rentable non ?

phabi1 (non vérifié), le ven, 30/03/2012 - 07:50

Bonjour,

J'ai une question à propos de mon site internet (drupal 7). Je voudrais créer une rubrique mariage dans mon site. J'ai créer un nouveau type de contenu "wedding_page" et des pages custom dont l'URL commencent par wedding. Ensuite, j'ai crée un module implémentant le hook_custom_theme. Ce hook vérifie si on est bien dans la rubrique mariage si il retourne le nom du thème correspondant sinon il renvoie rien. Le souci c'est que si je renvoie rien, il prend le dernier theme installé (comme défini dans l'API Drupal) et non le thème par défaut. Est ce que tu aurais une idée pour régler ce problème ?

Yoran, le ven, 30/03/2012 - 22:02

Bonsoir,

Une idée pour régler le problème serait de toujours renvoyer un nom de thème dans ton hook_custom_theme. Pas forcement très satisfaisant intellectuellement mais en tout cas efficace.

Sinon j'ai testé sur mon projet D7 en cours, et lorsque je ne renvoie rien dans le hook, j'ai bien le thème par défaut utilisé. Alors vérifications d'usage :
1/ drush variable-get theme_default te renvois t-il bien le nom du thème que tu as sélectionné comme étant le thème par défaut ?
2/ as-tu vidangé tes caches après cette implémentation de hook (drush cc all)
3/ as-tu le même comportement en anonyme et en authentifié ?

michel (non vérifié), le lun, 11/02/2013 - 18:06

Bonjour

je suis très intéressé par ce hook,
mais ce que j'ai pas encore compris, c'est dans quel fichier je doit l'écrire.... dans le template.php ?
merci pour votre réponse
cordialement

Michel

John (non vérifié), le lun, 18/03/2013 - 11:54

Non Michel, dans un module custom !

"En Drupal 6 ou 7, tout commence par la création dans votre projet d'un module custom que nous appellerons ici mon_module."

John (non vérifié), le lun, 18/03/2013 - 11:55

Non Michel, dans un module custom, comme c'est bien écrit :

"En Drupal 6 ou 7, tout commence par la création dans votre projet d'un module custom que nous appellerons ici mon_module."

John (non vérifié), le lun, 18/03/2013 - 11:55

Non Michel, dans un module custom, comme c'est bien écrit :

"En Drupal 6 ou 7, tout commence par la création dans votre projet d'un module custom que nous appellerons ici mon_module."

Publier un nouveau commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement.
  • Les adresses de pages web et de courriels sont transformées en liens automatiquement.
  • To highlight piece of code, just surround them with <code type="language"> Your code &tl;/code>>. Language can be java,c++,bash,etc... Everything Geshi support.
  • Les lignes et les paragraphes vont à la ligne automatiquement.

Plus d'informations sur les options de formatage

CAPTCHA
Cette question est là pour déterminer si vous êtes humain ou pas...