Structure de base d'un module Drupal
Partie II du guide pratique pour créer des modules de base Drupal 8
De .info aux tests, uniquement les bases
Structure de base
loremipsum.info.yml
name: Lorem ipsum type: module description: 'Générateur Lorem ipsum pour Drupal' package: Development core: 8.x configure: loremipsum.form
Les fichiers info sont dĂ©sormais formatĂ©s en YML, et la diffĂ©rence entre modules et thĂšmes doit ĂȘtre claire via la dĂ©claration du type. La dĂ©claration config pointe vers une route (plus d'infos plus tard), sinon il n'y a rien d'autre. En fait, c'est le seul fichier dont votre module aura besoin. AprĂšs avoir sauvegardĂ© ce fichier (dans le dossier root/modules), vous pouvez activer votre module dans /admin/modules sans casser votre site. Mais comme vous le verrez plus loin, ce n'est pas suffisant.
loremipsum.module
<?php use Drupal\Core\Routing\RouteMatchInterface; /** * ImplĂ©mente hook_help(). */ function loremipsum_help($route_name, RouteMatchInterface $route_match) { switch ($route_name) { case 'help.page.loremipsum': return t(' <h2>GĂ©nĂ©rateur Lorem ipsum pour Drupal.</h2> <h3>Instructions</h3> <p>Lorem ipsum dolor sit amet... <strong>Je plaisante !</strong></p> <p>DĂ©compressez dans le dossier <em>modules</em> (actuellement Ă la racine de votre installation Drupal 8) et activez-le dans <strong>/admin/modules</strong>.</p> <p>Ensuite, rendez-vous sur <strong>/admin/config/development/loremipsum</strong> et entrez votre propre jeu de phrases pour gĂ©nĂ©rer un texte alĂ©atoire (ou utilisez le Lorem ipsum par dĂ©faut).</p> <p>Enfin, visitez <strong>www.example.com/loremipsum/generate/P/S</strong> oĂč :</p> <ul> <li><em>P</em> est le nombre de <em>paragraphes</em></li> <li><em>S</em> est le nombre maximal de <em>phrases</em></li> </ul> <p>Il existe aussi un bloc gĂ©nĂ©rateur oĂč vous pouvez choisir le nombre de paragraphes et de phrases, et il s'occupe du reste.</p> <p>Si nĂ©cessaire, il existe aussi une permission spĂ©cifique <em>generate lorem ipsum</em>.</p> <h3>Attention</h3> <p>La plupart des bugs ont Ă©tĂ© corrigĂ©s, les failles bouchĂ©es, des fonctionnalitĂ©s ajoutĂ©es. Mais ce module est en cours de dĂ©veloppement. Merci de rapporter bugs et suggestions, ok ?</p> '); } }
Il est bon de placer ici au moins un appel Ă hook_help(). Notez aussi l'instruction use qui importe la classe RouteMatchInterface. Ceci est principalement dĂ» au fait que hook_menu() n'existe plus.
⊠Et en avançant, vous verrez que le fichier .module servira aussi Ă contenir des informations de thĂšme. Gardez cela en tĂȘte.
loremipsum.install
<?php /** * @file * Fonctions d'installation pour le module Lorem ipsum. */ use Drupal\user\RoleInterface; /** * Implémente hook_install(). */ function loremipsum_install() { user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array( 'generate lorem ipsum' => TRUE, )); }
Ici, on utilise une autre classe : RoleInterface. Essentiellement, ce fichier informe Drupal : « DÚs que ce module est activé, trouvez la permission 'generate lorem ipsum' et activez-la ».
Mais oĂč cette permission est-elle dĂ©finie ?
loremipsum.permissions.yml
generate lorem ipsum: title: 'Générer du Lorem ipsum'
Comme vous le voyez, c'est bien plus simple que d'implémenter hook_permission(). La syntaxe complÚte est documentée dans la documentation de PermissionHandler.
loremipsum.routing.yml
loremipsum.generate: path: '/loremipsum/generate/{paragraphs}/{phrases}' defaults: _controller: '\Drupal\loremipsum\Controller\LoremIpsumController::generate' requirements: _permission: 'generate lorem ipsum' loremipsum.form: path: '/admin/config/development/loremipsum' defaults: _form: '\Drupal\loremipsum\Form\LoremIpsumForm' _title: 'ParamĂštres Lorem ipsum' requirements: _permission: 'administer site configuration'
Le fichier de routage remplace lâappel Ă hook_menu(). Chaque entrĂ©e (sans indentation) dĂ©finit une route avec des lignes indentĂ©es dĂ©taillant ses paramĂštres spĂ©cifiques.
La route loremipsum.generate définit une page qui accepte deux arguments entre accolades {}; elle correspond à un contrÎleur (plus tard expliqué), tandis que loremipsum.form correspond à un formulaire de configuration avec un titre.
Les deux routes requiĂšrent des permissions, mais vous pouvez les remplacer par _access: 'TRUE' pour un accĂšs libre.
loremipsum.services.yml
Permet de déclarer un service personnalisé.
loremipsum.links.menu.yml
loremipsum.form: title: 'ParamĂštres Lorem Ipsum' description: 'Configurer les paramĂštres du module Lorem Ipsum.' route_name: loremipsum.form parent: 'system.admin_config_development'
Alors que le fichier de routage crée la page à /admin/config/development/loremipsum, ces définitions sont nécessaires pour ajouter les pages dans le menu Administration.
loremipsum.links.task.yml
Définitions pour créer des tùches locales (onglets) supplémentaires pour une route donnée.
loremipsum.links.action.yml
Définitions pour créer des actions locales (boutons) supplémentaires pour une route donnée.
loremipsum.links.contextual.yml
DĂ©finitions pour crĂ©er des actions contextuelles supplĂ©mentaires pour un Ă©lĂ©ment de lâinterface utilisateur.
loremipsum.libraries.yml
Utilisé pour déclarer les dépendances aux bibliothÚques CSS et Javascript. Plus de détails dans la documentation correspondante.
README.md
Décompressez dans le dossier *modules* (actuellement à la racine de votre installation Drupal 8) et activez-le dans `/admin/modules`.
Puis rendez-vous sur `/admin/config/development/loremipsum` et entrez votre propre série de phrases pour générer un texte aléatoire (ou utilisez le Lorem ipsum par défaut).
Enfin, visitez `www.example.com/loremipsum/generate/P/S`, oĂč:
- *P* est le nombre de *paragraphes*
- *S* est le nombre maximal de *phrases*
Il existe aussi un bloc gĂ©nĂ©rateur oĂč vous pouvez choisir combien de paragraphes et de phrases, et il fera le reste.
Si besoin, une permission spécifique *generate lorem ipsum* est disponible.
Attention
---------
La plupart des bugs ont été corrigés, les failles comblées, des fonctionnalités ajoutées. Mais ce module est toujours en cours de développement. Merci de signaler bugs et suggestions, ok ?
Oui, les fichiers README sont désormais écrits au format Markdown. PlutÎt cool, si vous me demandez.
Passons maintenant aux dossiers pour examiner plus en détail certains aspects.
LICENSE.TXT
Nâincluez pas de fichier LICENSE.txt (ou Ă©quivalent). Le script de packaging lâajoutera automatiquement.
/config/install/loremipsum.settings.yml
loremipsum:
page_title: 'Lorem ipsum'
source_text: "Lorem ipsum dolor sit amet, consectetur adipisci elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
Ce fichier contient les paramÚtres par défaut qui sont assignés aux champs correspondants via le fichier suivant :
loremipsum: page_title: 'Lorem ipsum' source_text: "Lorem ipsum dolor sit amet, consectetur adipisci elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
Ce fichier contient les paramÚtres par défaut qui sont assignés aux champs correspondants via le fichier suivant :
/config/schema/loremipsum.schema.yml
loremipsum.settings: type: config_object label: 'ParamÚtres Lorem Ipsum' mapping: loremipsum: type: mapping mapping: page_title: type: text label: 'Titre de la page du générateur Lorem ipsum :' source_text: type: text label: 'Texte source pour la génération de lorem ipsum :' block.settings.loremipsum_block: type: block_settings label: 'Bloc Lorem ipsum' mapping: loremipsum_block_settings: type: text label: 'ParamÚtres du bloc Lorem ipsum'
Le fichier de schĂ©ma est utilisĂ© mĂȘme si vous ne dĂ©finissez pas de table personnalisĂ©e pour votre module â ici vous pouvez voir les valeurs par dĂ©faut assignĂ©es aux champs du formulaire de configuration.
En dĂ©veloppant ce code, jâai dĂ©couvert que prĂ©remplir les champs Ă©tait lâune des tĂąches les plus complexes. Heureusement, il existe un module pour cela : Configuration Inspector pour Drupal 8, qui vous aidera Ă dĂ©boguer les paramĂštres par dĂ©faut.
De plus, le fichier de schéma YML est trÚs utile à bien des égards.
/src/Controller/LoremIpsumController.php
<?php namespace Drupal\loremipsum\Controller; // Modification suivant https://www.drupal.org/node/2457593 // Voir https://www.drupal.org/node/2549395 pour les mĂ©thodes dĂ©prĂ©ciĂ©es // use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Html; // Utiliser Html au lieu de SafeMarkup /** * Routines du contrĂŽleur pour les pages Lorem ipsum. */ class LoremIpsumController { /** * Construit le texte Lorem ipsum avec des arguments. * Ce callback est mappĂ© au chemin * 'loremipsum/generate/{paragraphs}/{phrases}'. * * @param string $paragraphs * Le nombre de paragraphes Ă gĂ©nĂ©rer. * @param string $phrases * Le nombre maximal de phrases pouvant ĂȘtre gĂ©nĂ©rĂ©es dans un paragraphe. */ public function generate($paragraphs, $phrases) {
Nous arrivons au cĆur du module, une classe avec une unique mĂ©thode gĂ©nĂ©rant le texte de remplissage. Comme vous voyez, la mĂ©thode dans la classe LoremIpsumController correspond Ă l'entrĂ©e dans le fichier YAML de routage :
Le cadre blanc montre le code du fichier loremipsum.routing.yml et lâarriĂšre-plan montre le fichier avec lequel nous travaillons.
Continuons, le fragment de code suivant récupÚre les paramÚtres du module et les sauvegarde pour une utilisation ultérieure :
// ParamÚtres par défaut. $config = \Drupal::config('loremipsum.settings'); // Titre de la page et texte source. $page_title = $config->get('loremipsum.page_title'); $source_text = $config->get('loremipsum.source_text');
Les paramÚtres mentionnés ci-dessus (loremipsum.page_title et loremipsum.source_text) proviennent du fichier YAML de configuration :
Puis on éclate les phrases de $source_text en un tableau :
$repertory = explode(PHP_EOL, $source_text);
Et on utilise ce tableau pour construire les paragraphes :
$element['#source_text'] = array(); // Générer X paragraphes avec jusqu'à Y phrases chacun. for ($i = 1; $i <= $paragraphs; $i++) { $this_paragraph = ''; // Quand on dit "jusqu'à Y phrases", on ne veut pas dire "de 1 à Y". // On commence donc à la moitié. $random_phrases = mt_rand(round($phrases / 2), $phrases); // Ne pas répéter la derniÚre phrase. $last_number = 0; $next_number = 0; for ($j = 1; $j <= $random_phrases; $j++) { do { $next_number = floor(mt_rand(0, count($repertory) - 1)); } while ($next_number === $last_number && count($repertory) > 1); $this_paragraph .= $repertory[$next_number] . ' '; $last_number = $next_number; } //$element['#source_text'][] = SafeMarkup::checkPlain($this_paragraph); $element['#source_text'][] = Html::escape($this_paragraph); }
Notez que ['#source_text'] est un tableau rendu transmis au template, et que chaque élément passe par Html::escape() pour la sécurité.
Enfin, on donne un titre Ă notre tableau rendu, on assigne la fonction thĂšme et on le retourne :
//$element['#title'] = SafeMarkup::checkPlain($page_title); $element['#title'] = Html::escape($page_title); // Fonction thĂšme. $element['#theme'] = 'loremipsum'; return $element; } }
Mais avant de passer ces variables Ă notre template, il faut sâen occuper.
Ătape suivante ;
Thématiser le module.
Puis ;
Ajouter un formulaire de configuration.
Définir un bloc pour ce module.
Ăcrire des tests pour ce module.