<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Artisan Numérique</title>
  <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1509"/>
  <link rel="self" type="application/atom+xml" href="http://artisan.karma-lab.net/node/1509/atom/feed"/>
  <id>http://artisan.karma-lab.net/node/1509/atom/feed</id>
  <updated>2008-10-08T15:50:42+02:00</updated>
  <entry>
    <title>Changer de thème Drupal en fonction du navigateur</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1509" />
    <id>http://artisan.karma-lab.net/node/1509</id>
    <published>2008-03-13T20:29:29+01:00</published>
    <updated>2008-10-08T15:50:42+02:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="Drupal" />
    <category term="drupalfr.org" />
    <category term="Planet Libre" />
    <category term="Dépassé" />
    <category term="Tutoriel" />
    <summary type="html"><![CDATA[<p>
   Rendre un thème compatible avec cette horreur d'IE6 a un coût certain et je n'avais pas, mais alors pas du tout envie de me lancer dans l'aventure pour le nouveau look d'artisan. La solution qui m'est paru plus saine, vu que ce brouteur est de toute façon en fin de vie (dieu merci), c'est d'utiliser spécifiquement pour lui, le vieux thème du site et ainsi laisser par défaut le nouveau pour ceux qui respectent un tant soit peu les standards. Et tout cela en restant dans un module, sans modifier le code de Drupal de préférence. 
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
   Rendre un thème compatible avec cette horreur d'IE6 a un coût certain et je n'avais pas, mais alors pas du tout envie de me lancer dans l'aventure pour le nouveau look d'artisan. La solution qui m'est paru plus saine, vu que ce brouteur est de toute façon en fin de vie (dieu merci), c'est d'utiliser spécifiquement pour lui, le vieux thème du site et ainsi laisser par défaut le nouveau pour ceux qui respectent un tant soit peu les standards. Et tout cela en restant dans un module, sans modifier le code de Drupal de préférence. 
</p>
<!--break-->

	<a name='chapter_1'></a>
  <h2>Stratégie de cache</h2>
	
<p>
  Comme vous devez le savoir, Drupal dispose de trois niveaux de cache allant de désactiver à agressif. Le cache des pages permet d'améliorer énormément les performances sur un site à fort trafic en court-circuitant de manière plus ou moins profonde tout traitement en PHP. Ce cache n'est utilisé que pour les connexions anonymes. 
</p>
<p>
  Le problème est que le cache étant par essence une version pré calculée d'une page, il va rentrer clairement en conflit avec notre module de changement de thème. Cependant, pour rester progressif, je vous propose d'abord une version qui implique de désactiver le cache. Nous verrons ensuite, dans un prochain article, comment modifier ce module pour qu'il puisse aussi fonctionner en mode "haute performance".  
</p>

	<a name='chapter_2'></a>
  <h2>Le module de base</h2>
	
<p>
   Pour construire notre module, nous allons comme d'habitude créer un dossier du genre <kbd>sites/all/modules/mes_modules/ie6_theme_hack</kbd> et y ajouter le fichier de description :

  <div class='code-block code-block-fragment'>
  <div class='container'>
  name &nbsp; &nbsp; &nbsp; &nbsp; = &quot;IE Theme Hack&quot;<br />
description &nbsp;= &quot;IE Theme Hack&quot;<br />
package &nbsp; &nbsp; &nbsp;= &quot;karma-lab&quot;<br />
version &nbsp; &nbsp; &nbsp;= &quot;5.x-1.0&quot;<br />
project &nbsp; &nbsp; &nbsp;= &quot;ie_theme_hack&quot;
  </div>
  <div class='caption'>ie_theme_hack.info</div>
  </div>
</p>
<p>
Ceci fait, créons un deuxième fichier, le module à proprement parler, avec pour l'instant juste ce qu'il faut pour l'activer :

  <div class='code-block code-block-fragment'>
  <div class='container'>
  &lt;?php<br />
<br />
function ie_theme_hack_help($section) {<br />
&nbsp; &nbsp; switch ($section) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; case 'admin/modules#description' :<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return t('IE Theme Hack');<br />
&nbsp; &nbsp; }<br />
}
  </div>
  <div class='caption'>ie_theme_hack.module</div>
  </div>
</p>
<p>
  Comme d'habitude, un petit tour dans <kbd>?q=/admin/build/modules</kbd>, on coche le nouveau module et on enregistre. 
</p>


	<a name='chapter_3'></a>
  <h2>Changement dynamique de thèmes</h2>
	
<p>
  Changer un thème sous Drupal est très simple. Le panneau de configuration <kbd>?q=/admin/build/themes</kbd> permet de sélectionner autant de thème "actifs" que l'on désire et en choisir un "par défaut". Il vous suffit donc de cocher votre thème "spécial IE6" pour le rendre disponible mais non actif par défaut. 
</p>
<p>
  Ensuite, le "truc" réside en une variable globale non documentée dans Drupal, <kbd>$custom_theme</kbd>. Lorsque elle est renseignée, son contenu vient écraser le non de thème par défaut. Une chose que nous pourrions faire dans le hool_<kbd>menu</kbd> de notre menu. Mais ce n'est pas "si" simple <img src="http://artisan.karma-lab.net/sites/all/modules/contrib/smileys/packs/crystal/wink2.gif" title="Wink" alt="Wink" class="smiley-content"/>
</p>
<p>
  En effet, la seule chose un peut délicate est que cette variable doit être renseignée très tôt dans le cycle de vie d'une page Drupal, bien avant que n'importe quel hook ne soit appelé sur notre module. 
</p>
<p>
  N'importe quel hook, sauf heureusement hook_<kbd>init</kbd> et hook_<kbd>exit</kbd>. Si un module possède ces deux fonctions, il sera considéré par Drupal comme prioritaire (aussi appelé module "bootstrap") et ces méthodes seront appelées avant même que le cache ne soit initialisé. Nous allons donc utiliser ces deux hooks dans notre nodule :

  <div class='code-block code-block-fragment'>
  <div class='container'>
  <a target="blank" href="http://www.php.net/function"><span class="kw2">function</span></a> ie_theme_hack_init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; <a target="blank" href="http://www.php.net/global"><span class="kw3">global</span></a> <span class="re0">$custom_theme</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$userAgent</span><span class="sy0">=</span> <span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st0">'HTTP_USER_AGENT'</span><span class="br0">&#93;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <a target="blank" href="http://www.php.net/if"><span class="kw1">if</span></a> <span class="br0">&#40;</span><span class="br0">&#40;</span><a target="blank" href="http://www.php.net/strpos"><span class="kw3">strpos</span></a><span class="br0">&#40;</span><span class="re0">$userAgent</span><span class="sy0">,</span> <span class="st0">'MSIE 6'</span><span class="br0">&#41;</span> <span class="sy0">!==</span> <a target="blank" href="http://www.php.net/false"><span class="kw2">false</span></a><span class="br0">&#41;</span> <span class="sy0">||</span> <span class="br0">&#40;</span><a target="blank" href="http://www.php.net/strpos"><span class="kw3">strpos</span></a><span class="br0">&#40;</span><span class="re0">$userAgent</span><span class="sy0">,</span> <span class="st0">'MSIE 5'</span><span class="br0">&#41;</span> <span class="sy0">!==</span> <a target="blank" href="http://www.php.net/false"><span class="kw2">false</span></a><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$custom_theme</span> <span class="sy0">=</span> <span class="st0">'theme_pour_ie6'</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
<br />
<a target="blank" href="http://www.php.net/function"><span class="kw2">function</span></a> ie_theme_hack_exit<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span><br />
<span class="br0">&#125;</span>
  </div>
  <div class='caption'>a la suite de ie6_theme_hack.module</div>
  </div>
</p>
<p>
  Comme vous le voyez, hook_<kbd>exit</kbd> n'est pas utilisé mais il doit être présent pour que le module soit déclaré comme prioritaire. Le corps du hook<kbd>_init</kbd> est lui assez simple. Une petite interrogation de la variable <kbd>$_SERVER['HTTP_USER_AGENT']</kbd> nous permet de déterminer s'il s'agit d'un IE5 ou IE6, et si c'est le cas, on positionne la variable <kbd>$custom_theme</kbd> avec le nom du thème alternatif, celui qui vous avez coché en plus du thème par défaut. 
</p>
<p>
  Il ne reste alors plus qu'à sauver. <b>Pour tester, prenez soin de déconnecter le cache dans la section performances de l'administration</b>. Ensuite, en fonction du navigateur soit c'est le thème par défaut qui sera utilisé, sinon c'est celui spécifique au navigateur cible.  
</p>

	<a name='chapter_4'></a>
  <h2>Conclusion</h2>
	
<p>
  Les deux hooks "init" et "exit" définissant un module "bootstrap" sont très précieux pour effectuer des opérations très bas niveau sans pour autant torpiller systématiquement le code de Drupal, en restant dans le cadre d'un module distribuable. Ceci dit, même si l'on cherche généralement à l'éviter, il n'est pas toujours possible d'éviter la modification du coeur de Drupal, c'est ce que nous allons voir au prochain épisode pour pouvoir réactiver le cache. 
</p>    ]]></content>
  </entry>
</feed>
