<?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/1535"/>
  <link rel="self" type="application/atom+xml" href="http://artisan.karma-lab.net/node/1535/atom/feed"/>
  <id>http://artisan.karma-lab.net/node/1535/atom/feed</id>
  <updated>2008-11-18T12:32:06+01:00</updated>
  <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>
</feed>
