<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Drupal</title>
  <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/taxonomy/term/1130"/>
  <link rel="self" type="application/atom+xml" href="http://artisan.karma-lab.net/taxonomy/term/1130/atom/feed"/>
  <id>http://artisan.karma-lab.net/taxonomy/term/1130/atom/feed</id>
  <updated>2008-10-08T00:23:52+02:00</updated>
  <entry>
    <title>PHP, CSS et Drupal, comment retrouver son chemin ?</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1277" />
    <id>http://artisan.karma-lab.net/node/1277</id>
    <published>2008-11-14T10:19:52+01:00</published>
    <updated>2008-11-14T10:24:51+01:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="Drupal" />
    <category term="drupalfr.org" />
    <category term="OK" />
    <category term="Planet Libre" />
    <category term="Tutoriel" />
    <summary type="html"><![CDATA[<p>
  Un problème récurent en PHP est de trouver le bon chemin qui mène à la bonne ressource. Qui ne s'est jamais demandé comment inclure le fichier <kbd>toto.inc</kbd> qui se trouve pourtant si près et pourquoi une fois que ça marche, tout se casse la figure dés que l'on touche à Apache... Et avec Drupal, le casse-tête prend une dimension de plus avec les modules, les thèmes, les fichiers attachés, les fichiers temporaires, etc. L'objectif de ce tutorial vise donc simplement à éviter de paumer ses petits. 
</p>

    ]]></summary>
    <content type="html"><![CDATA[<p>
  Un problème récurent en PHP est de trouver le bon chemin qui mène à la bonne ressource. Qui ne s'est jamais demandé comment inclure le fichier <kbd>toto.inc</kbd> qui se trouve pourtant si près et pourquoi une fois que ça marche, tout se casse la figure dés que l'on touche à Apache... Et avec Drupal, le casse-tête prend une dimension de plus avec les modules, les thèmes, les fichiers attachés, les fichiers temporaires, etc. L'objectif de ce tutorial vise donc simplement à éviter de paumer ses petits. 
</p>

<!--break-->


	<a name='chapter_1'></a>
  <h2>Se repérer du côté serveur</h2>
	
<h3>Le dossier de travail d'un script PHP</h3>
<p>
  Le dossier de travail d'un script PHP est l'endroit où il se trouve, physiquement. Donc, <b>quelle que soit l'URL</b>, on exécute le script se trouvant en <kbd>/var/www/scritps/index.php</kbd>, et que l'on cherche à y ouvrir le fichier qui lui se trouve dans <kbd>/var/www/scritps/utilitaires/fichier.txt</kbd>, cela nous donne :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <a target="blank" href="http://www.php.net/fopen"><span class="kw3">fopen</span></a> <span class="br0">&#40;</span><span class="st0">&quot;utilitaires/fichier.txt&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="sy0">...</span>
  </div>
  <div class='caption'>/var/www/scritps/index.php</div>
  </div>
</p>

<p>
  Maintenant, si l'on effectue la même opération dans un script <kbd>scripts/utilitaires/utilitaire.inc</kbd> qui est inclus (directive <kbd>include</kbd> ou <kbd>require</kbd>) par <kbd>index.php</kbd>, le chemin sera... exactement le même. En effet, le dossier de travail de tous les fichiers inclus reste le même que celui du script principal. On peut s'en convaincre en utilisant la commande <kbd>getcwd()</kbd> qui retourne le dossier de travail :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <a target="blank" href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;Répertoire de travail : &quot;</span><span class="sy0">.</span><a target="blank" href="http://www.php.net/getcwd"><span class="kw3">getcwd</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<a target="blank" href="http://www.php.net/fopen"><span class="kw3">fopen</span></a> <span class="br0">&#40;</span><span class="st0">&quot;utilitaires/fichier.txt&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="sy0">...</span>
  </div>
  <div class='caption'>/var/www/utilitaires/utilitaire.inc</div>
  </div>  
</p>

<h3>Le dossier d'un fichier PHP</h3>
<p>
  La syntaxe précédente est tout sauf une bonne solution, surtout si l'on déplace ou renomme jour <kbd>utilitaires</kbd>.
  Il y a heureusement un moyen d'éviter ce problème en utilisant la macro PHP <kbd>__FILE__</kbd> qui renvoie<strong>le nom de fichier complet (dossiers compris) du script qui la contient</strong>. Utilisé conjointement avec la fonction <kbd>dirname</kbd>, cette macro permet donc d'ouvrir plus naturellement notre fichier, devenant ainsi indépendant du nom et de l'emplacement final du dossier <kbd>utilitaire</kbd>.
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <a target="blank" href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;Dossier de ce script : &quot;</span><span class="sy0">.</span><a target="blank" href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><a target="blank" href="http://www.php.net/__FILE__"><span class="kw2">__FILE__</span></a><span class="br0">&#41;</span><span class="sy0">;</span><br />
<a target="blank" href="http://www.php.net/fopen"><span class="kw3">fopen</span></a><span class="br0">&#40;</span><a target="blank" href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><a target="blank" href="http://www.php.net/__FILE__"><span class="kw2">__FILE__</span></a><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;/fichier.txt&quot;</span><span class="sy0">,</span> <span class="st0">&quot;r&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  </div>
  <div class='caption'>/var/www/utilitaires/utilitaire.inc</div>
  </div>
</p>
  
<h3>Les spécificités de l'inclusion (include et require)</h3>
<p>
  Même si tout ce qui s'applique à un script principal s'applique aussi fichiers inclus, ces derniers ont de petites spécificités amusantes qu'il est intéressant de noter. 
</p>
<p>
  Par défaut, l'inclusion se fait en cherchant dans la liste de chemins contenus dans la variable <kbd>include_path</kbd> présente dans le fichier <kbd>/etc/php.ini</kbd>. Cette liste fonctionne un peu comme la variable <kbd>PATH</kbd> du système d'exploitation, PHP cherche de manière séquentielle les fichiers demandés dans cette liste de dossiers en commençant par le premier. 
</p>
<p>
  Généralement cette liste contient d'abord le dossier de travail représenté par un <kbd>.</kbd>, puis, selon les installations, une série de chemins vers des librairies (<kbd>pear</kbD>, librairies standard, etc...</kbd>). 
</p>
<p>
  La présence du <kbd>.</kbd> en tête de liste implique un fonctionnement proche de ce que nous avons déjà vu plus haut avec <kbd>fopen</kbd>. Imaginons que le script <kbd>a.php</kbd> inclus <kbd>b.inc</kbd> qui inclus à son tour <kbd>c.inc</kbd>. Nous savons déjà que toute inclusion se trouvant dans <kbd>c.inc</kbd> sera recherchée dans les dossier de <kbd>a.php</kbd> et de <kbd>c.inc</kbd>. Mais, petite subtilité, il sera aussi cherché dans le dossier de <kbd>b.inc</kbd>.
<p>
  La commande include (ou require) se comporte donc comme si à chaque appel, elle ajoutait dans <kbd>include_path</kbd> le dossier du script inclus. Comportement aussi pratique que dangereux car on ne sait plus bien où l'on en est au bout d'un temps, ni qui a la priorité sur qui. Sachant donc cela, le mieux reste à mon sens de coller à la logique générale, en oubliant se comportement particulier. 
</p>
  
<a name="module"></a>
<h3>Le dossier d'un module Drupal</h3>  
<p>
   D'un point de vue général, le dossier de travail de drupal est celui où se trouve le fichier <kbd>index.php</kbd>. Ainsi tout ce qui a été dit plus haut fonctionne logiquement avec les scripts contenus dans Drupal, que ce soit pour le script principal, mais aussi pour les modules, thèmes et autre, qui ne sont que des <kbd>include</kbd> aux yeux de PHP.
<p>
  La différence est que pour un module, le dossier final ne peut être prévu à l'avance. Il peut tout aussi bien se trouver dans <kbd>drupal/modules</kbd> que par exemple dans <kbd>drupal/site/all/modules</kbd>. Il est donc impossible de se baser sur un chemin en dur pour accéder aux ressources (include, fichiers textes, etc...). Et c'est encore plus vrai lorsque l'on doit référencer des éléments se trouvant dans un autre module. 
</p>
<p>
  Pour ces raisons, il est préconisé d'utiliser plutôt la fonction Drupal prévue à cet effet, <kbd>drupal_get_path(...)</kbd> qui permet de localiser précisément n'importe quel module :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <span class="re0">$module_path</span><span class="sy0">=</span>drupal_get_path<span class="br0">&#40;</span><span class="st0">'module'</span><span class="sy0">,</span> <span class="st0">'mon_module'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<a target="blank" href="http://www.php.net/fopen"><span class="kw3">fopen</span></a><span class="br0">&#40;</span><span class="re0">$module_path</span><span class="sy0">.</span><span class="st0">&quot;/fichier.txt&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="sy0">...</span>
  </div>
  <div class='caption'>mon_module.module</div>
  </div>
</p>
<p>
  Il est donc souhaitable d'utiliser cette fonction pour inclure dans la page finale les scripts et autres feuilles de style :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <span class="co1">// Récupération du dossier du module</span><br />
<span class="re0">$module_path</span><span class="sy0">=</span>drupal_get_path<span class="br0">&#40;</span><span class="st0">'module'</span><span class="sy0">,</span> <span class="st0">'mon_module'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
<span class="co1">// Association d'un script contenu mon_module/scripts/script.js</span><br />
drupal_add_js<span class="br0">&#40;</span><span class="re0">$path</span> <span class="sy0">.</span> <span class="st0">'/scripts/script.js'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
<span class="co1">// Association d'une feuille de style contenu mon_module/styles/style.js</span><br />
drupal_add_css<span class="br0">&#40;</span><span class="re0">$path</span> <span class="sy0">.</span> <span class="st0">'/styles/style.js'</span><span class="br0">&#41;</span><span class="sy0">;</span>
  </div>
  <div class='caption'>mon_module.module</div>
  </div>
</p>
<p>
  A noter que cette fonction ne renvoie pas un chemin absolu (comme <kbd>_FILE</kbd>) mais un chemin relative à la racine de Drupal (le répertorie de travail d'index.php), sans <kbd>/</kbd> ni au début, ni à la fin. Mais nous allons voir plus loin comment retrouver le dossier d'installation de Drupal dans le cas où nous aurions besoin d'un chemin complet. 
</p>

<h3>Le dossier du thème courant</h3>
<p>
  Encore plus que celui du module, il est très utile de connaître le chemin vers le thème courant, utilisable par exemple dans les templates. Pour ce faire, nous avons deux options : 
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <span class="co1">// De manière générale, en utilisant la même méthode que pour le module mais en la</span><br />
<span class="co1">// paramétrant cette fois pour un thème</span><br />
<span class="re0">$theme_path</span><span class="sy0">=</span>drupal_get_path<span class="br0">&#40;</span><span class="st0">'theme'</span><span class="sy0">,</span> <span class="st0">'mon_theme'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
<span class="co1">// Plus portable, en récupérant le chemin du thème courant</span><br />
<span class="re0">$theme_path</span><span class="sy0">=</span>path_to_theme<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  </div>
  <div class='caption'>mon_template.inc.tpl</div>
  </div>
</p>
<p>
  A partir de là, comme pour le module, il est possible d'accéder à toutes les ressources du thème (images, styles, etc..) avec des chemins relatifs. 
</p>

<h3>Dossier des fichiers uploadés</h3>
<p>
  Pour accéder au dossier <kbd>files</kbd>, seul emplacement avec le dossier temporaire où il est possible de créer des dossiers et d'écrire des données, vous pouvez faire appel à la fonction <kbd>file_directory_path()</kbd> :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <span class="co1">// ouverture en écriture d'un fichiers dans le dossier &quot;files&quot;</span><br />
<a target="blank" href="http://www.php.net/fopen"><span class="kw3">fopen</span></a> <span class="br0">&#40;</span>file_directory_path<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;/donnes.txt&quot;</span><span class="sy0">,</span> <span class="st0">&quot;w&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="sy0">...</span>
  </div>
  <div class='caption'>mon_module.module</div>
  </div>
</p>
<div class='inline-box note'>
  Comme <kbd>path_to_theme()</kbd> renvoie un <b>chemin relatif</b> au dossier de base de Drupal, débarrassé du slash de début et de fin. 
</div>

<h3>Dossier des fichiers temporaires</h3>
<p>
  Pour accéder cette fois au dossier <kbd>temporaire</kbd>, vous pouvez faire appel à la fonction <kbd>file_directory_temp()</kbd> :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <span class="co1">// ouverture en écriture d'un fichiers dans le dossier temporaire. </span><br />
<a target="blank" href="http://www.php.net/fopen"><span class="kw3">fopen</span></a> <span class="br0">&#40;</span>file_directory_temp<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;/log.txt&quot;</span><span class="sy0">,</span> <span class="st0">&quot;w&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="sy0">...</span>
  </div>
  <div class='caption'>mon_module.module</div>
  </div>
</p>
<div class='inline-box note'>
  Contrairement aux fonctions précédentes, <kbd>file_directory_temp</kbd> revoie un <b>chemin absolu</b> sans slash final (ex. /tmp). 
</div>


	<a name='chapter_2'></a>
  <h2>Du côté client</h2>
	
<h3>La quête du chemin de base</h3>
<p>
  Les pages générées par Drupal, prises cette fois du côté client WEB (firefox), contiennent sans aucun doute des références à des images et autres feuilles de styles par le biais d'URL. Comme nous l'avons vu plus haut, une partie de ces ressources (feuilles de style, scriptes) sont prisent en charge directement par Drupal avec la fonction <kbd>drupal_add_css</kbd> par exemple. En revanche c'est plus compliqué lorsqu'il s'agit, par exemple, de faire référence à une image contenue dans un module. 
</p>
<p>
  En effet, et c'est aussi vrai en simple PHP, l'URL qui est utilisée par le navigateur pour atteindre le script <kbd>index.php</kbd> contient un chemin qui peut être sans rapport avec le chemin physique du script. Cette différence tenant à la manière dont a été configuré l'ami Apache.
</p>
<p>
  Par exemple, imaginons que noter site drupal est accessible par l'URL <kbd>http://mon_site/drupal</kbd> et que je veuille utiliser l'image <kbd>photo.png</kbd> contenue dans le dossier de <kbd>mon_module</kbd>, j'aurais tendance à écrire cela :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <span class="co1">// Récupération du dossier du module</span><br />
<span class="re0">$module_path</span><span class="sy0">=</span>drupal_get_path<span class="br0">&#40;</span><span class="st0">'module'</span><span class="sy0">,</span> <span class="st0">'mon_module'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
<span class="co1">// Référence à notre image</span><br />
<a target="blank" href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;&lt;img src='/$module_path/mon_image'/&gt;&quot;</span><span class="sy0">;</span>
  </div>
  <div class='caption'>mon_module.php</div>
  </div>
</p>
<p>
  Alors comme cela, ça a l'air de marcher, et ça va marcher dans un seul cas, si l'URL de base de drupal est "simplement" <kbd>http://mon_drupal/</kbd>. En revanche cela va planter si l'url ressemble à quelque chose comme <kbd>http://mon_site/drupal</kbd>. Dans ce cas, la ressource va être recherchée au mauvais endroit, ou pire, dans un endroit qui n'existe pas.
</p>
<p>
  La solution évidente semble être de passer en notation relative, en enlevant le premier slash. Et effectivement, cela va régler notre problème précédent mais il nous en reste un : les URL simplifiées. 
</p>
<p>
  En effet, si vous laissez Drupal configuré par défaut avec des URL du type <kbd>http://mon_site/drupal/?q=node/12</kbd> vous n'aurez pas de problème. En revanche si vous activez la simplification d'URL (clean URL), cela devient <kbd>http://mon_site/drupal/node/12</kbd>. Et là les ennuis recommencent car en notation relative, vous allez demander au navigateur d'aller chercher votre image en <kbd>/drupal/node/12</kbd> et non pas en <kbd>/drupal</kbd>.
</p>

<p>
  Pour accéder de manière universelle à une ressource d'un module, il faut donc commencer par récupérer le <kbd>/drupal/</kbd> quelque part. Et ce "quelque part" c'est le fichier <kbd>settings.php</kbd>, et plus précisément la variable globale <kbd>$base_url</kbd> qui contient l'URL de base de Drupal, soit dans notre exemple <kbd>http://mon_site/drupal</kbd> (sans <kbd>/</kbd> final). Le code de l'exemple précédent se corriger donc comme suit :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <span class="co1">// Récupération du dossier du module</span><br />
<span class="re0">$module_path</span><span class="sy0">=</span>drupal_get_path<span class="br0">&#40;</span><span class="st0">'module'</span><span class="sy0">,</span> <span class="st0">'mon_module'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
<span class="co1">// Déclaration de la variable globale $base_url</span><br />
<a target="blank" href="http://www.php.net/global"><span class="kw3">global</span></a> <span class="re0">$base_url</span><br />
<br />
<span class="co1">// ouverture en écriture d'un fichiers dans le dossier temporaire. </span><br />
<a target="blank" href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;&lt;img src='$base_url/$module_path/mon_image'/&gt;&quot;</span><span class="sy0">;</span>
  </div>
  <div class='caption'>mon_module.php</div>
  </div>
</p>
<p>
  Cette solution marche très bien mais souffre d'un dernier inconvénient, celui d'inscrire dans le code HTML généré une URL absolue. Ce n'est pas très gênant, sauf si l'on a 1000 images impliquant une augmentation inutile de la taille du fichier.
</p>
<p>
  Une bien meilleurs solution est donc d'utiliser cette fois la fonction <kbd>base_path()</kbd> qui ne renvoie que la partie correspondant au chemin de la variable $base_url (ex. <kbd>drupal</kbd> pour <kbd>http://mon_site/drupal</kbd>. Cela nous donne le code final :
  Ainsi nous pouvons réécrire notre exemple précédent :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <span class="co1">// Récupération du dossier du module</span><br />
<span class="re0">$module_path</span><span class="sy0">=</span>drupal_get_path<span class="br0">&#40;</span><span class="st0">'module'</span><span class="sy0">,</span> <span class="st0">'mon_module'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
<span class="co1">// ouverture en écriture d'un fichiers dans le dossier temporaire. </span><br />
<a target="blank" href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;&lt;img src='&quot;</span><span class="sy0">.</span>base_url<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;/$module_path/mon_image'/&gt;&quot;</span><span class="sy0">;</span>
  </div>
  <div class='caption'>mon_module.php</div>
  </div>
</p>
<p>
  Maintenant l'URL de notre image est relative et fonctionne dans tous les cas de figure. Bien évidement la même méthode peut être appliquée pour une ressource relative à un thème ou au dossier <kbD>files</kbd>. 
</p>


	<a name='chapter_3'></a>
  <h2>Les menus Drupal</h2>
	
<p>
  Contrairement à ce que l'on imagine spontanément, un menu Drupal est avant tout une URL qui référence un traitement effectué par un module. A ce titre, <kbd>/node/12</kbd> <i>est</i> un menu. Les menus "qui s'affichent sur le côté" ne sont du coup qu'un cas particulier d'un menu Drupal.
</p>
<p>
  Très souvent dans un module, du code est généré pour faire référence à un menu drupal. Par exemple imaginons que nous désirions générer une page contenant le lien vers le menu <kbd>node/12</kbd>. La mauvaise méthode consisterait à écrire quelque chose comme cela :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <a target="blank" href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;&lt;a href='/node/12'&gt;Affiche la page 12&lt;/a&gt;&quot;</span><span class="sy0">;</span>
  </div>
  <div class='caption'>mon_module.php</div>
  </div>
</p>
<p>
  Mauvaise pour les mêmes raisons que celles évoquées plus haut car si l'url contient un dossier en plus (http://mon_site/drupal), le menu devient alors <kbd>http://mon_site/node/12</kbd> et cela ne marchera plus. 
</p>
<p>
  Drupal connaît "à l'avance" tous les menus possible car chaque module qui en donne, a le devoir de les faire enregistrer pour qu'ils soient utilisables. Il existe du coup une méthode magique qui permet de transformer un menu (ex. <kbd>/node/12</kbd>) en son équivalent URL, il s'agit de la fonction <kbd>url()</kbd>. En l'utilisant, notre code se transforme ainsi :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <a target="blank" href="http://www.php.net/print"><span class="kw3">print</span></a> <span class="st0">&quot;&lt;a href='&quot;</span><span class="sy0">.</span>url<span class="br0">&#40;</span><span class="st0">&quot;node/12&quot;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;'&gt;Affiche la page 12&lt;/a&gt;&quot;</span><span class="sy0">;</span>
  </div>
  <div class='caption'>mon_module.php</div>
  </div>
</p>
<p>
  Cette méthode a plus d'un mérite. Tout d'abord elle va utiliser <kbd>base_url()</kbd> et gérer l'éventuelle absence de simplification d'url en mettant un <kbd>?q=</kbd> si besoin est. De plus, si vous avec activé le module d'alias (aka <kbd>path</kbd>), elle va traduire <kbd>node/12</kbd> en <kbd>une-belle-url</kbd>. Enfin elle renvoie une URL relative (donc plus courte) mais peut aussi créer une URL absolue en ajoutant des paramètres : <kbd>url("node/12", null, null, true)</kbd>. Pour plus d'informations sur cette fonction incontournable, allez faire un tour <a class='external' target='_blank' href='http://api.drupal.org/api/function/url/6' >ici</a>.
</p>
<p>
  Pour simplifier encore le travail, il existe une autre fonction qui fait appel à <kbd>url()</kbd> et qui permet de générer l'ensemble du lien. Avec son aide, notre code devient tout simplement :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <a target="blank" href="http://www.php.net/print"><span class="kw3">print</span></a> l<span class="br0">&#40;</span><span class="st0">&quot;Administration des modules&quot;</span><span class="sy0">,</span> <span class="st0">&quot;node/12&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  </div>
  
  </div>
</p>


	<a name='chapter_4'></a>
  <h2>Les feuilles de style</h2>
	
<p>
  Un autre moyen de référencer une ressource comme typiquement une image est de l'inclure dans une définition CSS. L'avantage de cette approche est que cette fois le chemin de la ressource n'est pas relatif à quoi que ce soit d'autre que la feuille de style elle-même. Ainsi si nous avons une feuille de style dans un dossier <kbd>XXX</kbd>, une image <kbd>background.png</kbd> dans le sous-dossier <kbd>XXX/images</kbd>, le référencement de cette image se fait tout simplement :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  body <span class="br0">&#123;</span><br />
&nbsp; <span class="kw1">background-image</span><span class="re2">:url</span><span class="br0">&#40;</span><span class="st0">&quot;images/background.png&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
  </div>
  <div class='caption'>ma_feuille.css</div>
  </div>
</p>


	<a name='chapter_5'></a>
  <h2>Conclusion</h2>
	
<p>
  Voilà, c'est la fin de cette session de repérage dans l'arborescence d'une application WEB. Si vous voulez avoir un résumé de toutes ces fonctions en un coup d'oeil, vous pouvez créer un module simple, un menu avec un callback sur la fonction suivante :
  
  <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> afficher_tous_les_chemins<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<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">$base_url</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">=</span><span class="st0">&quot;&lt;pre&gt;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;<span class="es0">\$</span>_SERVER[&quot;</span>PHP_SELF<span class="st0">&quot;] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: &quot;</span><span class="sy0">.</span><span class="re0">$_SERVER</span><span class="br0">&#91;</span><span class="st0">&quot;PHP_SELF&quot;</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;getcwd() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: &quot;</span><span class="sy0">.</span><a target="blank" href="http://www.php.net/getcwd"><span class="kw3">getcwd</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;<span class="es0">\$</span>base_url &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : &quot;</span><span class="sy0">.</span><span class="re0">$base_url</span><span class="sy0">.</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;dirname(__FILE__) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : &quot;</span><span class="sy0">.</span><a target="blank" href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><a target="blank" href="http://www.php.net/__FILE__"><span class="kw2">__FILE__</span></a><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;drupal_get_path('module','mon_module') &nbsp;: &quot;</span><span class="sy0">.</span>drupal_get_path<span class="br0">&#40;</span><span class="st0">'module'</span><span class="sy0">,</span> <span class="st0">'hermes_wiki'</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;path_to_theme() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : &quot;</span><span class="sy0">.</span>path_to_theme<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;path_to_engine() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: &quot;</span><span class="sy0">.</span>path_to_engine<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;file_directory_path() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : &quot;</span><span class="sy0">.</span>file_directory_path<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;<span class="es0">\$</span>base_url &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: &quot;</span><span class="sy0">.</span><span class="re0">$base_url</span><span class="sy0">.</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;base_path() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: &quot;</span><span class="sy0">.</span>base_path<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$output</span><span class="sy0">.=</span><span class="st0">&quot;&lt;/pre&gt;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <a target="blank" href="http://www.php.net/return"><span class="kw1">return</span></a> <span class="re0">$output</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
  </div>
  <div class='caption'>mon_module.module</div>
  </div>
</p>
    ]]></content>
  </entry>
  <entry>
    <title>Drupal 6.6 et 5.11, correctifs sécurité</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1684" />
    <id>http://artisan.karma-lab.net/node/1684</id>
    <published>2008-10-24T22:51:12+02:00</published>
    <updated>2008-10-24T22:51:12+02:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="Drupal" />
    <category term="drupalfr.org" />
    <category term="OK" />
    <category term="Planet Libre" />
    <category term="Article" />
    <summary type="html"><![CDATA[<p>Les pétouilles du jour sont arrivées sur drupal 5.x et 6.x. Donc on passe à Drupal 6.6 et Drupal 5.12.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Les pétouilles du jour sont arrivées sur drupal 5.x et 6.x. Donc on passe à Drupal 6.6 et Drupal 5.12.</p>
<p>  Pour les détails, c'est ici que cela se passe. A priori rien de bien extraordinaire même si 27 fichiers patchés pour deux anomalies, ça parait un peu gros <img src="http://artisan.karma-lab.net/sites/all/modules/contrib/smileys/packs/crystal/wink2.gif" title="Wink" alt="Wink" class="smiley-content"/></p>
    ]]></content>
  </entry>
  <entry>
    <title>Drupal 6.5, Mise à jour de sécurité</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1675" />
    <id>http://artisan.karma-lab.net/node/1675</id>
    <published>2008-10-09T00:09:20+02:00</published>
    <updated>2008-10-09T17:39:25+02:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="Drupal" />
    <category term="drupalfr.org" />
    <category term="OK" />
    <category term="Planet Libre" />
    <category term="Article" />
    <summary type="html"><![CDATA[<p>
  Quelques pétouilles ont été découvertes sur drupal 5.x et 6.x. C'est donc patch timine...
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
  Quelques pétouilles ont été découvertes sur drupal 5.x et 6.x. C'est donc patch timine...
</p>
<!--break-->
<p>
  Pour les détails, c'est <a class='external' target='_blank' href='http://drupal.org/node/318706' >ici que cela se passe</a>. Et pour la mise à jour sans tout casser il y a ce <a class='external' target='_blank' href='/node/1240' >tutoriel</a> et bien évidement <a class='external' target='_blank' href='http://ftp.drupal.org/files/projects/drupal-6.5.tar.gz' >Drupal 6.5</a> ou <a class='external' target='_blank' href='http://ftp.drupal.org/files/projects/drupal-5.11.tar.gz' >Drupal 5.11</a>.
</p>
<p>
  Ah oui, et pour ceux qui veulent gagner du temps, voici le <a class='external' target='_blank' href='/files/artisan/1675/diff-6.4-6.5.patch_.bz2' >patch de la 6.4 à la 6.5</a>. Ca a du me prendre 10 minutes avec ça de mettre à jour, alors pas de quoi s'en priver... En espérant qu'il n'y ait pas trop de regressions <img src="http://artisan.karma-lab.net/sites/all/modules/contrib/smileys/packs/crystal/wink2.gif" title="Wink" alt="Wink" class="smiley-content"/>
</p>    ]]></content>
  </entry>
  <entry>
    <title>Créer un module Drupal, les blocks</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1535" />
    <id>http://artisan.karma-lab.net/node/1535</id>
    <published>2008-10-08T15:02:03+02:00</published>
    <updated>2008-11-18T12:32:06+01:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="Drupal" />
    <category term="drupalfr.org" />
    <category term="OK" />
    <category term="Planet Libre" />
    <category term="Tutoriel" />
    <summary type="html"><![CDATA[<p> 
  Une des grandes forces de Drupal réside en son architecture à base de modules. Que ce soit pour la gestion des blogs ou celle d’un forum, chaque fonction fondamentale est en réalité un simple module interagissant avec le cœur de Drupal. Et si les modules fournis en standard ne suffisent pas, des centaines d’autres <a class='external' target='_blank' href='http://drupal.org/project/Modules' >sont disponibles</a> couvrant à peu prés tous les usages. 
</p> 
<p> 
  Mais malgré cette richesse, il arrive parfois que l’on ne trouve pas LE module « qui va bien ». Alors pourquoi ne pas le fabriquer soi-même et ainsi découvrir à quel point Drupal s'adapte facilement à des besoins spécifiques. 
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p> 
  Une des grandes forces de Drupal réside en son architecture à base de modules. Que ce soit pour la gestion des blogs ou celle d’un forum, chaque fonction fondamentale est en réalité un simple module interagissant avec le cœur de Drupal. Et si les modules fournis en standard ne suffisent pas, des centaines d’autres <a class='external' target='_blank' href='http://drupal.org/project/Modules' >sont disponibles</a> couvrant à peu prés tous les usages. 
</p> 
<p> 
  Mais malgré cette richesse, il arrive parfois que l’on ne trouve pas LE module « qui va bien ». Alors pourquoi ne pas le fabriquer soi-même et ainsi découvrir à quel point Drupal s'adapte facilement à des besoins spécifiques. 
</p>
<!--break-->
<div class='inline-box note'>
  Ce tutoriel est la seconde version d'une précédente mouture que j'ai cherché à intégrer comme première étape de la série <a class='external' target='_blank' href='/taxonomy/term/1084%252C1130' >Créer un module Drupal</a>. Comme toujours, l'ensemble des sources de ce tutoriel est disponible <a class='external' target='_blank' href='/node/1674' >ici</a> avec en plus les archives pour éviter d'avoir à utiliser subversion.
</div> 

	<a name='chapter_6'></a>
  <h2>Pré-requis</h2>
	 
<p> 
  Les seuls pré-requis pour développer un module sont une bonne connaissance des concepts clés de Drupal (blocks, node, type de contenu, taxinomie, etc.), une relative maîtrise de PHP. 
</p>
<p>
  Armé de tout cela, nous allons commencer en douceur avec la création d'un module dont le seul but est de nous fournir un bloc avec du texte dedans, rien de plus. Ce module 'Liste des courses', sera ensuite étendu pour en faire un module complet de gestion de vos achats quotidien. Tant qu'à prendre un exemple, autant qu'il serve à quelque chose (quoi ? vous n'avez pas tous un intranet domestique sous Drupal ??? <img src="http://artisan.karma-lab.net/sites/all/modules/contrib/smileys/packs/crystal/wink2.gif" title="Wink" alt="Wink" class="smiley-content"/>). Et tout cela pour Drupal 6.x. 
</p>


	<a name='chapter_7'></a>
  <h2>Des modules et des hooks</h2>
	 
<p> 
  Avant de poursuivre, il est important de comprendre ce qu'est réellement un module. Un module Drupal est un bout de code PHP que l'on peut activer ou désactiver, et qui implémente des "hooks".  
</p> 
<p> 
  Un hook (en français, "Crochet") est un prototype de fonction dédié à une tâche spécifique, comme par obtenir la liste des blocs disponibles et le contenu de chacun d'entre eux. 
</p>
<p>
 	Chaque module peut ainsi implémenter ce hook sous la forme d'une fonction ayant des paramètres calqués sur ceux du prototype. Dans le cas  d'un bloc, le prototype se nomme <kbd><a class='external' target='_blank' href='http://api.drupal.org/api/function/hook_block/6' >hook_view</a></kdb>: 

  <div class='code-block code-block-fragment'>
  <div class='container'>
  hook_block<span class="br0">&#40;</span><span class="re0">$op</span> <span class="sy0">=</span> <span class="st0">'list'</span><span class="sy0">,</span> <span class="re0">$delta</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="re0">$edit</span> <span class="sy0">=</span> <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
  </div>
  <div class='caption'>prototype du hook &#039;hook_view&#039;</div>
  </div> 
</p> 
<p> 
   Ainsi un module désirant implémenter ce hook, devra comporter le code suivant : 
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  &nbsp; &nbsp;<a target="blank" href="http://www.php.net/function"><span class="kw2">function</span></a> hook_block<span class="br0">&#40;</span><span class="re0">$op</span> <span class="sy0">=</span> <span class="st0">'list'</span><span class="sy0">,</span> <span class="re0">$delta</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="re0">$edit</span> <span class="sy0">=</span> <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <br />
<span class="co1">// Traitement à effectuer sur le module </span><br />
&nbsp; &nbsp;<span class="br0">&#125;</span>
  </div>
  <div class='caption'>implémentation de &#039;hook_view&#039; dans le module &#039;monModule&#039;</div>
  </div> 
</p> 
<p> 
   Lorsque Drupal aura besoin d'obtenir la liste des blocs, il cherchera dans la liste de toutes les fonctions PHP disponibles, c'est-à-dire les fonctions contenues dans tous les modules activés, celles dont le nom commence par le nom d'un module et se termine par <kbd>_block</kbd>, le nom du hook. 
</p> 
<p> 
   La manière dont Drupal utilise un hook est assez simple. Pour rester sur notre exemple, lorsqu'il a besoin d'obtenir la liste des blocs, il va appeler tout les fonctions <kbd>_block</kbd> qu'il trouve, les unes après les autres, en leur passant en premier paramètre la chaîne <kbd>list</kbd>. Et réponse, chacune va donner un tableau contenant les noms et descriptions des blocs qu'elles prennent en charge. 
</p>
<p>
  Ensuite lorsque Drupal va devoir afficher un bloc en particulier, il effectue la même opération mais cette fois en passant en paramètre <kbd>view</kbd> suivi du nom du bloc. 
</p> 
<p> 
   Maintenant au delà du mode d'exécution des hooks de même type, chacun est spécifique tant par les paramètres qu'il reçoit que par les valeurs que Drupal s'attend à recevoir.  Vous pouvez obtenir leur description dans la <a class='external' target='_blank' href='http://api.drupal.org/api/function/hook_view/5' >documentation de l'API Drupal</a>. 
</p> 


	<a name='chapter_8'></a>
  <h2>Structure d'un module</h2>
	 
<p> 
Un module est donc un fournisseur d'implémentation de hooks. En conséquence, la majeure partie de son code va s'insérer dans les traitements de Drupal et étendre son comportement. Maintenant de manière plus prosaïque, un module est simplement un dossier qui contient au minimum deux fichiers. 
</p> 
<p> 
Ce dossier doit porter le nom du module et doit être placé dans l'arborescence de Drupal, à un endroit qui soit approprié pour que ce dernier puisse le voir. Techniquement il est possible de les mettre dans <kbd>modules/</kbd> mais vous seriez vite embêtés lors d'un changement de version. Il est donc préconisé de mettre cela dans un dossier <kbd>sites/all/modules/mes_modules</kbd> que vous créerez si nécessaire. Ainsi lorsque vous changez de version, il suffit de déplacer le dossier <kbd>sites</kbD> à sa place dans la nouvelle arborescence. 
</p> 
<p> 
	Dans ce dossier <kbd>mes_modules</kbd>, vous allez donc créer le sous-dossier du module lui-même, dans notre cas <kbd>courses</kbd>. A l'intérieur de celui-ci, vous devez avoir au minimum deux fichiers, portant le même nom de base que le dossier parent : <kbd>courses.info</kbd> et <kbd>courses.module</kbd>. Ce qui nous donne l'arborescence suivante : 

  <div class='code-block code-block-fragment'>
  <div class='container'>
  &nbsp; modules <br />
&nbsp; ... etc ... <br />
&nbsp; site <br />
&nbsp; &nbsp; all <br />
&nbsp; &nbsp; &nbsp; modules <br />
&nbsp; &nbsp; &nbsp; &nbsp; contributions <br />
&nbsp; &nbsp; &nbsp; &nbsp; ...etc... <br />
&nbsp; &nbsp; &nbsp; &nbsp; mes_modules <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;courses<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; courses.info <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; courses.module <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...etc... <br />
&nbsp; &nbsp; &nbsp; themes <br />
&nbsp; &nbsp; ...etc...
  </div>
  
  </div> 
</p> 


	<a name='chapter_9'></a>
  <h2>Fichier .info</h2>
	
<p> 
  Le fichier <kbd>statistiques.info</kbd> est un simple fichier texte contenant des informations sur le module comme son nom, sa description, la version de Drupal avec lequel il est compatible, etc. Ce qui nous donne pour notre exemple, le contenu suivant : 

  <div class='code-block code-block-fragment'>
  <div class='container'>
  name = &quot;Liste des courses&quot;<br />
description = &quot;Gestion de la liste des courses&quot;<br />
package = &quot;karma-lab - exemples&quot;<br />
project = &quot;courses&quot;<br />
version = &quot;6.x-1.0&quot;<br />
core = 6.x
  </div>
  <div class='caption'>courses/courses.info</div>
  </div> 
</p> 
<p>
<kbd>package</kbd> indique dans quelle catégorie le module doit être affiché. <kbd>name</kbd>, <kbd>description</kbd> sont des informations textuelles qui seront affiché dans le panneau d'administration des modules. <kbd>name</kbd> reprend le nom du module (qui est aussi le nom du dossier). <kbd>version</kbd> indique quant à lui la version du module. C'est d'ailleurs plus une norme qu'autre chose qui se lit "Module version 0.1 pour Drupal 6.x". Enfin <kbd>core</kbd> prévient Drupal que le module est seulement compatible avec sa version <kbd>6.x</kbd>. Tout autre version de Drupal empêchera le module de s'activer. 
</p>
<p>
Si nous avions eu besoin de définir une dépendance avec un autre module, nous aurions ajouté une clause de la forme <kbd>dependencies[] = autre_module</kbd>. Enfin, si vous désirez ajouter des commentaires, il suffit d'utiliser le symbole <kbd>;</kbd> suivi du texte du commentaire.  
</p>


	<a name='chapter_10'></a>
  <h2>Fichier .module</h2>
	
<p> 
  Le second fichier est le code PHP du module. C'est lui qui va héberger les hooks que nous souhaitons implémenter. Pour l'instant, nous allons faire simple et n'en mettre aucun. Notre fichier va donc contenir une simple balise de démarrage de code PHP : 

  <div class='code-block code-block-fragment'>
  <div class='container'>
  <a target="blank" href="http://www.php.net/?php"><span class="kw2">&lt;?php</span></a>
  </div>
  <div class='caption'>courses/courses.module</div>
  </div> 
</p> 
<p> 
  <image file="step1.png" width="600px"/><br style='clear:left'/>
  
  Voilà, nous avons maintenant un module aussi simple qu'inutile, que Drupal est cependant capable de voir et d'activer. Pour s'en convaincre, il suffit d'aller faire un tour en <kbd>http://mon_site_drupal/?q=/admin/build/modules</kbd> pour le voir apparaître dans la liste. Vous constatez que les informations affichées sont les champs <kbd>name</kbd> et <kbd> description</kbd> de notre fichier <kbd>courses.info</kbd>. 
</p> 
<p> 
  A ce stade nous pourrions donc activer notre module, mais ne le faites pas tout de suite, nous avons encore quelque chose à rajouter. </p> 


	<a name='chapter_11'></a>
  <h2>Implémentation de hook_block</h2>
	
<p> 
	Il est maintenant temps d'implémenter notre premier hook. Comme nous l'avons vu plus haut, celui qui est responsable de la génération de bloc est <kbd>hook_block</kbd>. Il nous faut donc ajouter son implémentation à la suite, dans notre fichier <kbd>statistiques.modules</kbd>:

  <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> courses_block<span class="br0">&#40;</span><span class="re0">$op</span> <span class="sy0">=</span> <span class="st0">'list'</span><span class="sy0">,</span> <span class="re0">$delta</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="re0">$edit</span> <span class="sy0">=</span> <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; <span class="re0">$blocks</span><span class="sy0">=</span><a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="co1">// Enumeration des blocs disponibles</span><br />
&nbsp; <a target="blank" href="http://www.php.net/if"><span class="kw1">if</span></a> <span class="br0">&#40;</span><span class="re0">$op</span> <span class="sy0">==</span> <span class="st0">'list'</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="re0">$blocks</span><span class="br0">&#91;</span><span class="st0">'courses'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; <span class="st0">'info'</span> <span class="sy0">=&gt;</span> t<span class="br0">&#40;</span><span class="st0">'Les courses en attente'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <a target="blank" href="http://www.php.net/return"><span class="kw1">return</span></a> <span class="re0">$blocks</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; <span class="co1">// Génération du formulaire de configuration </span><br />
&nbsp; <a target="blank" href="http://www.php.net/else"><span class="kw1">else</span></a> <a target="blank" href="http://www.php.net/if"><span class="kw1">if</span></a> <span class="br0">&#40;</span><span class="re0">$op</span> <span class="sy0">==</span> <span class="st0">'configure'</span> <span class="sy0">&amp;&amp;</span> <span class="re0">$delta</span> <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="re0">$form</span><span class="br0">&#91;</span><span class="st0">'courses_nombre_item_max'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; <span class="st0">'#type'</span> <span class="sy0">=&gt;</span> <span class="st0">'textfield'</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; <span class="st0">'#title'</span> <span class="sy0">=&gt;</span> t<span class="br0">&#40;</span><span class="st0">&quot;Combien d'item affiché au maximum ?&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; <span class="st0">'#default_value'</span> <span class="sy0">=&gt;</span> courses_nombre_item_max<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; <span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <a target="blank" href="http://www.php.net/return"><span class="kw1">return</span></a> <span class="re0">$form</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; <span class="co1">// Sauvegarde du formulaire de configuration</span><br />
&nbsp; <a target="blank" href="http://www.php.net/else"><span class="kw1">else</span></a> <a target="blank" href="http://www.php.net/if"><span class="kw1">if</span></a> <span class="br0">&#40;</span><span class="re0">$op</span> <span class="sy0">==</span> <span class="st0">'save'</span> <span class="sy0">&amp;&amp;</span> <span class="re0">$delta</span> <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; variable_set<span class="br0">&#40;</span><span class="st0">'courses_nombre_item_max'</span><span class="sy0">,</span> <span class="re0">$edit</span><span class="br0">&#91;</span><span class="st0">'courses_nombre_item_max'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; <span class="co1">// Génération du contenu à afficher pour le block</span><br />
&nbsp; <a target="blank" href="http://www.php.net/else"><span class="kw1">else</span></a> <a target="blank" href="http://www.php.net/if"><span class="kw1">if</span></a> <span class="br0">&#40;</span><span class="re0">$op</span> <span class="sy0">==</span> <span class="st0">'view'</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <a target="blank" href="http://www.php.net/switch"><span class="kw1">switch</span></a><span class="br0">&#40;</span><span class="re0">$delta</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <a target="blank" href="http://www.php.net/case"><span class="kw1">case</span></a> <span class="st0">'courses'</span><span class="sy0">:</span> <span class="co1">// Il s'agit bien de notre bloc</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$block</span> <span class="sy0">=</span> <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">'subject'</span> <span class="sy0">=&gt;</span> t<span class="br0">&#40;</span><span class="st0">'Liste des courses'</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">'content'</span> <span class="sy0">=&gt;</span> <span class="st0">'Un bloc vide'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a target="blank" href="http://www.php.net/break"><span class="kw1">break</span></a><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <a target="blank" href="http://www.php.net/return"><span class="kw1">return</span></a> <span class="re0">$block</span><span class="sy0">;</span><br />
&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> courses_nombre_item_max<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; <a target="blank" href="http://www.php.net/return"><span class="kw1">return</span></a> variable_get<span class="br0">&#40;</span><span class="st0">'courses_nombre_item_max'</span><span class="sy0">,</span><span class="nu0">5</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
  </div>
  <div class='caption'>à ajouter à courses.module</div>
  </div>
</p>
<p>
   Le paramètre important de ce hook est <kbd>$op</kbd>. Lorsque Drupal a besoin de la liste des blocs disponible, il appelle cette fonction avec <kbd>$op=='list'</kbd>. Drupal s'attend alors à ce que la fonction renvoie un tableau associant un id (ici <kbd>courses</kbd>) à une définition de bloc.  Cette définition est elle aussi un tableau associant une propriété du bloc à sa valeur. Cette organisation des données est un grand classique dans Drupal. 
</p>
<p>
   Ici nous renvoyons à Drupal un seul bloc ayant pour description (propriété <kbd>info</kbd>) <kbd>affichage des statistiques</kbd>. Notez l'utilisation de la fonction <kbd>t(...)</kbd> qui permet de prévoir une prise en charge ultérieure de la traduction du module. Pensez à utiliser systématiquement cette fonction pour tous les textes. 
</p>
<p>
   Vous pouvez dés maintenant voir le hook en action en allant sur l'URL <kbd>http://mon_site_drupal?q=admin/build/block</kbd>. Vous devriez alors le voir apparaître dans la liste des blocs désactivés. 
   <image file="step2.png" width="600px"/><br style='clear:left'>
</p>
<p>
  Sélectionnez maintenant dans la liste une position pour votre bloc et sauvegardez l'ensemble. Il devrait apparaître à l'endroit désiré. 
</p>


	<a name='chapter_12'></a>
  <h2>Paramétrage du bloc</h2>
	
<p>
   Passons maintenant à la possibilité d'ajoute un formulaire de paramétrage pour notre bloc. Cela se passe toujours dans <kbd>hook_bloc</kbd> mais nous nous adressons cette fois aux opérations <kbd>$op==configure</kbd> et <kbd>$op==save</kbd>. La première fabrique un mini formulaire Drupal. La seconde sauvegarde le résultat du formulaire modifié par l'utilisateur. 
</p>
<p>
Le formulaire est construit dans la variable <kbd>$form</kbd> dont la structure de stockage est la même que pour <kbd>$blocks</kbd>. C'est à dire un double tableau associatif, contenant la liste par id des champs. Puis par champ, la liste des propriétés et leurs valeurs. 
</p>
<p>
  La propriété <kbd>#type</kbd> détermine le type du champ (zone de texte,liste déroulante, etc). Ici nous choisissions un champ texte (<kbd>textfield</kbd>). La liste de complète des types et de leurs propriétés associées est disponible dans la <a class='external' target='_blank' href='http://api.drupal.org/api/file/developer/topics/forms_api_reference.html/6' >documentation de Drupal</a>. 
</p> 
<p> 
   Mais la propriété vraiment intéressante est <kbd>#default_value</kbd>. Elle définit la valeur que dois prendre le champ au moment de l'affichage du formulaire. Cette valeur est extraite des propriétés générales de Drupal par la fonction  <kbd>variable_get(...)</kbd>, par l'intermédiaire de la fonction <kbd>courses_nombre_item_max()</kbd>. En effet, Drupal met à disposition des modules un système de variables persistantes très simple à mettre en oeuvre. Passer par une fonction intermédiaire nous permet seulement de définir la valeur par défaut ((ici 5) de cette variable à un seul endroit et d'utiliser cette fonction partout où nous auront besoin de ce paramétrage. 
</p>
<p>
  La dernière propriété <kbd>#title</kbd> définit le titre du champ. Là aussi nous utilisons la fonction <kbd>t(...)</kbd> en prévision d'éventuelles traductions à venir.
</p>
<p>
   Notre micro formulaire est maintenant  prêt à être utilisé par Drupal. Vous pouvez le tester en retournant dans l'administration des blocs, en allant à la ligne que vous avez activée plus haut et en cliquant sur le lien <kbd>configurer</kbd>. 
  <image file="step3.png" width="600px"/><br style='clear:left'/>
</p>
<p>
   Lorsque vous aurez paramétré votre bloc, le fait de clicker sur le bouton <kbd>Enregistrer le bloc</kbd> provoquer un nouvel appel de notre hook, mais cette fois avec le paramètre <kbd>save</kbd> renvoyant les résultats du formulaire définit à l'étape précédente. Ces résultats sont contenus dans le tableau associatif <kbd>$edit</kbd> et notre seule tâche est d'utiliser la fonction Drupal permettant de stocker une variable persistante,  <kbd>variable_set(...);</kbd>, en lui passant la valeur du champ <kbd>courses_nombre_item_max</kbd>. 
</p>

<p>
   La dernière étape est la génération du code HTML du bloc. C'est le rôle de l'opération <kbd>$op==view</kbd> qui utilise le paramètre du hook <kbd>$delta</kbd>. 
</p>
<p>
  <kbd>hook_block</kbd> permettant de créer autant de blocs que désiré,  <kbd>$delta</kbd> contient l'ID du bloc à créer. Ici nous n'en avons qu'un mais autant prévoir l'avenir et effectuer tout de même le test. Ensuite, nous définissons une fois de plus un tableau associatif contenant deux propriétés, le titre du node (<kbd>subject</kbd>) et le contenu HTML du node (<kbd>content</kbd>). 
</p>
<p>
<image file="step4.png" width="200px"/>
  Il est maintenant temps d'afficher notre bloc en sélectionnant une position dans la page d'administration. Une fois ce paramétrage sauvegardé (bouton <kbd>enregistrer les blocs</kbd>, le nouveau bloc devrait apparaître là où vous l'avez décidé. 
</p>

	<a name='chapter_13'></a>
  <h2>Contenu du bloc</h2>
	
<p>
Maintenant que notre bloc est prêt, passons à l'affichage de son contenu. Pour cela nous allons remplacer la ligne <kbd>content' => 'Un bloc vide');</kbd> par <kbd>'content' => statistiques_contenu());</kbd> et ajouter la fonction de rendu HTML de notre bloc. Bien évidemment, vu que nous n'avons pour l'instant pas de base de données contenant la liste réelle de nos courses, nous allons mettre dans ce bloc des items poétiques :

  <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> courses_contenu<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; <span class="re0">$result</span><span class="sy0">=</span><span class="st0">&quot;&lt;ul class='menu'&gt;&quot;</span><span class="sy0">;</span><br />
&nbsp; <span class="re0">$liste</span><span class="sy0">=</span><a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">1</span><span class="sy0">,</span><span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;triperie&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">2</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;pierre&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">3</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;fleurs&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;oiseau&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">22</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;fossoyeurs&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;amour&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;raton laveur&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;madame untel&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;citron&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;pain&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;grand rayon de soleil&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">2</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;lame de fond&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;pantalon&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span><br />
&nbsp; <a target="blank" href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="st0">'quantite'</span><span class="sy0">=&gt;</span><span class="nu0">3</span><span class="sy0">,</span> <span class="st0">'description'</span><span class="sy0">=&gt;</span><span class="st0">&quot;porte (avec son paillasson)&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="re0">$nombre</span><span class="sy0">=</span><span class="nu0">1</span><span class="sy0">;</span><br />
&nbsp; <span class="re0">$max</span><span class="sy0">=</span>courses_nombre_item_max<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <a target="blank" href="http://www.php.net/foreach"><span class="kw1">foreach</span></a> <span class="br0">&#40;</span><span class="re0">$liste</span> <a target="blank" href="http://www.php.net/as"><span class="kw1">as</span></a> <span class="re0">$item</span><span class="br0">&#41;</span> <span class="br0">&#123;</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="re0">$nombre</span> <span class="sy0">&gt;</span> <span class="re0">$max</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <a target="blank" href="http://www.php.net/break"><span class="kw1">break</span></a><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="re0">$result</span><span class="sy0">.=</span><span class="st0">&quot;&lt;li class='leaf'&gt;&quot;</span><span class="sy0">.</span>t<span class="br0">&#40;</span><span class="re0">$item</span><span class="br0">&#91;</span><span class="st0">'description'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st0">' ('</span><span class="sy0">.</span><span class="re0">$item</span><span class="br0">&#91;</span><span class="st0">'quantite'</span><span class="br0">&#93;</span><span class="sy0">.</span><span class="st0">&quot;)&lt;/li&gt;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="re0">$nombre</span><span class="sy0">++;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
&nbsp; <span class="re0">$result</span><span class="sy0">.=</span><span class="st0">&quot;&lt;/ul&gt;&quot;</span><span class="sy0">;</span><br />
&nbsp; <a target="blank" href="http://www.php.net/return"><span class="kw1">return</span></a> <span class="re0">$result</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
  </div>
  <div class='caption'>à ajouter à courses.module</div>
  </div>
</p>
<p>
<image file="step5.png" width="200px"/>
  Voilà, rien de sorcier dans cette fonction, juste la création de code HTML que l'on renvoie à <kbd>hook_block</kbd>. Il ne reste maintenant plus qu'à apprécier le résultat. 
</p>


	<a name='chapter_14'></a>
  <h2>Conclusion</h2>
	 
<p> 
    Voilà, nous avons terminé notre premier module totalement fonctionnel en espérant que vous avoir montré à quel point, une fois quelques notions de base assimilées Drupal est facile à adapter à des besoins même très particuliers. 
</p>
    ]]></content>
  </entry>
  <entry>
    <title>Module &#039;Liste de courses&#039; pour Drupal version 6.x-1.0</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1674" />
    <id>http://artisan.karma-lab.net/node/1674</id>
    <published>2008-10-08T13:40:24+02:00</published>
    <updated>2008-10-08T14:24:56+02:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="Drupal" />
    <category term="Aucun" />
    <category term="OK" />
    <summary type="html"><![CDATA[<p>
  Version de la liste des courses correspondant au tutoriel <a class='external' target='_blank' href='/node/1535' >sur les blocks</a>
</p>    ]]></summary>
    <content type="html"><![CDATA[<p>
  Version de la liste des courses correspondant au tutoriel <a class='external' target='_blank' href='/node/1535' >sur les blocks</a>
</p>    ]]></content>
  </entry>
  <entry>
    <title>Module &#039;Broken Anchor&#039; pour Drupal version 6.x-1.0-rc2</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1672" />
    <id>http://artisan.karma-lab.net/node/1672</id>
    <published>2008-10-06T18:53:56+02:00</published>
    <updated>2008-10-08T00:24:07+02:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="Drupal" />
    <category term="drupalfr.org" />
    <category term="OK" />
    <summary type="html"><![CDATA[<p>
  Une petite modularisation de la version précédente. Maintenant la découverte des contenus est "hookable" à partir de modules tiers. 
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
  Une petite modularisation de la version précédente. Maintenant la découverte des contenus est "hookable" à partir de modules tiers. 
</p>
<!--break-->
<p>
Mise à part cela, des statistiques d'avancement ont été ajoutées, quelques corrections aussi, et c'est un peu plus rapide que la dernière version.
</p>
<p>
  Sinon, le projet est passé sur <a class='external' target='_blank' href='http://drupal.org/project/broken_anchor' >drupal.org</a>, donc s'il y a des <a class='external' target='_blank' href='http://drupal.org/project/issues/broken_anchor?states=all' >anomalies</a>, c'est ici que ça se passe.
</p>    ]]></content>
  </entry>
  <entry>
    <title>Module &#039;WebDAV&#039; pour Drupal version 6.x-0.9.5-dev</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1671" />
    <id>http://artisan.karma-lab.net/node/1671</id>
    <published>2008-10-06T02:02:21+02:00</published>
    <updated>2008-10-08T00:26:27+02:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="Drupal" />
    <category term="drupalfr.org" />
    <category term="OK" />
    <summary type="html"><![CDATA[<p>
   Cette version est avant tout une optimisation des performances (environ 30%), ça va être difficile de faire mieux sans me coltiner la ré-écriture du serveur WebDAV du projet PEAR.
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
   Cette version est avant tout une optimisation des performances (environ 30%), ça va être difficile de faire mieux sans me coltiner la ré-écriture du serveur WebDAV du projet PEAR.
</p>
<!--break-->
<p>
<ul>
<li>Première implémentation d'un système de cache (voir dans les settings). Celui sur les membres semble bien fonctionner. </li>
<li>Ajout d'un script de test utilisant PerlDAV (et ajout du client qui va avec).</li>
<li>fix - Création de doubles teasers.</li>
<li>fix - Les réglages par défaut des nodes n'étaient pas respectés. </li>
<li>Ajout d'un réglage pour empêcher la publication automatique d'un node créé par WebDAV</li>
</ul>
</p>    ]]></content>
  </entry>
  <entry>
    <title>Module &#039;WebDAV&#039; pour Drupal version 6.x-0.9.4-dev</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1668" />
    <id>http://artisan.karma-lab.net/node/1668</id>
    <published>2008-10-03T14:02:55+02:00</published>
    <updated>2008-10-08T00:27:16+02:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="Drupal" />
    <category term="drupalfr.org" />
    <category term="OK" />
    <summary type="html"><![CDATA[<p>Cette nouvelle version est un correctif de la version précédente.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>Cette nouvelle version est un correctif de la version précédente.</p>
<ul>
<li>Fix. Erreur sur le GET en mode browser.</li>
<li>Fix. Incorporation des erreurs webdav au système drupal lorsqu'une erreur est détectée.</li>
</ul>
    ]]></content>
  </entry>
  <entry>
    <title>Module &#039;Broken Anchor&#039; pour Drupal version 6.x-1.0-dev</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1666" />
    <id>http://artisan.karma-lab.net/node/1666</id>
    <published>2008-10-03T02:48:18+02:00</published>
    <updated>2008-10-08T00:24:34+02:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="Drupal" />
    <category term="Aucun" />
    <category term="OK" />
    <summary type="html"><![CDATA[<p>Version initiale</p>    ]]></summary>
    <content type="html"><![CDATA[<p>Version initiale</p>    ]]></content>
  </entry>
  <entry>
    <title>Module &#039;Broken Anchor&#039; pour Drupal</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1665" />
    <id>http://artisan.karma-lab.net/node/1665</id>
    <published>2008-10-03T02:45:14+02:00</published>
    <updated>2008-10-08T00:23:52+02:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="Drupal" />
    <category term="Artisanat" />
    <category term="drupalfr.org" />
    <category term="Planet Libre" />
    <summary type="html"><![CDATA[<p>
   Broken Anchor est un module Drupal dont le but est de passer en revue l'ensemble des nodes et commentaire à la recherche de liens cassés et d'adresses email en clair. 
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
   Broken Anchor est un module Drupal dont le but est de passer en revue l'ensemble des nodes et commentaire à la recherche de liens cassés et d'adresses email en clair. 
</p>
<!--break-->
<p>
  Dans son fonctionnement standard, le module utilise le CRON de Drupal. A chaque itération le moteur va pouvoir analyser le contenu des nodes, des commentaires, ou les deux. Pour chaque catégorie de contenu, il est possible de spécifier un nombre maximum à analyser. Il est aussi possible de désactiver l'analyse d'un type de contenu (par exemple les commentaires). 
</p>
<p>
  Sur chaque contenu sont appliqué l'ensemble des formats d'entrées qui lui sont associés de sorte à avoir un résultat équivalent à ce qui est affiché. Ensuite sont recherché l'ensemble des chaînes correspondant à des URL (balise HREF, IMG, etc.) et effectue une connexion sur le site associé pour en vérifier le statut. Il est possible dans les réglages d'ajouter des exceptions. 
</p>
<p>
  De manière optionnelle, le moteur va aussi rechercher des motifs correspondant à des adresses courriel en clair (qu'elles soient ou pas dans un href). Là aussi il est possible d'ajouter des exceptions.
</p>
<p>
  Le module fournit ensuite un rapport paginé, classé par ID de contenu (commentaire ou node) avec un lien vers l'adresse fautive, un autre vers l'édition du contenu fautif, et un statut indiquant l'erreur rencontré (404 Not Found, 403 Forbidden, Timeout, etc.)
</p>
<p>
  Pour chaque ligne il est possible de relancer la vérification qui du coup portera sur ce seul contenu, faisant disparaître les erreurs du rapport s'il a été corrigé. 
</p>
<p>
  Voilà, j'espère que cela servira à d'autres et bonne chasse au liens cassés. 
</p>
</p>    ]]></content>
  </entry>
</feed>
