Drupal avancé un cms pour développeurs christophe villeneuve

Page 1


Choisissez le plus puissant et le plus évolutif des outils pour créer vos sites web et mobiles ! Découvrez comment bien démarrer avec Drupal Concevez progressivement un site web complet en suivant une étude de cas Développez vos sites Drupal en utilisant la puissance de son API Adaptez votre site à la consultation sur un smartphone ou une tablette Choisissez les modules Drupal les plus intéressants pour votre site web Apprenez à écrire effi cacement vos scripts Drupal Illustrez vos contenus avec des images, sons ou vidéos Cet ouvrage a pour objectif de rendre les webmasters débutants et chevronnés autonomes avec Drupal, aussi bien pour l’utilisation de son interface graphique, que pour les lignes de code.

À qui s’adresse cet ouvrage ? Aux créateurs, administrateurs et développeurs de sites Drupal Aux agences web, chargés de marketing et responsables de communication

Pour que l’informatique soit un outil et non

un ennemi !

Pour maîtriser Drupal Drupal est l’un des CMS (Content Management System, ou SGC, Système de gestion de contenu, en français) les plus puissants au monde. C’est également un framework qui propose une API pour tous les développeurs donnant entre autres accès à des milliers de modules supplémentaires. C’est pourquoi les professionnels s’orientent vers Drupal, qui répond mieux aux attentes et contraintes des métiers du Web en raison de son architecture souple et modulaire et de sa capacité à s’adapter aux différents besoins des sites Internet.

Auteur très infl uent de la communauté PHP, Christophe Villeneuve coorganise des événements renommés (Forum PHP, Drupagora, DrupalCamp, etc.), est


conférencier, contribue à différents projets (Firefox OS, elePHPant PHP...) et est trésorier dans des associations telles que l’association française de Drupal ou l’AFUP (Association française des utilisateurs de PHP). Visible sur de nombreuses plates-formes, il anime les émissions « Cyberculture » et « Hotline » sur la radio Ici et maintenant une à deux fois par mois et rédige fréquemment des articles pour les magazines Programmez, Linux pratique... et pour de nombreux blogs. Vanessa Kovalsky David est très visible également, avec l’organisation des Journées du logiciel li bre à Lyon et l’animation de nombreux ateliers et conférences sur Lyon. Conférencière sur les deux derniers DrupalCamp, elle utilise Drupal au quotidien en tant que lead développeuse et chef de projet sur différents projets pour des clients de toute taille.


Christophe Villeneuve Vanessa Kovalsky David

Drupal avancé Un CMS pour développeurs Préface de Frédéric G. Marand


ÉDITIONS EYROLLES 61, bd Saint-Germain 75240 Paris Cedex 05 www.editions-eyrolles.com

En application de la loi du 11 mars 1957, il est interdit de reproduire intégralement ou partiellement le présent ouvrage, sur quelque support que ce soit, sans l’autorisation de l’Éditeur ou du Centre Français d’exploitation du droit de copie, 20, rue des Grands Augustins, 75006 Paris. © Groupe Eyrolles, 2015, ISBN : 978-2-212-14011-8


DANS LA MÊME COLLECTION F. DRAILLARD. – Premiers pas en CSS 3 & HTML 5. N°13944, 6e édition, 2015, 480 pages. I. CANIVET. – Bien rédiger pour le web. N°13750, 3e édition, 2014, 736 pages. X. DELENGAIGNE. – Organiser sa veille sur Internet. N°13945, 2e édition, 2014, 320 pages. F.-X. BOIS, L. BOIS. – WordPress 3.5 pour des sites web efficaces. N°13801, 2013, 346 pages. A. FAQUE. – Google Android 4 efficace. N°13721, 2013, 232 pages. D. ROCH. – Optimiser son référencement Wordpress. N°13714, 2013, 220 pages. D. ROBERT. – Gimp 2.8 N°12700, 2013, 360 pages.

SUR LE MÊME THÈME H. COCRIAMONT. – Réussir son premier site Joomla! 2.5. N°13425, 2012, 160 pages. H. GIRAUDEL, R. GOETTER. – CSS3 : Pratique du design web. N°14023, 2015, 372 pages. S. POLLET-VILLARD. – Créer un seul site pour toutes les plates-formes. N°13986, 2014, 144 pages. K. DELOUMEAU-PRIGENT. – CSS maintenables avec Sass et Compass. N°13640, 2e édition, 2014, 252 pages. J. PATONNIER, R. RIGOT. – Projet responsive web design. N°13713, 2013, 162 pages. C. SCHILLINGER. – Intégration web – Les bonnes pratiques. N°13370, 2012, 390 pages. S. DAUMAL. – Design d’expérience utilisateur. N°13456, 2012, 390 pages. O. ANDRIEU. – Réussir son référencement web. N°13825, 6e édition, 2013, 660 pages. O. ANDRIEU. – SEO zéro euro.


N°14033, 2014, 224 pages. R. RIMELÉ, R. GOETTER. – HTML 5 – Une référence pour le développeur web. N°13638, 2e édition, 2013, 752 pages. E. MARCOTTE. – Responsive web design. N°13331, 2011, 160 pages. Retrouvez nos bundles (livres papier + e-book) et livres numériques sur http://izibook.eyrolles.com


Préface

J+1. 10h15. Le site a été mis en production hier, les semaines ou les mois de préparation sont enfin terminés. Vous avez passé une première nuit blanche à le veiller et tout fonctionne ; les contenus sont en place, les visiteurs s’inscrivent, les serveurs ronronnent, les premières commandes ont commencé à rentrer. Bien sûr, il est basé sur Drupal : que vous l’ayez développé vous-même, ou qu’une agence vous l’ait fourni, c’était le moyen le plus sûr d’être opérationnel au plus vite, de valider les concepts en développant rapidement, de pouvoir changer d’avis jusqu’au dernier moment. Et c’était le choix gagnant, puisque vous en êtes là. Et maintenant ? Évidemment, pour être plus vite en ligne, le gros du développement a été réalisé directement en utilisant au maximum les outils de développement rapide qui font le premier attrait de Drupal : des pages de liste créées avec Views UI, des types de contenus spécialisés créés dans l’interface, des déclenchements d’événements insérés avec Rules admin, des champs, surtout, par dizaines ou par centaines. C’est votre Minimal Viable Product et vous savez déjà ce que vous voudriez voir dans la version 2, qui n’avait pas sa place dans le budget et les délais de la version 1. Vous savez aussi que les plus grands projets Drupal, ceux qui font les showcases et les présentations aux DrupalCon, utilisent Drupal d’une autre façon, 100 % en code pour accéder à la traçabilité des évolutions et, problème merveilleux à avoir, pour tenir la charge face à une audience en croissance. Et c’est là votre prochaine frontière : passer du développement rapide d’un site à l’évolution d’un site rapide. C’est sur cette deuxième étape de votre parcours Drupal que le livre de Christophe et Vanessa se propose de vous aider : découvrir en pratique comment, pour chaque fonctionnalité visuelle de Drupal, il existe un moyen de passer d’une version initiale créée manuellement, pour sortir au plus vite, à une version programmée, plus rapide et en mesure de respecter de plus près les besoins et les souhaits du métier pour lequel un site a été créé. Et cela sans devoir investir lourdement dans une réécriture nécessitant de devenir un développeur hard core, mais toujours par petites touches, une vue après l’autre, un formateur de champ après l’autre, un module après l’autre, sur le chemin qui fera de vous un développeur Drupal de plus à avoir conquis son outil. Frédéric G. MARAND CEO OSInet Core maintainer Drupal XML-RPC


Table des matières

AVANT-PROPOS Présentation de l’ouvrage À qui s’adresse cet ouvrage ? Structure du livre Remerciements spéciaux 1. BIEN DÉMARRER AVEC DRUPAL Les prérequis pour Drupal Décomposition Environnement AMP Avec un logiciel En ligne de commande Configurer votre environnement Création d’un VirtualHost pour Drupal Installation Installer un premier site avec Drupal Les différentes étapes Installer Drupal Installer en ligne de commande Configurer votre IDE Eclipse PDT (PHP Development Tools) Netbeans Les outils GIT Drush Installation Utilisation Devel DevelThemer 2. LES CONCEPTS FONDAMENTAUX DANS DRUPAL Nœud (Node) Qu’est-ce qu’un nœud ? À quoi cela sert-il ? Exemple Entité (entity) Qu’est-ce qu’une entité ?


À quoi cela sert-il ? Exemple Champ (field) Qu’est-ce qu’un champ ? À quoi peut-il être rattaché ? Exemple Hook Qu’est-ce qu’un hook ? Comment et où écrire des hooks ? Exemple 3. LES MODULES Qu’est-ce qu’un module ? L’API des modules Pourquoi une API ? Arborescence Composition Les bonnes pratiques à respecter Fichier <monmodule>.info Fichier <monmodule>.module Autres fichiers Exemple : un module à la carte Description Fichier .info : menu_for_all.info Fichier .module : menu_for_all.module Hook_help() Hook_action_info() Hook_menu() Actions du module hook_basic_action() hook_unblock_user_action() hook_node_sticky_action() Mise en place du module Installation Configuration Exécution Conclusion 4. CRÉER UN TYPE DE CONTENU EN PROGRAMMANT Un nouveau type de contenu avec l’interface d’administration Ajouter un type de contenu sans programmer Ajouter des champs à notre type de contenu Champs de type Texte Fields et entité Création du type d’entité Menus


Ajouter une interface d’administration Afficher l’entité Features À la découverte de Features Déploiement d’un code Features et modification Voir les différences avec Diff La taxonomie Ajouter une taxonomie avec l’interface d’administration Créer son premier vocabulaire Ajouter des termes à notre vocabulaire Utiliser un vocabulaire dans un type de contenu Gérer les taxonomies par le code Créer un vocabulaire depuis un module Déclarer des termes Développer le champ Lieu pour le bundle Diner Permettre la suppression du vocabulaire lors de la désinstallation 5. L’AFFICHAGE AVANCÉ AVEC LE MODULE VIEWS Views : présentation Qu’est ce que Views ? Liste des vues Ajouter une vue pour lister tous les plats Fonctionnalités avancées de Views Créer une vue bloc Les paramètres avancés des vues Filtres contextuels : limiter aux plats d’un utilisateur Relation : ajouter les restaurants et leurs adresses Écrire une vue dans un module Création du module et déclaration de l’utilisation de l’API Views Déclaration de la vue Ajout de fonctionnalités Ajout d’un type de vue (hook views_data) Ajout d’un handler : filtre sur les types de menus sous forme d’une liste de sélection 6. MOTEUR DE RÈGLES ET VALIDATION Envoyer un e-mail à l’auteur d’un contenu lors de la publication d’un commentaire Ajouter une action Envoi de courriel Déclencher les actions créées Des règles plus souples avec Rules Ajouter une règle par l’interface graphique Création d’une règle en programmant Création d’une action, d’une condition et d’un événement par le code Gérer un workflow de publication simple avec Drupal Un circuit plus complexe avec le module Workflow


Création de notre premier workflow Utilisation d’un workflow sur une entité 7. GÉRER LES GROUPES D’UTILISATEURS ET LEURS SPÉCIFICITÉS AVEC ORGANIC GROUPS Le concept d’utilisateur et de rôles dans Drupal À la découverte de l’interface d’administration des utilisateurs et des rôles Ajouter un utilisateur Rôles existants et ajout de rôle L’ajout d’utilisateurs et de rôles par la programmation La gestion des profils utilisateurs Gestion du profil par l’interface d’administration Ajout de champs à l’entité Utilisateur par le code La gestion des droits Gestion des droits avec l’interface d’administration Ajouter des permissions à notre entité Menus Des groupes d’utilisateurs (OG) Création d’un groupe et paramétrages Contenus spécifiques aux groupes Membres et permissions d’un groupe Gestion des membres d’un groupe Gestion des permissions et des rôles d’un groupe 8. GÉRER LES TERMINAUX MOBILES Un seul site avec un affichage et un contenu adapté ? Adapter la mise en forme avec un thème en Responsive Design Découverte et installation d’un thème Création d’un thème à partir de Zen Les différents fichiers qui composent un thème Proposer des webservices pour un site ou une application mobile Utiliser le module Services Développer des ressources supplémentaires pour Services Panels/Panelizer : présentation Quels-sont ces modules ? Construire sa propre page Définir ce qui sera personnalisé Choisir ce qui sera disponible Configuration de la présentation Configurer le contenu Ajouter des éléments de contenu Voir le résultat Personnaliser les éléments de contenu Observations des modifications 9. LES TESTS Bootstrap


Qu’est-ce que le bootstrap ? Étendre le bootstrap Tests unitaires Qu’est-ce que PHPUnit ? Installer PHPUnit PHPUnit avec Drupal Préparer son module de test Fichier <monmodule>.test.php Créer des fonctions de test Premier test : un hook Deuxième test : une page Lancer les tests Tests fonctionnels Qu’est-ce que Selenium HQ ? Installer Selenium IDE Selenium HQ et Drupal Associer les tests Installer Selenium HQ server Préparer son module de test fonctionnel Fichier <monmodule>.test.php Créer des fonctions de tests Premier test : connexion avec le navigateur Deuxième test : détection du module Troisième test : ouverture d’une page Quatrième test : insertion de données Cinquième test : affichage de la page visible Exécuter l’ensemble des tests Conclusion 10. LA RECHERCHE : NATIVE ET ÉTENDUE AVEC SOLR ET FACET API La recherche native dans Drupal Activation et mise en place de la recherche Indexation du contenu Search API avec Solr pour indexer et rechercher dans notre entité Menus Installation et configuration de Search API Installation de Solr et déclaration en tant que serveur de recherche Ajout d’un index sur l’entité Menus Affichage de la recherche dans nos menus Utilisation de Facet API et de Views pour des recherches par facettes Créer l’index des nœuds et la vue associée Filtrer la recherche avec Facet API Aller plus loin avec les modules complémentaires de Search API Autocomplete Spellcheck pour obtenir des suggestions en cas d’erreur de frappe


Saved searches pour que nos utilisateurs retrouvent leurs recherches Multi-index searches : remplacer le bloc de recherche natif de Drupal Indexer les fichiers joints avec Search Api Attachments et Apache Tika 11. GESTION AVANCÉE DES IMAGES AVEC MEDIA Insérer du multimédia Le module Media Présentation Configuration La liste des extensions Le module Multimédia dans un champ Type de contenu Le champ multimédia Le champ document Modifier la valeur du champ image Le contenu Le bouton Multimedia Le bouton Document Multimédia dans le body (content) Installation du module Wysiwyg Configuration Wysiwyg Installation de la bibliothèque CKEditor Configuration Création d’un article Créer une animation bandeau Installation du module Views Slideshow Configuration du cache Création du type de contenu Création d’un contenu Afficher notre bandeau Améliorer l’animation Publier notre vue 12. DÉPLOIEMENT Déploiement avec FTP et phpMyAdmin Transférer les fichiers avec FileZilla Transfert de la base de données avec phpMyAdmin Déploiement avec Drush Drush et les alias pour déployer facilement Drush make INDEX


Avant-propos

Drupal fait partie de la catégorie des CMS (Content Management System, ou SGC, Système de gestion de contenu, en français). C’est également un framework qui propose une API pour tous les développeurs donnant entre autres accès à des milliers de modules supplémentaires. Son approche est complètement différente de celle des autres CMS. Drupal part du principe qu’un emplacement dans une page est un bloc, unique. Ce bloc peut être personnalisé à volonté et permet de définir une région (zone). À partir de plusieurs régions, il est possible de construire une page web. À titre de comparaison, les autres CMS partent d’une page web globale et proposent ensuite différentes options pour en construire l’intérieur. C’est pourquoi les professionnels s’orientent vers Drupal, qui répond mieux aux attentes et contraintes métier du Web en raison de son architecture souple et modulaire et de sa capacité à s’adapter aux différents besoins d’un site Internet.

Présentation de l’ouvrage Il suffit de naviguer sur Internet pour croiser, parfois sans même s’en rendre compte, des sites réalisés avec Drupal. Les exemples qui tirent parti de ce CMS vous ont sans doute donné envie d’en savoir plus ; vous avez donc décidé de le tester et de réaliser votre premier projet Drupal. Les fonctionnalités natives de Drupal, couplées avec les modules en provenance du site drupal.org, vous permettront déjà de réaliser aisément de nombreux sites. Toutefois, si vous voulez maîtriser ces fonctionnalités, vous serez vite... bloqué. Vous aurez en effet de fortes chances de fourmiller d’idées pour votre projet de site, mais vous ne saurez pas comment faire, techniquement parlant, pour les exploiter. L’ouvrage que vous tenez dans vos mains va répondre à cette attente et a pour ambition de vous faire quitter le niveau débutant pour passer au mode avancé. Notre expérience de Drupal, des possibilités qu’il offre et de sa documentation nous conduisent à vous proposer ce livre qui s’adresse donc à la fois aux lectrices et lecteurs n’ayant jamais touché à Drupal et à celles et ceux qui en connaissent déjà les bases et qui souhaitent aller plus loin. Comme il est possible d’atteindre un objectif de plusieurs façons avec Drupal, le nôtre sera de vous expliquer pas à pas quelques-unes des méthodes les plus efficaces pour répondre aux questions que vous pourrez vous poser tout au long de votre parcours initiatique. Ainsi, pour arriver à un résultat précis, vous pouvez toujours tester tous les modules disponibles ou effectuer le développement soit à partir de modules, soit de différentes


manières de configurations ou encore par du développement proprement dit. C’est pourquoi nous vous proposerons une méthode répondant au maximum de cas que vous rencontrerez dans vos différents projets. Notre méthodologie étant basée sur l’exemple, nous partirons d’une problématique donnée et nous essaierons de vous donner deux solutions associées : l’une réalisable pour un site builder en utilisant et en configurant les différents modules existants ; l’autre en utilisant l’API de Drupal, qui permet, via quelques lignes de code supplémentaires, de concevoir des applications robustes et évolutives. Les deux approches ne sont pas opposées et il arrive régulièrement que nous utilisions les deux : une partie du site est réalisée via des modules et une interface utilisateur classique il s’agit souvent de la partie que le client devra mettre à jour lui-même - et une autre partie sera développée en interne pour faciliter les évolutions, la maintenance et les performances du site. Nous vous renverrons, quand cela nous semblera nécessaire, vers la documentation officielle ou vers d’autres sources de documentation. Cependant, nous ferons le maximum pour que vous puissiez utiliser cet ouvrage comme manuel de référence pour vos projets Drupal, sans avoir besoin d’aller chercher d’autres informations ailleurs.

À qui s’adresse cet ouvrage ? Cet ouvrage s’adresse à celles et ceux qui ont une présence sur le Web et qui veulent découvrir ou approfondir leurs connaissances avec le CMS Drupal. Plus précisément, cet ouvrage s’adresse aux : directeurs et décideurs qui souhaitent comprendre ce qu’est un CMS et comment il fonctionne, pour ensuite adapter au mieux leurs besoins ; webmasters, développeurs et intégrateurs qui sont amenés à répondre aux attentes des utilisateurs, en leur permettant de mettre en place de nouvelles fonctionnalités ; lecteurs qui utilisent au quotidien la gestion de contenu pour alimenter un portail web, blog, etc. et qui souhaitent construire leurs propres sites web.

Structure du livre L’ouvrage que vous tenez entre les mains est découpé en douze chapitres qui expliquent pas à pas les points importants de la construction et de l’évolution d’une application web open source avec le CMS Drupal. L’objectif de cette série de chapitres est de détailler une à une les fonctionnalités qui font le succès de Drupal en termes de gestion de contenu. Le chapitre 1 commence par donner des informations sur les principaux outils dont nous aurons besoin tout au long de l’ouvrage. Ce chapitre nous aidera également à construire notre propre environnement de développement. Le chapitre 2 s’oriente vers les concepts fondamentaux de Drupal pour bien comprendre les nombreux termes utilisés par ce CMS, qui peuvent porter à confusion. Ces termes sont


utilisés tout au long de l’ouvrage. Le chapitre 3 est très important car il permet de comprendre l’API de Drupal. Pour cela, nous verrons les bonnes pratiques à respecter et le moyen de construire son propre module fonctionnel. Le chapitre 4 privilégie la création en aidant à construire notre propre type de contenu. Nous savons qu’un contenu est différent d’un site à l’autre et que les zones ne peuvent pas être identiques ; c’est pourquoi les approches de construction, de taxonomie et de Features seront abordées ici. Le chapitre 5 propose de s’initier à l’affichage dynamique des contenus. Nous aborderons le module Views et nous verrons également comment personnaliser notre site avec l’API de Drupal. L e chapitre 6 permet d’améliorer les moteurs de règles et de validations. En effet, lorsqu’un contenu est saisi sur une page web, nous pouvoir avoir besoin d’exécuter une action automatique supplémentaire. Pour ce faire, un contenu doit logiquement être validé et c’est pour cela que nous aborderons la gestion des workflows pour définir exactement les procédures de validation et de publication d’un contenu. Le chapitre 7 concerne la gestion des utilisateurs et de leurs droits associés. La notion de rôle est ici importante, surtout si plusieurs personnes fournissent du contenu. Ce chapitre aborde également la possibilité offerte par Drupal de gérer des communautés d’utilisateurs au travers de groupes - et de leurs membres associés - avec le module Organic Groups. L e chapitre 8 aborde l’affichage du contenu qui, tout en étant publié aisément, doit s’adapter à tous les types de terminaux (mobile, tablette, ordinateur...). Nous verrons ainsi comment créer un thème qui s’adapte aux différents écrans, comment transformer Drupal en fournisseur de webservices pour une application mobile et enfin comment gérer la composition d’une zone de contenu à l’aide du module Panels. Le chapitre 9 permet de valider les acquis via les différentes fonctionnalités et actions que nous avons générées dans les chapitres précédents. Nous avons donc choisi de tester un contenu web grandeur nature. Le chapitre 10 améliore les fonctions natives du moteur de recherche de Drupal, tout en conservant les spécificités de l’API. Nous aborderons donc les principaux modes de recherche proposés par Drupal, comme le mode étendu ou la recherche par facettes. Le chapitre 11 apporte davantage de diversité dans nos contenus grâce à l’ajout d’images et de vidéos. Nous verrons comment ajouter un bandeau supplémentaire sur la page d’accueil pour mettre une information plus en avant. Le chapitre 12 permet enfin d’effectuer une dernière action, cruciale, à savoir la livraison de notre site Drupal vers un serveur de production. Nous aurons ainsi passé en revue l’ensemble des étapes nécessaires à la création d’un site Drupal et de sa mise en ligne sur Internet. À noter que les fichiers sources associés à ce livre peuvent être télécharger sur www.editions-eyrolles.com.


Remerciements spéciaux L’ouvrage a vu le jour notamment grâce à la demande croissante de la communauté française rassemblée autour de Drupal. Nous remercions les deux contributeurs qui, avec nous, ont participé à cet ouvrage : Frédéric G. Marand, Core maintainer Drupal XML-RPC, qui a réalisé la préface. C’est un honneur pour nous de l’accueillir ici. Vincent Pontier (aka El Roubio), créateur de nombreux logos dont la mascotte elePHPant PHP, qui a apporté son coup de crayon pour illustrer ce livre.


Bien démarrer avec Drupal

1

Pour réaliser un premier projet avec Drupal, il est indispensable de posséder une plateforme de développement complète. Et une fois la configuration du CMS terminée, nous verrons dans ce chapitre quels sont les différents outils nécessaires et les extensions les plus populaires que nous utiliserons tout au long de l’ouvrage.

SOMMAIRE Les outils à posséder La configuration nécessaire pour Drupal


Drupal a besoin pour fonctionner d’un environnement de travail complet combinant serveur web, base de données et langage de programmation web. Voyons ensemble quels sont les logiciels prérequis pour utiliser Drupal et comment les installer sur votre propre ordinateur. Nous installerons ensuite Drupal et quelques outils complémentaires afin de faciliter notre travail avec ce CMS.

Les prérequis pour Drupal Comme de nombreux sites web s’appuyant sur des CMS open source, Drupal nécessite trois briques indispensables : PHP, le langage de programmation de Drupal, qui transforme notre code en informations que l’on peut afficher sur un navigateur web et donc lisibles pour tout internaute ; Apache (ou Nginx ou IIS), le chef d’orchestre, qui reçoit les demandes de consultation des pages visitées par les internautes via leur adresse web et sollicite Drupal (via PHP) afin de leur transmettre la page requise ; MySQL ou MariaDB, le gestionnaire de bases de données (SGBD) qui stocke de nombreuses informations que notre site affiche.

Décomposition Avant de démarrer un projet, nous devons vérifier certains prérequis matériels et logiciels pour être certains de pouvoir utiliser Drupal dans de bonnes conditions. Voici l’espace disque conseillé et les versions minimales requises pour les différents logiciels nécessaires au bon fonctionnement de Drupal. Tableau 1–1 Prérequis logiciels et matériels pour faire fonctionner Drupal Configuration

Valeur

Espace disque

Conseillé 60 Mo

Serveur web

Apache 1.3/2.x Nginx IIS 6+...

Gestionnaire de bases de données

MySQL 5.0.15 ou MariaDB PostgreSQL 8.3+ SQLite 3.3.7+

Langage

PHP 5.3 ou plus

Environnement AMP Il existe deux manières d’installer un environnement AMP (Apache, MySQL, PHP) : par l’intermédiaire d’un logiciel ou en ligne de commande. Avec un logiciel


Installer l’environnement AMP via un logiciel tout-en-un résout un certain nombre de problèmes de configuration, notamment parce qu’il est composé de programmes compatibles les uns avec les autres : serveur web, langage et SGBD. Suivant votre système d’exploitation, vous pourrez télécharger et installer le logiciel touten-un de votre choix. Tableau 1–2 Logiciels tout-en-un pour l’installation d’un environnement AMP Nom

URL

Linux

Win​dows

Mac

Xampp

http://apachefriends.org

x

x

x

Wamp​server

http://www.wampserver.com

x

Easy​PHP

http://www.easyphp.org

x

Mamp

http://mamp.info

Raid

https://github.com/crazy-max/neard

x x

Pour installer un environnement AMP sous Windows, nous choisissons d’utiliser le logiciel Xampp. Après avoir téléchargé la version qui correspond à notre système d’exploitation, nous lançons l’installation.

Figure 1–1 Premier écran d’installation de Xampp

Nous cliquons sur Next pour continuer.


Figure 1–2 Sélection des logiciels à installer avec Xampp

Nous laissons les composants sélectionnés par défaut et cliquons sur Next.

Figure 1–3 Choix du répertoire d’installation de Xampp

Nous choisissons ici de garder le répertoire C:\xampp, mais vous pouvez le changer sans aucun souci.


Figure 1–4 Plus d’informations sur Bitnami

La page suivante nous propose d’en savoir plus sur Bitnami (il s’agit d’un logiciel open source permettant de déployer des CMS en quelques clics), ce que nous refusons en décochant la case affichée à l’écran. Dans notre cas, nous préférons effectuer une installation manuelle pour détailler les différentes étapes importantes à suivre.

Figure 1–5 Xampp est maintenant prêt à être installé.

Xampp est prêt et nous cliquons sur Next pour lancer l’installation.


Figure 1–6 L’installation est en cours.

Voici la page que vous obtiendrez à la fin de l’installation.

Figure 1–7 L’installation est terminée.

L’installation est maintenant terminée et nous laissons l’option cochée pour démarrer Xampp. Le panneau de Xampp se lance alors et affiche ce qui suit.


Figure 1–8 Panneau de contrôle de Xampp

Pour installer Drupal, nous avons besoin de démarrer Apache et MySQL en cliquant sur Start au niveau des deux lignes correspondantes.

Figure 1–9 Apache et Mysql apparaissent en vert : ils sont lancés.

Pour vérifier le bon fonctionnement de notre Xampp, ouvrons un navigateur et rendonsnous à l’adresse suivante : http://localhost/xampp/index.php. Une page d’accueil de Xampp apparaît alors.


Figure 1–10 Page d’accueil de Xampp

Cette page nous indique que nous avons terminé l’installation de notre environnement AMP. Nous pouvons maintenant commencer sa configuration. En ligne de commande Pour installer notre environnement AMP en ligne de commande avec une distribution Linux, nous installons les paquets suivants. Installation d’Apache, MySQL, PHP $ sudo apt-get install apache2 mysql-server mysql-client php5 php5-cli php5-mysql php5-dev php5-gd php5-mcrypt libapache2-mod-php5 $ sudo a2enmod rewrite

Certains paquets nécessiteront des renseignements complémentaires. Il suffit de répondre aux différentes questions pour finaliser notre installation.

Configurer votre environnement Après avoir choisi et installé votre environnement en fonction de votre système d’exploitation, configurez-le pour améliorer la performance et faciliter l’utilisation du CMS Drupal. Ces opérations sont nécessaires sur un serveur de production. Cependant, certains hébergeurs mutualisés ne nous permettent pas de les effectuer, sauf s’ils signalent la compatibilité avec Drupal.

Si vous n’avez pas accès aux variables de configuration, par exemple sur un serveur mutualisé, voici la variable à ajouter dans le fichier .htaccess à la racine de votre site. Tableau 1–3 Serveur Fichier

Valeur

Obligatoire

Optionnel


.htaccess

directive Allow Override (différente de none) : All

X

Sur un serveur dédié ou sur votre propre machine avec un environnement AMP, modifiez les fichiers de configuration avec un éditeur de texte et ajoutez les variables listées dans les tableaux 1-4 et 1-5. Avec Xampp, vous pouvez cliquer sur l’onglet Config d’Apache et sélectionner le fichier concerné (php.ini ou my.cnf).

Figure 1–11 Accès au fichier de configuration via le panneau de contrôle de Xampp Tableau 1–4 Langage PHP (php.ini) Variable

Valeur

Obligatoire

Optionnel

Memory_limit

128 M (conseillé 256 M)

X

upload

40

X

Extension activée

PDO GD

X

error_reporting

E_ALL & ~E_NOTICE

X

display_errors

On

X

max_input_time

120

X

max_execution_time

60

X

Emplacement du fichier php.ini sous Linux Debian : /etc/php5/apache2/php.ini

Tableau 1–5 SGBD MySQL/MariaDB (my.cnf) Variable

Valeur

Obligatoire

Optionnel


Key_buffer

16 M

X

Key_buffer_size

32 M

Max_allowed_packet

16 M

X

thread_stack

512 K

X

thread_cache_size

8

X

max_connections

300

X

X

Emplacement du fichier my.cnf sous Linux : /etc/mysql/my.cnf

Création d’un VirtualHost pour Drupal Configurons Apache pour qu’il travaille en bonne intelligence avec Drupal. Pour ce faire, nous avons besoin de créer un fichier de configuration, appelé VirtualHost, du serveur web. Et nous allons demander à Apache de rediriger les internautes se connectant au site http://drupal7.local vers le bon répertoire local. Pour cela, nous allons créer un fichier que nous positionnerons, en fonction du système d’exploitation, dans l’un des répertoires suivants : sous Windows : (si C:\xampp est votre répertoire d’installation) : C:\xampp\apache\extra\httpd-vhosts.conf ; sous Mac OS : /Applications/XAMPP/etc/extra/httpd-vhosts.conf ; sous Linux : /etc/apache2/sites-available/drupal7-local.conf (fichier à créer). Sous Windows et Mac OS, il sera nécessaire d’ajouter les lignes suivantes à la fin de votre fichier de configuration. Code à ajouter à la fin du fichier de configuration (Windows et Mac OS) <VirtualHost *:80> ServerName drupal7.local DocumentRoot /var/www/drupal7.local <Directory /var/www/drupal7.local> AllowOverride All Order allow,deny allow from all </Directory> </VirtualHost>

Pensez à changer le chemin d’accès de DocumentRoot, en fonction de votre système d’exploitation, ainsi que le dossier qui contiendra votre Drupal. Windows : C:\xampp\htdocs\drupal Mac OS : /Applications/XAMPP/xamppfiles/htdocs/drupal Linux : /var/www/drupal

Nous allons ensuite faire correspondre notre adresse IP locale avec le nom que nous


avons choisi : drupal7.local. Nous devons modifier sur notre ordinateur le fichier hosts qui redirige une adresse Internet en lettres (ici http://drupal7.local) vers une adresse IP. ATTENTION Ce paramétrage du fichier hosts ne fonctionne que pour l’ordinateur sur lequel il est effectué. Vous ne pourrez donc pas accéder au site http://drupal7.local depuis un autre ordinateur.

L’emplacement de ce fichier dépend de votre système d’exploitation : sous Windows : C:\Windows\System32\drivers\etc\hosts (nécessite d’éditer le fichier en tant qu’administrateur du poste) ; sous Mac OS : /private/etc/hosts ; sous Linux : /etc/hosts . Code à mettre dans le fichier hosts 127.0.0.1 drupal7.local

Pour que les modifications effectuées sur ces deux fichiers soient prises en compte, il est obligatoire de redémarrer Apache. Nous avons désormais tous les prérequis nécessaires à l’installation de Drupal et à la configuration de notre poste. Nous pouvons donc aborder son installation.

Installation Installer un premier site avec Drupal Après avoir installé et configuré notre environnement AMP, il nous reste à déclarer le SGBD en utilisant phpMyAdmin. Par ailleurs, les identifiants à connaître sont : login de base de données ; mot de passe de base de données. Ces valeurs correspondent à celles que nous avons saisies lors de l’installation de notre environnement. En revanche, le nom de la base de données est souvent imposé par l’hébergeur. Nous le connaîtrons lors de l’ouverture de notre compte chez ce dernier. Les différentes étapes En résumé, les différentes étapes à connaître sont les suivantes. Nous installons tout d’abord notre environnement embarqué. Ensuite, nous devons créer une base de données via le webservice http://localhost/phpmyadmin. Lorsque nous nous trouvons dans cette interface, nous créons une base de données, nommée par exemple drupal .


Figure 1–12 Créer une base de données

Installer Drupal Nous devons télécharger la dernière version de Drupal, à partir d’un des liens suivants : http://www.drupal.org/project/drupal http://www.drupalfr.org

Nous devons ensuite suivre quelques étapes intermédiaires pour utiliser Drupal. 1 Décompresser le fichier téléchargé dans le dossier ROOT de notre environnement. Pour certains environnements, ce dossier se trouve dans htdocs ou www. 2 Créer dans le dossier site/default/ un dossier nommé File, puis y copier et renommer le fichier default.settings.php en settings.php. 3 Notre installation de Drupal peut alors commencer en ouvrant notre navigateur web à l’adresse suivante : http://localhost/drupal. 4 Drupal détecte automatiquement qu’il s’agit d’une nouvelle installation et nous aide dans la configuration du CMS. 5 Sélectionner la version proposée.


Figure 1–13 Version proposée

6 Si nous avons téléchargé la version disponible sur le site de l’association France et Francophonie, un écran supplémentaire est proposé pour nous permettre de choisir la langue.

Figure 1–14 Choix de la langue

7 Renseigner ensuite le nom de la base de données, celui de l’utilisateur et le mot de passe associé. Cette opération va configurer la base de données et un certain nombre de modules natifs sur l’installation du profil sélectionné.

Figure 1–15 Configuration de la base de données

8 Cette étape sert à personnaliser quelques informations sur notre site, comme son nom


ou son adresse électronique principale.

Figure 1–16 Configuration de base

9 Sur le même écran, nous configurons le premier compte administrateur en renseignant son adresse électronique et son mot de passe.

Figure 1–17 Compte administrateur

10 Il est ensuite possible de définir la zone de géolocalisation du site et d’être alerté automatiquement si Drupal ou l’un des modules a été mis à jour.


Figure 1–18 Zone de géolocalisation

L’installation est terminée.

Figure 1–19 Fin de l’installation

Installer en ligne de commande Pour installer Drupal en ligne de commande, nous devons au préalable installer Drush, un outil qui permet entre autres d’automatiser le CMS à l’aide de scripts (voir plus loin dans ce chapitre). Nous téléchargeons et décompressons Drupal à l’aide de la commande suivante : $ drush dl drupal

Nous obtenons l’écran suivant.


Figure 1–20 Installation avec Drush

Les fichiers d’installation de Drupal ayant été téléchargés et décompressés, un dossier appelé drupal apparaît. Avant de lancer l’installation, il est important de créer le dossier files et de lui ouvrir les droits en écriture : $ cd drupal $ cd sites/default $ mkdir files $ chmod 755 files $ cp default.settings.php settings.php $ chmod 666 settings.php

Pour poursuivre l’installation de Drupal, recopions ce qui suit dans le terminal : $ cd drupal $ drush site-install standard --account-name=admin --account-pass=admin --dburl=mysql://YourMySQLUser:RandomPassword@localhost/YourMySQLDatabase

Cette procédure crée un compte administrateur (admin/admin) et la base de données associée.

Configurer votre IDE Une fois Drupal installé et configuré, l’utilisation d’un IDE (Integrated Development Environment, ou environnement de développement intégré) est fortement conseillée, principalement pour faciliter le développement et le test de vos applications web. Et là encore, plusieurs solutions s’offrent à vous. Il existe en effet de nombreux IDE, open source ou non. Nous allons ici vous en proposer deux parmi les plus populaires auprès des développeurs... et des auteurs de cet ouvrage qui n’utilisent pas le même. Cependant, quel que soit votre IDE, il est important de s’assurer de certains points : se conformer aux normes de codage de Drupal ; utiliser la coloration syntaxique ; reconnaître les fichiers Drupal comme des fichiers PHP ; veiller à ce que les espaces soient bien utilisés au lieu des tabulations ; vérifier l’encodage des fichiers (par défaut Unix).


Le codage est important pour Drupal et les critères à connaître sont les suivants : nombre d’espaces avant le tiret : 2 ; espace de tabulation : 2 ; marge de droite : 80 ; retrait initial : 0. À NOTER Standards de programmation de Drupal https://drupal.org/coding-standards

Eclipse PDT (PHP Development Tools) Eclipse est un IDE maintenu par la fondation Eclipse et utilisé par de nombreux langages de programmation. Il peut être enrichi de plug-ins et de packages. La version PDT est dédiée à PHP. http://www.eclipse.org/pdt/

Une fois Eclipse PDT téléchargé, il faut le configurer pour le rendre compatible avec Drupal. Cette opération est nécessaire pour lui permettre d’interpréter tous les fichiers propres au CMS, qui ont des extensions *.module, *.install, *.theme, etc.

Figure 1–21 Configurer Eclipse


ALLER PLUS LOIN Configuration de l’IDE Eclipse PDT https://www.drupal.org/project/eclipse

Netbeans Netbeans est un IDE très populaire car ouvert à tous les langages de programmation grâce à des plug-ins dédiés. Nous pouvons le télécharger en choisissant la version HTML5 & PHP. http://netbeans.org/downloads/index.html

Nous allons également le configurer pour le rendre compatible avec Drupal. Pour ce faire, nous devons vérifier si le plug-in PHP est bien présent en nous rendant dans les préférences à partir de menu Tools>Options.

Figure 1–22 Plug-in PHP

Ensuite, dans l’onglet Miscellaneous, nous configurons les extensions utilisées par Drupal.


Figure 1–23 Configuration de Netbeans

Pour ajouter une nouvelle extension, nous devons effectuer les opérations suivantes : cliquer sur le bouton New ; saisir le module ; valider ; choisir dans la liste déroulante Associated File_Type (MIME) : PHP Files . Il est ensuite indispensable de répéter la même opération pour les autres extensions propres au CMS : install ; theme ; make ; tpl .

Les outils L’installation d’outils de développement supplémentaires n’est pas forcément nécessaire dès le lancement de votre projet, mais elle reste très importante pour le finaliser sereinement. C’est pourquoi il est important de les avoir à portée de mains dès le début, pour nous aider à paramétrer le CMS plus aisément et prendre de bonnes habitudes.

GIT Tout d’abord, nous utilisons un gestionnaire de versions décentralisé, ce qui permet de : travailler en équipe plus facilement ;


gérer des sauvegardes ; revenir en arrière en cas de problème ; etc. Il existe différents types de gestionnaires de versions reconnus comme : CVS : gestion sous un modèle centralisé (http://cvs.nongnu.org/) ; SVN : gestion sur le mode client-serveur (https://subversion.apache.org/) ; GIT : gestion décentralisée (http://git-scm.com). Nous choisirons d’utiliser GIT pour suivre les orientations de Drupal, qui remplace de plus en plus la gestion de versions d’origine CVS. Installons GIT pour pouvoir l’utiliser en interaction avec Drupal et ainsi gérer aisément les différentes versions de notre code source. http://git-scm.com/downloads

Pour installer GIT, il est préférable de nous rendre sur le site officiel et de télécharger la dernière version correspondant à notre système d’exploitation. Une fois GIT téléchargé et installé, nous pouvons cloner Drupal pour le déployer sur nos différents environnements de développement. Installer Drupal avec GIT $ git clone http://git.drupal.org/project/drupal.git

Figure 1–24 Installer Drupal avec GIT $ cd drupalgit $ git checkout 7.34

Figure 1–25 Checkout sur la dernière version


Une fois la version 7.34 de Drupal activée, il ne nous reste plus qu’à l’installer (voir la partie installation de ce chapitre). Que faire une fois GIT installé ? Voici quelques-unes de ses fonctionnalités les plus populaires. Tableau 1–6 Principales fonctionnalités de GIT Fonctions

Ligne de commande

git init

initialiser un nouveau dépôt

git add

ajouter un nouveau fichier à l’index du projet pour qu’il soit pris en compte dans la gestion des versions

git commit

valider les modifications

git pull

télécharger les nouveautés depuis le serveur

git push

envoyer nos modifications sur le serveur

git status

connaître toutes les modifications qui n’ont pas encore été validées

git branch

créer une nouvelle branche de développement

git merge

fusionner plusieurs branches de développement

git revert

annuler des modifications et revenir à une certaine version

git diff

voir ce qui a changé sur un fichier depuis une certaine version

git fetch

importer les modifications à partir d’un dépôt distant

Drush Drush est un outil, considéré comme un couteau suisse, qui permet d’automatiser Drupal à travers des lignes de commandes dans un terminal. Son but est de nous éviter d’utiliser l’interface du CMS, et donc de gagner du temps. Installation L’installation de l’outil Drush est légèrement différente suivant les systèmes d’exploitation. Nous chercherons quant à nous à l’installer en version paquet sous Linux Ubuntu. Pour ce faire, nous ouvrons un terminal et nous tapons les lignes de commandes suivantes : $ sudo apt-get install php-pear $ pear channel-discover pear.drush.org $ pear install drush/drush

Ces trois lignes installent tout d’abord l’extension PEAR de PHP et ensuite le paquet Drush. Il est toujours possible de vérifier si Drush est installé sur notre serveur, avec la


commande suivante : $ drush version

Le résultat obtenu montre que Drush a bien été installé.

Figure 1–26 Version de Drush installée

Bien entendu, si le système d’exploitation avec lequel vous travaillez est différent de Linux Ubuntu, nous vous conseillons de vous rendre sur l’un des sites proposés ci-après. Tableau 1–7 Versions de Drush suivant les différents systèmes d’exploitation OS

Lien d’installation

Debian/Ubuntu

https://www.drupal.org/node/1248790

CentOS

https://www.drupal.org/node/2009426

OpenSUSE

https://www.drupal.org/node/1437988

Any Linux based Server Out there

https://www.drupal.org/node/2132447

Arch Linux

https://www.drupal.org/node/2152127

Hosting Accounts

https://www.drupal.org/node/1181480

Windows

https://www.drupal.org/node/594744

Windows avec Cygwin

https://www.drupal.org/node/1432756

Windows XP/7/8 avec Git Bash

https://www.drupal.org/node/1843176

Mac

https://www.drupal.org/node/1674222

Mac avec Homebrew

https://www.drupal.org/node/954766

Utilisation Cet outil est compatible avec des centaines de modules Drupal. Il permet par exemple de contrôler les autres modules dont nous avons besoin pour notre projet. Les fonctionnalités les plus utilisées sont les suivantes : installer/désinstaller de nouveaux modules ; activer/désactiver les modules ; vider les caches ; cron ; gérer les utilisateurs ; récupérer/changer les valeurs des variables de configuration ; etc.


Pour utiliser cet outil, les commandes par défaut sont détaillées dans le tableau suivant. Tableau 1–8 Principales commandes de Drush Fonctions

Ligne de commande

Télécharger un module

drush dl [nom_module]

Télécharger plusieurs modules

drush pm-download module1 module2 module3

Installer

drush en -y modulename

Désactiver un module

drush pm-list -type=module --status=enabled

Vider le cache

drush cc

Mettre à jour Drupal et les modules

drush up

Installons et activons les modules suivants : $ drush dl ctools pathauto token wysiwyg $ drush en-y ctools pathauto token wysiwyg

Ces modules sont : ctools : suite API et outils ; pathauto : crée automatiquement des URL personnalisées par page (nécessite le module token) ; token : jeton utilisé dans différents modules ; wysiwyg : affiche une barre de mise en forme des contenus.

Devel Le module Devel est une autre boîte à outils indispensable pour développer, que nous vous proposons d’installer et d’activer. Nous avons le choix entre une installation via l’interface web ou via la ligne de commande avec Drush. MÉTHODE Installer le module via l’interface web Télécharger le module suivant : https://www.drupal.org/project/devel Décompresser les archives dans votre dossier /sites/all/modules. Aller à la page module de votre site (Admin/Modules). Trouver le module ci-dessus dans la liste.

MÉTHODE Installer le module en ligne de commande avec Drush $ drush dl devel $ drush en -y devel


Les paramètres de configuration de Devel se trouvent dans Administration>Configuration>Développement>Paramètres de Devel. Définissons les options de Devel que nous voulons utiliser parmi celles disponibles.

Figure 1–27 Réglages de Devel - Partie 1

On peut voir ici que Devel est utile pour effectuer de nombreuses actions. Il affiche les requêtes SQL générées par Drupal, ce qui est très utile lorsque nous n’arrivons pas à afficher ce que nous voulons sur notre page, ou que notre site rencontre des problèmes de performance. Il peut activer XHPROF, ou du moins le pont entre Drupal et ce débogueur PHP. L’URL de l’API conduit à la documentation des fonctions de Drupal. Les options suivantes montrent différentes choses, en fonction de ce que nous cherchons à faire : problème de performance : Chronomètre de page et Utilisation mémoire ; problème de redirection : Afficher la page de renvoi ; une fonction qui n’affiche pas ce qu’elle devrait ou ne reçoit pas les bons paramètres : $page ; une page qui s’affiche vide ou avec un message « Accès refusé » : le nom système des permissions nous permet de déterminer d’où vient le problème. La deuxième partie des réglages permet de choisir le mode et la forme d’affichage des messages de débogage.


Figure 1–28 Réglages de Devel - Partie 2

Lors du débogage, nous utilisons le mode Standard Drupal + Krumo backtrace above the rendered page pour obtenir le plus d’informations possible sur ce qui se passe. La reconstruction systématique du thème à chaque changement de page est très utile pendant la phase de développement du thème Drupal. La décompression de jQuery aide à déboguer plus facilement nos scripts JavaScript lorsque nous en développons de nouveaux. L’activation des fonctions de débogage de Devel est très gourmande en ressources. Cet outil ne doit donc pas être utilisé en production, mais uniquement sur nos machines de développement.

DevelThemer Pour nous aider à travailler sur notre thème et savoir à coup sûr quels gabarits (templates) sont appelés - et à quel moment -, nous pouvons installer le module Theme developper (DevelThemer). MÉTHODE Installer le module par l’interface Télécharger le module suivant : https://drupal.org/project/devel_themer Décompresser les archives dans votre dossier /sites/all/modules . Aller à la page module de votre site (Admin/Modules). Trouver le module ci-dessus dans la liste.

MÉTHODE Installer le module en ligne de commande à l’aide de Drush


$ drush dl devel_themer $ drush en -y devel_themer

Une fois le module installé et activé, nous aurons pour chaque page une fenêtre supplémentaire.

Figure 1–29 Activation de l’affichage des informations liées au thème

En cochant la case, une fenêtre d’information apparaît, qui permet en cliquant sur une zone de la page d’obtenir des informations sur les gabarits utilisés et ceux qui pourraient l’être.

Figure 1–30 Bloc DevelThemer pour voir les gabarits utilisés et utilisables

Nous avons donc installé et configuré la plupart des outils facilitant notre travail de développement avec Drupal.


Les concepts fondamentaux dans Drupal

2

Le CMS Drupal utilise de nombreux termes techniques qu’il est nécessaire de connaître avant d’en profiter pleinement. Ce chapitre explique les fondamentaux de Drupal. Ainsi, les termes employés dans l’ouvrage seront plus simples à appréhender.

SOMMAIRE Comprendre le noeud Comprendre les entités Comprendre les champs Comprendre le Hook


Nœud (Node) Qu’est-ce qu’un nœud ? Un nœud est une pièce d’information, c’est-à-dire du texte et/ou des images qui apparaissent de façon structurée sur une page web. Il s’agit donc d’un des éléments centraux du CMS, tout site Drupal étant constitué (entre autres) de nœuds. Un nœud possède un type (que l’on appelle souvent un type de contenu) : article, page, discussion, forum, etc. Le fait que chaque nœud soit typé permet notamment d’avoir une architecture différente en fonction des contenus que nous comptons exploiter. On ajoutera par exemple un champ de mots-clés dans le but de classer les articles que l’on ne retrouverait pas sur les pages. Ces bribes d’information organisées définissent le type de nœud.

À quoi cela sert-il ? Les nœuds servent principalement à identifier, à l’aide d’un numéro unique, chaque pièce d’information. Cela permet notamment de récupérer avec certitude le contenu auquel le visiteur veut accéder. Les nœuds peuvent être affichés à différents endroits du site, sur une seule page, sous forme de liste, de liens ou de tableaux de contenu. Ce sont des contenus non liés spécifiquement à une page qui sont enregistrés et affichés en fonction de ce que demande le visiteur.

Exemple Nous allons créer un site pour stocker les menus des restaurants que nous connaissons déjà et qui laissera les visiteurs donner leur avis et proposer de nouveaux établissements. Pour ce faire, chaque restaurant aura une fiche, c’est-à-dire un nœud. Ces nœuds auront des caractéristiques communes puisqu’il s’agira du même type de contenu. On pourra alors afficher sur la page d’accueil, en plein écran, un nœud au hasard. Nous pourrons également afficher les cinq derniers restaurants ajoutés, avec uniquement leur titre et quelques informations supplémentaires.

Entité (entity) Qu’est-ce qu’une entité ? Drupal est composé de différentes sortes d’objets appelés entités : des types de contenus (articles, pages, forums), des utilisateurs, des commentaires, des taxonomies, etc. Ces entités sont le fondement de l’architecture de Drupal, un peu comme le sont les différentes pièces de votre maison ou de votre appartement.


Pour ceux qui connaissent le développement orienté objet, une entité est ce qui se rapproche le plus d’une classe. Pour les autres, il s’agit d’un objet ayant des caractéristiques spécifiques pouvant être étendues si nécessaire. Pour prendre une image, il s’agit d’une sorte de boîte, avec des cases déjà préremplies, qui nous permet de ranger différents types de données.

À quoi cela sert-il ? Les entités ont l’immense avantage de posséder des caractéristiques communes et une manière bien spécifique de les créer. Pour reprendre notre image, la dimension et la couleur des boîtes peuvent en effet être prédéfinies. Il ne nous reste donc plus qu’à les remplir... Ces outils évitent aux développeurs les nombreux problèmes rencontrés avec les versions précédentes de Drupal, un peu trop permissives sur certains points et qui laissaient chaque développeur organiser ses données, sans réel ordre. Cela entraînait une augmentation quasi systématique de la complexité, surtout si l’on utilisait de nombreux modules contrib. Modules contrib Un module est une pièce de l’architecture Drupal, une fonctionnalité que l’on ajoute. Il peut être mis gratuitement à disposition par la communauté sur le site drupal.org (modules contrib, pour « contribution ») ou non.

Drupal 7 gère plus finement les entités, notamment en permettant de modifier avec la même procédure celles qui existent déjà, ce qui simplifie grandement la maintenance et la compréhension du code.

Exemple Pour reprendre l’exemple précédent d’un site présentant les menus des restaurants, nous pourrions créer une entité - plutôt que de créer un type de contenu - qui nous « débarrasserait » des informations ne nous intéressant pas directement, comme la date de publication ou les champs de description. Nous privilégierions ainsi les champs plus précis décrivant les menus des différents restaurants.

Champ (field) Qu’est-ce qu’un champ ? Nous pouvons retrouver cette notion de champ au sein des nœuds ou des entités. En effet, elle est centrale puisqu’il s’agit de la plus petite unité d’information existante dans Drupal. Les nœuds et entités possèdent donc différents champs contenant eux-mêmes une information. Le champ peut à la fois être ce qui va s’afficher dans le formulaire de saisie, son stockage en base de données et les moyens de l’afficher.


À quoi peut-il être rattaché ? Un champ peut être rattaché à tout type d’entité. Plus précisément, il est possible d’ajouter des champs aux entités existantes de Drupal, comme les utilisateurs ou les commentaires, mais également aux entités que l’on aura créées. Cela va nous permettre d’organiser nos informations comme on le souhaite, avec des champs complètement personnalisés. Chaque champ correspondra alors à une table spécifique dans la base de données (avec un lien vers l’identifiant numérique de l’entité correspondant dans la table).

Exemple Pour notre site sur les menus des restaurants, nous considérons que les utilisateurs ont des chances d’être intéressés par des établissements situés dans des villes précises. Nous ajoutons donc un champ à l’entité utilisateur correspondant à la ville dans laquelle il habite. Nous complétons également l’entité menu avec un champ ville correspondant à la ville dans laquelle on doit se rendre pour déguster les plats proposés.

Hook Qu’est-ce qu’un hook ? Dans Drupal, on parle régulièrement de hook. Ce terme désigne l’extension des fonctionnalités proposées nativement par le CMS. Le cœur de Drupal est en effet composé de plusieurs fonctions informatiques ; le fait d’ajouter un hook équivaut à modifier une de ces fonctions ou à en ajouter une. Les modules existants de Drupal sont donc en fait des hooks puisque chacun étend un morceau du cœur de Drupal. Le chef d’orchestre (le routeur) du cœur de Drupal est conçu pour lire ces hooks et savoir précisément comment les interpréter et à quel moment précis, pour peu que les hooks respectent les bonnes pratiques de codage de Drupal. Si l’on prend une analogie dans le monde automobile, nous pourrions parler d’une voiture qui a besoin pour rouler d’un moteur, de roues et de seulement quelques pièces. Les hooks correspondent à l’ensemble des options que nous ajoutons sur cette voiture (fenêtre, carrosserie métallisée, ABS, etc.).

Comment et où écrire des hooks ? Les hooks sont directement gérés dans les modules. Par principe, pour garder une compatibilité avec les versions supérieures de Drupal, nous n’allons pas modifier directement les fichiers du cœur du CMS, mais plutôt lui ajouter des modules dédiés. Le troisième chapitre est dédié à la création de modules, mais ce que nous pouvons déjà retenir est que le code personnalisé se retrouvera dans le sous-répertoire sites de notre installation Drupal. Il s’agit d’ailleurs du répertoire qui va contenir l’ensemble des


éléments spécifiques à nos sites.

Exemple Nous souhaitons que le menu (informatique) principal du site pointe vers la liste de l’ensemble de nos menus (gastronomiques). Pour créer un lien de menu, nous devrons utiliser la fonction hook_menu (hook étant à remplacer par le nom de notre module), ce qui donnera : function bookdev_menusgastronomiques_menu() { $items['menusgastronomiques'] = array( 'page_callback' => 'menusgastronomiques_view', ); }

Nous devrons donc créer un item (ou entrée, ou lien) de menu nommé ici menusgastronomiques et appelant la fonction menusgastronomiques_view, que l’on devra définir dans le module. Pour chaque hook, le nom du module vient se placer avant le nom de la fonction que l’on souhaite étendre, ici la fonction menu, que l’on préfixe avec le nom du module et un signe souligné (_) : bookdev_menusgastronomiques_menu().


Les modules

3

Drupal propose des milliers de modules additionnels, développés par la communauté, qui améliorent les fonctionnalités natives du CMS. Si toutefois ils ne répondent pas à vos besoins, nous verrons dans ce chapitre comment réaliser vos propres modules.

SOMMAIRE Création d’un module Les bonnes pratiques Cas pratiques


Qu’est-ce qu’un module ? Les modules servent à ajouter des fonctionnalités supplémentaires à Drupal. Ils sont tellement nombreux qu’ils couvrent quasiment tous les besoins standards du Web. Les modules contrib, c’est-à-dire ceux qui sont mis à disposition de tous par la communauté, sont référencés sur la plate-forme drupal.org. http://www.drupal.org/project

Drupal propose par défaut une arborescence de dossiers et sous-dossiers. Un emplacement nous est réservé dans le dossier sites/, où nous trouvons deux sous-dossiers : all contient les modules, thèmes et bibliothèques pour l’intégralité des sites (car une seule installation Drupal peut être utilisée pour plusieurs sites) : libraries : bibliothèques externes utiles, comme les éditeurs WYSIWYG ; modules : modules contrib ou développés par vous ; themes. default contient notamment la configuration et les fichiers du site principal (celui que nous utiliserons). Les autres dossiers sont réservés à l’équipe Core de Drupal, ce qui garantit que les mises à jour du CMS ne « casseront » pas votre site.

Figure 3–1 Composition des dossiers

L’API des modules


Pourquoi une API ? Une API sert à étendre les fonctionnalités déjà disponibles dans un logiciel pour répondre à certaines contraintes métier ou spécifiques. On répond ainsi à des besoins qui ne sont pas couverts par les modules téléchargeables du CMS. Cela peut également servir simplement pour définir des comportements précis lors d’une action donnée. Les fonctionnalités des modules que nous pouvons utiliser se trouvent sur le site de l’API de Drupal. https://api.drupal.org/api/drupal

Arborescence L’arborescence d’un site Drupal 7 est divisée en deux grandes parties : d’un côté l’installation de base (Drupal Core) et de l’autre les dossiers de votre site (modules et thèmes éventuellement personnalisés). Le Core de Drupal est lui-même composé de modules qui se trouvent dans le dossier du même nom, à la racine de votre site. Les modules supplémentaires seront quant à eux installés dans sites/all/modules.

Composition Les modules Drupal sont tous construits de la même façon et sont composés de deux fichiers principaux : .info, qui fournit le nom du module et la version de Drupal avec laquelle il est compatible ; .module, qui contient le code spécifique du module.

Les bonnes pratiques à respecter Fichier <monmodule>.info Le nom <monmodule> doit être identique à celui du dossier dans lequel il est placé. Tableau 3–1 Composition du fichier <monmodule>.info Variable

Valeur

name

Nom du module affiché dans l’interface de Drupal

description

Descriptif du module que l’on voit dans la page de liste des modules

package

Positionne le module par rapport à son utilisation (visible dans la page Modules).


core

Version de Drupal compatible avec ce module

dependencies[]

Modules associés nécessaires (= dépendances)

files[]

Tous les fichiers de ce module, sauf <monmodule>.module et <monmodule>.install

configure

Chemin vers la page de configuration du module

version

Numéro de version du module

Un exemple de fichier <monmodule>.info name = Mon module description = Bonne pratique de mon module package = BookDev core = 7.x dependencies[] = user files[] = monmodule.test ;configure = version = "7.x-1.0"

Fichier <monmodule>.module Le fichier <monmodule>.module est composé de différents hooks, tous recensés dans l’API Drupal. https://api.drupal.org/api/drupal/includes!module.inc/group/hooks/7

Notez également que le hook est précédé du nom du module. Exemple de fichier <monmodule>.module <?php /** * Implementation hook_page_alter() */ function monmodule_page_alter($page) { // votre code } /** * Implementation hook_help() */ function monmodule_help($path, $arg) { // votre code } /** * Implementation hook_block_info() */ function monmodule_block_info() { // votre code


} ...

?>

Notre exemple détaille la déclaration de trois hooks différents : l’aide, le bloc et la page. Autres fichiers Avec Drupal, nous pouvons également déclarer d’autres fichiers, contenant les fonctionnalités métier dont nous avons besoin. Toutes les extensions doivent être préfixées avec le même nom de module. Tableau 3–2 Liste des extensions disponibles Extensions

Description

inc

Autres fonctions sauf les hooks Drupal

css

CSS

js

Fonctions JavaScript

install

Fichier d’installation (utile pour la mise à jour de la base de données)

test

Tests unitaires

admin.inc

Code des pages d’administration du module

theme.inc

Fonctions du thème

Exemple : un module à la carte Description Notre objectif est ici d’étendre le module Trigger intégré nativement dans le Core de Drupal. Trigger est un déclencheur d’actions qui permet d’exécuter des fonctionnalités supplémentaires sans avoir recours à PHP (voir le chapitre 6 pour plus de détails). Il répond aux actions spécifiques d’un événement et sert par exemple à ajouter de nouvelles fonctionnalités dans la partie administration (back office) de notre site Drupal : prévenir un validateur d’un nouveau contenu avant sa publication ; afficher un message de bienvenue lors de l’identification d’un utilisateur ; modifier un ou plusieurs nœud(s) ; etc. En d’autres termes, Trigger permet d’effectuer des actions lorsque des événements se produisent. Ces actions se traduisent par des fonctions PHP que nous développons et qui se déclencheront pour les utilisateurs, la taxonomie, un nœud, etc. Les actions consisteront par exemple à envoyer un e-mail lors de la création d’un nouvel utilisateur ou à afficher des informations supplémentaires lors de l’utilisation d’une


taxonomie.

Fichier .info : menu_for_all.info Le fichier identifiant notre module se nomme menu_for_all.info. Contenu du fichier menu_for_all.info name = Menu pour tous description = Action supplémentaire pour le type de contenu 'Menu pour tous' package = Ouvrage Drupal Avancé dependencies[] = trigger version = "7.x-1.x-dev" core = "7.x" project = "Ouvrage Drupal Avancé" datestamp = "1322093758"

Pour utiliser notre module correctement, nous spécifions ici une dépendance à Trigger : de cette façon, si nous n’activons pas ce dernier, le CMS le fera à notre place.

Fichier .module : menu_for_all.module Intéressons-nous aux différentes fonctions que nous allons coder dans les prochaines lignes. Hook_help() L e hook_help affiche une aide sur l’utilisation du module. Pour activer ce dernier et accéder à l’aide, il faut se rendre à la page Admin>Modules de Drupal.

Figure 3–2 Activation du module et accès à l’aide

Contenu de hook_help() function menu_for_all_help($path, $arg) { switch ($path) { case 'admin/help#menu_for_all': $output = '<h3>A propos du module : Menu for all</h3>'; $output .= '<p>Exemple de module pour le livre : Drupal Avancé aux éditions Eyrolles</p>'; return $output; } }


Lorsque nous cliquons sur le bouton Aide, nous arrivons à la page d’information du module et nous obtenons le résultat suivant.

Figure 3–3 Page d’information du module Menu_for_all

Hook_action_info() La configuration du déclencheur s’effectue via le module Trigger que nous avons pris soin d’activer précédemment. Ceci permet à l’administrateur du site d’activer une fonctionnalité supplémentaire dans le but d’exécuter une opération tierce. Contenu de hook_action_info() function menu_for_all_action_info() { return array( 'menu_for_all_basic_action' => array( 'label' => t('Garder une trace dans le journal'), 'type' => 'system', 'configurable' => FALSE, 'triggers' => array('any'), ), 'menu_for_all_unblock_user_action' => array( 'label' => t('Débloquer une action utilisateur'), 'type' => 'user', 'configurable' => FALSE, 'triggers' => array('any'), ), 'menu_for_all_node_sticky_action' => array( 'type' => 'node', 'label' => t('Garder une trace des informations venant de la page d\'accueil'), 'configurable' => TRUE, 'behavior' => array('changes_property'), 'triggers' => array('node_presave', 'node_insert', 'node_update'), ), ); }

Hook_menu() Le hook_menu est important car il fournit une entrée de menu et indique précisément ce que le module fait.


Contenu de hook_menu() function menu_for_all_menu() { $items['examples/menu_for_all'] = array( 'title' => 'Menu pour tous', 'description' => 'Page d\'information', 'page callback' => '_menu_for_all_page', 'access callback' => TRUE, ); return $items; }

Actions du module Après avoir défini les entrées, nous devons désormais programmer les fonctions associées. hook_basic_action() Cette fonction exécute deux opérations : un message signale l’insertion de la saisie dans le journal et la ligne est effectivement ajoutée dans celui-ci. Enfin, pour utiliser cette action supplémentaire, nous devons l’activer via le déclencheur. Contenu de hook_basic_action() function menu_for_all_basic_action(&$entity,$context=array()) { drupal_set_message(t('Ajout dans le journal')); watchdog('menu_for_all', 'Ajout dans le journal'); }

hook_unblock_user_action() Cette action vérifie s’il s’agit d’un contenu ou d’une entité objet utilisateur. Si nous sommes bien dans l’un de ces deux cas, le déclencheur exécutera l’action, qui consiste à enregistrer l’opération dans le journal. Contenu de hook_unblock_user_action() function menu_for_all_unblock_user_action(&$entity,$context = array()) { // si c'est une entité if (isset($entity->uid)) { $uid = $entity->uid; } // si c'est un contenu elseif (isset($context['uid'])) { $uid = $context['uid']; } // sinon bloquer l'utiliseur else {


$uid = $GLOBALS['user']->uid; } $account = user_load($uid); $account = user_save($account, array('status' => 1)); watchdog('menu_for_all', 'Débloquer utilisateur %name.', array('%name' => $account->name)); drupal_set_message( 'Débloquer utilisateur %name ', array('%name' => $account->name)); }

hook_node_sticky_action() Cette fonction est une action spéciale qui va enregistrer l’utilisateur par rapport au contenu affiché en page d’accueil. hook_node_stick_action() function menu_for_all_node_sticky_action($node, $context) { // Récupère les informations utilisateur $account = user_load_by_name($context['author']); // Vérifie si le créateur du noeud est l'utilisateur connecté if ($account->uid == $node->uid) { $node->promote = NODE_PROMOTED; $node->sticky = NODE_STICKY; watchdog('action', '@type %title noeud activé par %username.', array('@type' => node_type_get_name($node), '%title' => $node->title, '%username' => $account->name)); drupal_set_message('@type %title noeud activé par utilisateur %username.', array('@type' => node_type_get_name($node), '%title' => $node->title, '%username' => $account->name)); } }

Mise en place du module Le module Menu_for_all propose de gérer nos propres fonctionnalités. Installation Nous devons tout d’abord activer notre module, ainsi que le module Trigger si cela n’est pas déjà fait. Bien entendu, il sera automatiquement activé puisque le module Trigger est une dépendance.


Configuration Le module peut être configuré Admin>Structure>Déclencheurs).

par

le

déclencheur

(menu

Figure 3–4 Configuration du déclencheur

Les onglets affichés sur cet écran nous montrent les différents points abordés dans les lignes précédentes. Exécution Lorsque nous associons une action à un nœud, un contexte ou un utilisateur, cette dernière se déclenche automatiquement lors de la réalisation d’un événement associé.

Conclusion Bien entendu, nous pouvons réaliser plusieurs fonctions à la suite pour les faire évoluer séparément.


Créer un type de contenu en programmant

4

Découvrons dans ce chapitre comment fonctionnent les types de contenu (ajout d’un nouveau type de contenu et de différents champs). Nous expliquerons ensuite comment programmer une entité et lui ajouter des champs. Puis nous verrons comment utiliser le module Features pour faciliter la centralisation et le déploiement de nos configurations.

SOMMAIRE Champs et entités : les fondamentaux Features : intérêt, création, utilisation, modification Taxonomie : création, gestion, utilisation


Un nouveau type de contenu avec l’interface d’administration Reprenons notre exemple du site de menus de restaurants pour expliquer ce qu’est un type de contenu et comment cela fonctionne. Nous créons donc un nouveau type, appelé Restaurant, afin que les utilisateurs de notre site puissent ajouter les fiches des menus. Il nous faudra élaborer un contenu de ce type par restaurant. Pour savoir ce qui existe déjà, rendons-nous dans Structure>Types de contenu.

Figure 4–1 Liste des types de contenus

Par défaut, nous avons donc deux types de contenus : les articles et les pages basiques. Nous n’allons pas détailler leurs différences (nous pouvons les chercher par nous-mêmes, ce qui nous rendra un peu plus à l’aise avec les options), mais nous allons plutôt ajouter un nouveau type de contenu.

Ajouter un type de contenu sans programmer Il suffit de cliquer sur le lien + Ajouter un type de contenu, qui nous conduira sur un formulaire.


Figure 4–2 Formulaire d’ajout d’un type de contenu

La première partie du formulaire nous demande un nom, qui apparaîtra à la fois dans l’interface d’administration du site et aux utilisateurs qui auront les droits suffisants pour ajouter ce type de contenu. Lorsque nous entrons un nom dans ce champ, nous voyons apparaître Nom systeme : <le mot que nous tapons en minuscules> et un lien Modifier. Le nom système est unique. C’est lui que Drupal utilisera en interne pour interagir avec ce type de contenu. Nous pouvons le modifier si nous le souhaitons. La description demandée ensuite sert à donner des informations sur notre type de contenu et apparaîtra dans l’interface d’administration et dans celle qui sert à l’utilisateur pour choisir le type de contenu qu’il souhaite ajouter. Nous retrouvons, à la fin de cette première partie, des onglets correspondant aux différentes options de notre type de contenu.

Figure 4–3 Bouton d’enregistrement

Ces options ayant déjà des choix prédéfinis, cliquons directement sur le bouton Enregistrer et ajouter les champs.

Figure 4–4 Bouton Enregistrer et ajouter les champs

Ce bouton passe directement à l’étape suivante : ajouter des champs spécifiques à notre type de contenu. Nous allons d’abord détailler les options disponibles pour le type de contenu, puis nous reviendrons sur l’ajout de champs. Après enregistrement, nous revenons donc à la liste des types de contenus. Pour accéder de nouveau aux options, cliquons sur le lien modifier de la ligne correspondant à notre type.


Figure 4–5 Liste des champs par défaut

Le premier onglet concerne les Paramètres du formulaire de contribution. Le premier champ demandé est le titre - personnalisable -, les contenus de type restaurant étant identifiés de manière unique par ce biais. La seconde option donne la possibilité au rédacteur de voir son travail avant de l’enregistrer, pour le relire ou pour se rendre compte de la présentation de son travail. Le dernier champ, Explication ou directives pour la contribution, donne des informations supplémentaires à nos rédacteurs, par exemple le ton global à utiliser (exemple : « Veuillez ne décrire que des faits, et non des interprétations » ou bien « Seuls les champs avec des astérisques sont obligatoires. Toutefois, n’hésitez pas à renseigner le maximum d’informations. »)

Figure 4–6 Paramètres du formulaire de contribution

Le second onglet, Options de publication, propose de choisir l’emplacement des publications (par exemple, sur la page d’accueil du site) et de décider si le contenu sera publié par défaut (c’est-à-dire visible de tous) ou non (il sera alors visible uniquement de


son auteur et des éventuels modérateurs auxquels nous aurions donné les droits). L’option Épinglé en haut des listes sert à mettre un contenu en avant. Nous avons également la possibilité de Créer une nouvelle révision, c’est-à-dire de conserver les différentes versions d’un contenu, comme pour une page Wiki. Le deuxième champ spécifie si notre contenu doit être traduit dans plusieurs langues.

Figure 4–7 Options de publication

Le troisième onglet, Paramètres d’affichage, définit si le nom du rédacteur et la date de publication doivent être affichés systématiquement (par défaut sous le titre du contenu, même si notre thème peut décider de les afficher ailleurs).

Figure 4–8 Paramètres d’affichage

Le quatrième onglet, Paramètres des commentaires, demande si l’ajout de commentaires sur le type de contenu doit être autorisé. Si c’est le cas, il faut choisir l’option Ouvert dans la première liste déroulante. D’autres options permettent de les cacher, de les afficher de manière indentée, de gérer le nombre de commentaires par page, ou d’autoriser les internautes à ajouter un titre aux commentaires. Il est par la même occasion possible d’afficher le formulaire de commentaire sur la même page que le contenu et d’obliger les internautes à avoir un aperçu de leur commentaire avant de le soumettre.


ATTENTION Commentaires indésirables Il faut rester prudent avec les commentaires autorisés par défaut sous les articles. De nombreux robots peuvent en effet ajouter automatiquement des commentaires qui contiennent de la publicité vers des sites exotiques (vers des produits pharmaceutiques ou des sites pornographiques).

Pour nous prémunir contre les commentaires indésirables, mais sans aller jusqu’à la modération systématique avant publication, nous conseillons d’utiliser le module Honeypot, qui a l’immense avantage de ne pas être visible par les utilisateurs, contrairement aux nombreux modules de Captcha, qui demandent à l’utilisateur de saisir une information supplémentaire.

Figure 4–9 Paramètres des commentaires

MÉTHODE Installer le module Honeypot via l’interface de Drupal Télécharger le module : https://drupal.org/project/honeypot Décompresser l’archive dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver le module Honeypot dans la liste et cocher la case pour l’activer. Cliquer sur Enregistrer la configuration en bas de page.

MÉTHODE Installer le module Honeypot en ligne de commande avec Drush $ drush dl honeypot $ drush en -y honeypot

L’onglet Paramètres du menu sert à gérer les menus (informatiques) dans lesquels les contenus de type Restaurant pourront être ajoutés. Par défaut, le seul endroit dans lequel un contenu de ce type peut être directement ajouté manuellement est le menu principal.


Cependant, nous pouvons souhaiter que les rédacteurs n’entrent le contenu de manière manuelle que dans un menu spécifique que nous avons créé à cet usage. Nous pouvons également spécifier un élément parent par défaut. Tous les contenus de type Plat que nous allons créer pourront alors être des sous-menus de l’item de menu Restaurant. Cela permet de créer automatiquement des menus enfants qui sont des sousmenus de l'item choisi.

Figure 4–10 Paramètres du menu

Une fois toutes les options définies, nous pouvons cliquer sur Enregistrer le type de contenu. ATTENTION Ce sont des options par défaut. Si notre rédacteur a les droits suffisants, il sera possible de redéfinir chacune d’entre elles pour chaque contenu créé.

Ajouter des champs à notre type de contenu Retournons à notre liste de types de contenu via le menu Structure>Types de contenu et cliquons sur le lien Gérer les champs.


Figure 4–11 Paramètres du menu

Les mêmes onglets que lors de la modification du type de contenu apparaissent. Cela facilite le passage d’une partie à l’autre de la configuration d’un type de contenu. Nous retrouvons donc deux champs que nous avons paramétrés lors de la création du type de contenu : title et body. Nous remarquons que seul ce dernier peut être modifié ou supprimé. Comme nous l’avons déjà évoqué, le champ de titre étant obligatoire pour un type de contenu, nous ne pourrons pas le supprimer. Cette liste affiche différentes informations en dehors de l’Étiquette (qui est le nom commun de notre champ, celui qui s’affichera pour nos rédacteurs, voire pour nos visiteurs) et du Nom système (utilisé en interne par Drupal). Nous retrouvons trois autres colonnes. Le Type de champ définit ce que contiendra notre champ. L e Widget est la manière dont pourra être saisi le contenu de notre champ (des widgets différents seront donc disponibles en fonction du type de champ choisi). La colonne Actions sert à modifier ou supprimer nos champs. Deux liens sont proposés : Ajouter un nouveau champ pour créer un champ inexistant ; Ajouter un champ existant pour récupérer un champ déjà créé pour un autre type de contenu. Si nous créons par exemple un champ Régions, nous allons l’utiliser dans notre type Restaurant, mais aussi probablement dans notre type Ville, afin de préciser dans quelle région se trouve notre ville. Enrichissons donc notre type de contenu Restaurant avec différents champs. Ajoutons dans un premier temps un champ Régions qui sera composé d’une liste des régions. Puis cliquons sur Ajouter un nouveau champ.


Figure 4–12 Ajouter un nouveau champ

Nous avons choisi comme type de champ une liste de texte, Liste (texte), car notre liste des régions étant déjà déterminée, il n’est pas utile de laisser aux rédacteurs la possibilité de les saisir eux-mêmes (cela présente également l’avantage de ne pas avoir des orthographes différentes pour désigner un même lieu). Pour le widget, nous avons choisi une Liste de sélection car il aurait fallu trop de boutons radio. Une fois ces choix effectués et l’étiquette de notre champ renseignée (ici, nous avons choisi Régions), il faut cliquer sur Enregistrer pour arriver sur la page de paramétrage détaillé du champ.

Figure 4–13 Paramètres du champ

Le seul paramètre à renseigner est la liste des choix autorisés. Une fois ceux-ci entrés, cliquons sur Enregistrer les paramètres du champ. Nous sommes alors redirigés vers une deuxième page de paramétrage.


Figure 4–14 Configuration d’un champ

Il est possible de modifier l’étiquette, rendre le champ obligatoire, renseigner un texte d’aide (à destination de nos rédacteurs), préciser une valeur par défaut, dire si le champ prend une ou plusieurs valeur(s) et modifier la liste des valeurs autorisées. Une fois que nous sommes satisfaits de nos réglages, n’oublions pas de cliquer sur Enregistrer les paramètres. Cette fois-ci, nous revenons à la liste des champs. Ajoutons un deuxième champ pour que nos rédacteurs puissent attribuer un nombre d’étoiles aux restaurants. Pour cela, nous utilisons de nouveau Ajouter un nouveau champ, en sélectionnant cette fois-ci un champ de type Entier et le seul widget disponible pour ce type de champ : Champ texte. Drupal nous informe alors que pour ce type de champ il n’existe pas de paramètres à personnaliser et nous conduit sur la page de modification du champ.

Figure 4–15 Configuration d’un champ Nombre


Nous pouvons cette fois-ci renseigner un minimum, un maximum, un préfixe et/ou un suffixe pour notre entier. Pour chaque type de champ, des paramètres différents sont disponibles. Offrons à nos rédacteurs la possibilité d’illustrer leur propos avec des images du restaurant qu'ils critiquent. Pour cela, nous insérons un champ de type Image, avec pour étiquette Photo, dont la figure suivante indique les paramètres spécifiques. Les images sont stockées par défaut sur le serveur web où est installé Drupal. Cependant, nous pouvons choisir une destination différente pour le transfert à condition d’avoir au préalable spécifié cette option dans Configuration>Système de fichiers. Nous pouvons également sélectionner une image par défaut pour notre champ.

Figure 4–16 Configuration d’un champ Image

Figure 4–17 Paramètres du champ Image

Les paramètres pour les images sont les suivants. Extensions de fichier autorisées spécifie les formats des fichiers images acceptés par notre site. Répertoire du fichier précise un répertoire spécifique à ce type de contenu.


Résolution maximale de l’image et Résolution minimum de l’image définissent la qualité des photos acceptées par notre site. Taille maximale de transfert concerne le poids d’une image. Nous limiterons à 1 Mo cette taille maximale, afin d’éviter que des photos trop lourdes ne remplissent très vite l’espace disque disponible sur notre serveur. Il est fortement conseillé de cocher la case Activer le champ Alt. Les internautes qui ne peuvent pas afficher les images (pour cause de mauvais débit, par exemple) apprécieront de lire à leur place des textes décrivant celles-ci. Cet aspect est une règle d’accessibilité basique du Web. Il est également recommandé de cocher l’option Activer le champ Titre pour que nos rédacteurs donnent un titre à chacune de leurs photos, avec pour consignes éventuelles de préciser le lieu de la photo, son auteur et la date de la prise de vue. Aperçu du style d’image : c’est l’image qui s’affichera lorsqu’un rédacteur créera ou modifiera un contenu. Nous laissons thumbnail par défaut pour que notre rédacteur ait un aperçu de son image. Il faut en revanche qu’elle ne soit pas trop volumineuse pour que les performances web restent acceptables. Champs de type Texte Enfin, nous créons un champ Description de type Texte long, dans lequel nos rédacteurs donneront une description du restaurant. Le champ de type Texte est destiné à contenir des textes très courts, des tweets par exemple. Un champ de type Texte long permet au contraire de rentrer plusieurs lignes de texte. Le champ de type Texte long et résumé donne en plus la possibilité de saisir quelques lignes qui résument le texte long (pour afficher sur une page d’accueil, par exemple, ou dans un flux RSS). Ce champ n’a pas de paramètre. Après avoir cliqué sur Enregistrer les paramètres du champ, nous arriverons donc sur l’écran ci-après.

Figure 4–18 Paramètre du champ Texte

Nous pouvons spécifier ici le nombre de lignes que nous souhaitons afficher par défaut dans le champ de saisie et si nous souhaitons que le texte soit mis en forme (voir la partie sur les formats de textes). Nous n’avons pas parlé du type de champ Référence à un terme. Nous reviendrons dessus un peu plus loin dans ce chapitre, dans la section qui aborde la taxonomie.


Fields et entité Après avoir vu comment ajouter un type de contenu avec notre souris, nous allons apprendre à créer une entité avec du code. Nous allons définir une entité de type Menus, que nous déclinerons à travers deux bundles : Diner et Gouter. La création par le code présente plusieurs avantages : il est possible de réutiliser les entités créées sur différents sites et de les « versionner », donc de conserver aisément un historique de leurs évolutions. Nous gérons également beaucoup plus finement les champs que nous souhaitons rattacher à notre entité, sans être obligé de garder l’ensemble des champs disponibles et obligatoires dans un type de contenu. Il faut avoir quelques notions de langage PHP pour pouvoir comprendre ce qu’on écrit avec l’API Drupal. Création du type d’entité Menus Pour cela, nous allons écrire un module que nous appellerons menus. Nous allons commencer par définir la table de la base de données dans le fichier menus.install, que nous plaçons dans le répertoire sites/all/modules/custom/menus créé pour contenir notre module. menus_schema() function menus_schema() { /* On commence par définir la table avec le $schema['menus'] */ $schema['menus'] = array( /* On définit les colonnes de la table avec les champs */ /* de notre type d'entité */ 'fields' => array( /* Un champ id unique */ 'eid' => array( 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE ), /* Un champ type pour définir de quel menu il s'agit */ 'type' => array( 'description' => 'Le type de menu', 'type' => 'text', 'size' => 'medium', 'not null' => TRUE ), /* Un champ nom pour pouvoir nommer notre menu */ /* (quelle que soit son espèce) */ 'nom' => array( 'type' => 'text', 'size' => 'medium' ) ), /* On définit la clé primaire de la table */ 'primary key' => array('eid') ); return $schema;


}

Une fois la table définie, nous créons le fichier menus.module. Dans ce fichier, nous définissons les informations de notre entité en utilisant menus_entity_info. menus_entity_info() function menus_entity_info() { $entity['menus'] = array( // On définit l'étiquette du type d'entité 'label' => t('Menus'), 'base table' => 'menus', 'uri callback' => 'menus_uri', // Le type d'entité contient des champs 'fieldable' => TRUE, // On définit les clés liées à l'entité 'entity keys' => array( // L'identifiant utilisé par entity_load 'id' => 'eid', // La clé utilisée par field_attach pour charger les champs associés 'bundle' => 'type' ), // La clé pour les bundles 'bundle keys' => array('bundle' => 'type'), 'bundles' => array() ); // Emplacement pour les définitions des bundles Diner et Gouter return $entity; };

Nous avons donc créé notre entité en déclarant ces informations : son nom Menus, la possibilité d’avoir des champs et le nom de ses bundles (type). Voyons maintenant ce que sont ces bundles et à quoi ils servent. Partons sur l’idée que notre type d’entité Menus contient plusieurs déclinaisons qui vont constituer nos bundles. Nous créons donc un bundle Diner et un bundle Gouter. Ces deux menus partagent des caractéristiques et donc des champs communs (comme un nom). Cependant, un Diner possède une entrée + plat + dessert, alors qu’un Gouter ne contient que le goûter et nous aurons donc besoin de deux champs distincts pour récupérer cette information. Ainsi, la table de la base menus contiendra les informations communes au dîner et au goûter, et chacun des bundles contiendra des informations spécifiques. Commençons avec le bundle Diner. Bundle Diner dans menus_entity_info() // Bundle Diner $entity['menus']['bundles']['diner'] = array( 'label' => t('Diner'), // On définit les éléments pour l'administration // de ce type de menu


'admin' => array( // Le chemin interne d'accès aux pages // d'administration 'path' => 'admin/menus/%menus_type', // Le chemin d'administration affiché aux // utilisateurs 'real path' => 'admin/menus/diner', // L'argument %menus_types doit être passé 'bundle argument' => 2, // On ajoute la permission, ici on utilisera // Administrer les nœuds 'access arguments' => array('administer nodes') ) );

Avec ces quelques lignes, nous avons donc défini les informations nécessaires à la création d’un bundle. Continuons avec Gouter. Bundle Gouter dans menus_entity_info() // Bundle Gouter $entity['menus']['bundles']['gouter'] = array( 'label' => t('Gouter'), 'admin' => array( 'path' => 'admin/menus/%menus_type', 'real path' => 'admin/menus/gouter', 'bundle argument' => 2, 'access arguments' => array((administer nodes') ) );

Pour résumer, notre fichier menus.module contient donc maintenant la fonction menus_entity_info (hook entity_info) qui définit notre type d’entité (Menus) et nos deux bundles (Diner et Gouter). menus_entity_info() function menus_entity_info() { $entity['menus'] = array( // On définit l'étiquette du type d'entité 'label' => t('Menus'), // La table définie dans le menus.install 'base table' => 'menus', 'uri callback' => 'menus_uri', // Le type d'entité contient des champs 'fieldable' => TRUE, // On définit les clés liées à l'entité 'entity keys' => array( // L'identifiant utilisé par entity_load 'id' => 'eid', // La clé utilisée par field_attach pour charger les champs associés 'bundle' => 'type' ), // La clé pour les bundles


'bundle keys' => array('bundle' => 'type'), 'bundles' => array() ) ; // Diner bundle $entity['menus']['bundles']['diner'] = array( 'label' => t('Diner'), // On définit les éléments pour l'administration de ce type de menu 'admin' => array( // Le chemin interne d'accès aux pages d'administration 'path' => 'admin/menus/%menus_type', // Le chemin d'administration affiché aux utilisateurs 'real path' => 'admin/menus/diner', // L'argument %menus_types doit être passé 'bundle argument' => 2, // On ajoute la permission, ici on utilisera Administrer les nœuds 'access arguments' => array('administer nodes') ) ); // Gouter bundle entity['menus']['bundles']['gouter'] = array( 'label' => t('Gouter'), 'admin' => array( 'path' => 'admin/menus/%menus_type', 'real path' => 'admin/menus/gouter', 'bundle argument' => 2, 'access arguments' => array((administer nodes') ) ); return $entity; };

Nous allons également ajouter dans ce fichier une fonction menus_uri qui doit appeler une entité de type Menus. menus_uri() function menus_uri($menus) { return array('path' => 'menus/' .$menus->mid ); }

Notre entité est maintenant créée avec ses deux bundles. Cela sera très utile, mais nous n’avons pas pour l’instant d’interface d’administration pour la modifier sans passer par le code. Ajouter une interface d’administration Pour faciliter la maintenance de notre site, nous souhaitons ajouter des champs à notre entité sans passer par le code, mais par l’interface d’administration de Drupal. Pour cela, nous apportons au CMS les éléments nécessaires, c’est-à-dire créer les liens des nouveaux menus avec une fonction hook_menu. Toutes les fonctions suivantes sont à ajouter au fichier menus.module.


menus_menu() function menus_menu() { $items['admin/menus'] = array( 'title' => 'admin menus', 'access arguments' => array('access content'), 'page callback' => 'menus_admin', 'file' => 'menus.pages.inc', 'type' => MENU_NORMAL_ITEM ); // On définit un accès à l'API et l'UI de champ // pour chacun de nos bundles items['admin/menus/%menus_type'] = array( 'title callback' => 'menus_type_title', 'title arguments' => array(2), 'access arguments' => array('access content'), 'page arguments' => array(2) ); // On définit le lien pour ajouter une entité de type Menu $items['admin/menus/%menus_type/add'] = array( 'title' => 'add' ; 'access arguments' => array('access content'), 'type' => MENU_DEFAULT_LOCAL_TASK ) ; }

Nous avons donc ajouté les liens des nouveaux menus et développons maintenant les fonctions qui y sont appelées. Expliquons d’abord le %menus_type qui apparaît dans les URL : il s’agit d’une fonction qui va récupérer les informations du bundle concerné via menus_type_load. Chaque bundle a son propre %menus_type, qui est utilisé comme argument dans l’URL. Ici nous allons donc créer la fonction menus_type_load, chargée de vérifier que nous utilisons bien un type d’entité existant. menus_type_load() /** * Chargement de l'argument pour %menus_type * Vérification de ce qui est passé comme argument * pour éviter une injection **/ function menus_type_load($menus_type) { switch ($menus_type) { case 'diner' : case 'gouter' : return $menus_type ; default : return FALSE ; } }

Nous écrivons ensuite les fonctions appelées par page callback dans le menus_menu.


Commençons par menus_type_title. menus_type_title() /** * On retourne le type de l'objet **/ function menus_type_title($menus_type) { return $menus_type ; }

Définissons maintenant le contenu des pages d’administration. Comme indiqué dans menus_menu à la ligne 'page callback', créons un nouveau fichier nommé menus.pages.inc. Commençons par définir le comportement de la page d’administration globale de notre type d’entité Menus. Nous décidons que, lors de l’arrivée sur cette page, si un type de bundle est présent dans l’URL, nous serons alors redirigés vers le formulaire d’ajout du bundle en question. Le cas échéant, contentons-nous de lister les bundles existants. menus_admin() /** Sur la page d'administration de l'entité Menus, on listera les bundles de ce type d'entités. Lorsque l'on cliquera sur l'un des bundles, on sera redirigé sur la page permettant d'administrer les champs et leur affichage. **/ function menus_admin($type = NULL){ if ($type) { return drupal_get_form('menus_addmenu', $type); } else{ // Pour simplifier, on code en dur la liste des bundles $row = array(); $row[] = array(l(t('Diner'), 'admin/menus/diner')); $row[] = array(l(t('Gouter'), 'admin/menus/gouter')); $header = array('Type'); $content = array( '#theme' => 'table', // On affiche un tableau '#header' => $header, // On complète les en-têtes '#rows' => $rows, // Et on ajoute les deux lignes du dessus ); return $content ; } };

Créons à présent la fonction qui générera le formulaire d’ajout de notre entité. menus_addmenu() /** Ici, via le générateur de formulaire, on ajoute une entité de type Menus en fonction du bundle sélectionné. **/ function menus_addmenu($form, &$form_state, $type) { // On ajoute le champ Nom de notre entité Menus


$form['nom'] = array( '#type' => 'textfield', '#title' => 'nom' ); // On crée une classe de style Drupal $menus = new stdClass(); $menus->type = $type; // On définit l’objet Menus $form['menus'] = array( '#type' => 'value', '#value' => $menus ); // On définit le type de bundle afin de passer // la validation du formulaire. $form['type'] = array( '#type' => 'value', '#value' => $type ); // On fournit les champs attachés au formulaire field_attach_form('menus', $menus, $form, $form_state); // On ajoute les actions du formulaire $form['actions'] = array('#type' => 'actions'); $form['actions']['add'] = array( '#type' => 'submit', '#value' => 'add' ); return $form; };

Écrivons ensuite la fonction de validation, dont le rôle est de déclencher la vérification que les champs sont conformes à ce qui est attendu. menus_validate() function menus_addmenu_validate($form, &$form_state) { entity_form_field_validate('menus', $form, $form_state); };

Il nous reste à développer la fonction d’envoi du formulaire pour que les informations renseignées soient enregistrées. menus_addmenu_submit() function menus_addmenu_submit($form, &$form_state) { $menus = $form_state['values']['menus']; $menus->nom = $form_state['values']['nom']; // On enregistre les informations dans la table menus drupal_write_record('menus', $menus); // On injecte les données à l'objet avec les paramètres // du formulaire entity_form_submit_build_entity('menus', $menus, $form, $form_state);


// On récupère les champs d'autres éventuels modules field_attach_submit('menus', $menus, $form, $form_state); // On ajoute les données dans la BDD field_attach_insert('menus', $menus); // On affiche un message de confirmation de l'ajout drupal_set_message( t('Nouveau @type a été ajouté', array('@type' => $menus->type)) ) };

Nous avons donc maintenant une belle interface d’administration, en plus de la possibilité pour nos rédacteurs d’ajouter des Diner ou des Gouter. Toutefois, il ne faudrait pas oublier une chose importante : rien ne permet pour l’instant à nos visiteurs de voir les entités ainsi créées. Afficher l’entité Pour cela, nous avons besoin d’ajouter les deux onglets Voir et Modifier dans la fonction menus_menu de notre fichier menus.module. Ajout des onglets Voir et Modifier dans menus.module $items['menus/%menus'] = array( 'title callback' => 'menus_title', 'title arguments' => array(1), 'page callback' => 'menus_display_one', 'page arguments' => array(1), 'access arguments' => array('access content'), 'file' => 'menus.pages.inc', 'type' => MENU_CALLBACK ); // L'onglet Voir $items['menus/%menus/view'] = array( 'title' => 'view', 'access arguments' => array('access content'), 'weight' => -3, 'type' => MENU_DEFAULT_LOCAL_TASK ); // L'onglet Modifier $items['menus/%menus/edit'] = array( 'title' => 'edit', 'page callback' => 'drupal_get_form', 'page arguments' => array('menus_edit', 1), 'access arguments' => array('access content'), 'file' => 'menus.pages.inc', 'type' => MENU_LOCAL_TASK );

Ensuite, comme pour l’administration, nous avons besoin d’écrire les fonctions que nous appelons à travers les items de menus créés. Ces fonctions sont à ajouter dans le fichier menus.pages.inc. Commençons par le chargement d’une entité de type Menus avec un menus_load.


menus_load() function menus_load($mid) { // On utilise la fonction entity_load qui va retrouver // l’entité avec son identifiant unique et le nom // de la table. $menus = entity_load('menus', array($mid)); return $menus[$mid]; };

Nous récupérons le nom du menu avec la fonction menus_title. menus_title() function menus_title($menus) { return $menus->nom; };

Nous continuons avec menus_display_one pour afficher une entité Menus. menus_display_one() function menus_display_one($menu){ // On récupère l'objet Menus chargé par entity_load $content[] = array( '#markup' => 1($menu->nom, 'menus/' . $menu->mid ) ); // On attache également les champs supplémentaires $content[] = field_attach_view('menus', $menu, 'full') ; return $content ; }

Nos entités de type Menus s’affichent maintenant dans l’onglet Voir. Il nous reste à traiter l’onglet Modifier. Il ressemble beaucoup au précédent. menus_edit() function menus_edit($form, &$form_state, $menu) { // On affiche le nom du menu $form['name'] = array( '#type' => 'texfield', '#title' => 'name', '#default_value' => $menu->nom ); $form['menus'] = array( '#type' => 'value', '#value' => $menu->type ); // On affiche aussi les formulaires des champs attachés field_attach_form('menus', $menu, $form, $form_state ) ; // On sauvegarde les modifications $form['actions'] = array('#type' => 'actions) ; // On ajoute le bouton de sauvegarde $form['actions']['save'] = array(


'#type ' => 'submit', '#value' => 'save' ); // On gère la suppression $form['actions']['delete'] = array( '#type' => 'submit', '#value' => 'delete', '#submit' => array('menus_edit_delete') ); return $form ; }

Ajoutons la validation, comme pour l’ajout. menus_edit_validate() function menus_edit_validate($form, &$form_state) { entity_form_field_validate('menus', $form, $form_state) ; }

Il nous reste à développer la fonction d’envoi. menus_edit_submit() function menus_edit_submit($form, &$form_state) { $menu = $form_state['values']['menus'] ; $menu->nom = check_plain($form_state['values']['nom']); drupal_write_record('menus', $menu, array('mid')); entity_form_submit_build_entity('menus', $menu, $form, $form_state) ; field_attach_submit('menus, $menu, $form, $form_state) ; field_attach_update('menus', $menu) ; drupal_set_message( t('Le @type a été sauvegardé', array('@type' => $menu->type) ) ); // On redirige vers l'affichage de l'entité $form_state['redirect'] = 'menus/' . $menu->mid ; }

Nous pouvons donc maintenant modifier nos entités. Le dernier point sera la suppression d’une entité avec la fonction menus_edit_delete. menus_edit_delete() /** * Gestion de la suppression d'un menu **/ function menus_edit_delete($form_ &$form_state) { $menu = $form_state['values']['menus']; // On supprime les informations des champs attachés field_attach_delete('menus', $menu) ; // On supprime ensuite le menu en lui-même


db_delete('menus') ->condition('bip', $menu->mid) ->execute() ; $form_state['redirect'] = 'menus' ; }

Nous avons à présent un type d’entité et deux bundles opérationnels, que nous pouvons utiliser pour afficher, ajouter, modifier, supprimer des entités, pour lesquelles nous avons également la possibilité d’ajouter et de gérer les champs via l’interface d’administration.

Features Commençons par l’installation et la création de notre premier code Features, puis nous verrons comment le réutiliser sur un autre site et enfin comment le modifier.

À la découverte de Features Features est un module de Drupal qui sert à générer automatiquement du code. La configuration définie depuis l’interface d’administration de Drupal est stockée en base de données. Cela implique que, si par exemple nous voulons transférer des modifications d’un environnement de développement vers un site en production, nous nous retrouvons dans l’obligation de réimporter la base de données du site de production, d’y recopier nos modifications et de renvoyer la base sur le site de production. Ce processus, qui peut fonctionner dans certains cas (avec un seul auteur sur le site qui en est aussi l’administrateur), est bien souvent fragile et nécessite beaucoup de rigueur pour éviter ce qu’un webmaster redoute le plus : perdre des données (articles, commentaires publiés pendant le temps des manipulations, etc.). Features va nous affranchir de ces contraintes, en externalisant toute la configuration et en l’enregistrant sous forme de code. Nous avons vu que nous pouvions créer un type de contenu dans l’interface, mais aussi dans le code. C’est ce que Features va réaliser pour nous. MÉTHODE Installer le module Features par l’interface Télécharger le module : https://drupal.org/project/features Décompresser l’archive dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver le module Features dans la liste et cocher la case pour l’activer. Cliquer sur Enregistrer la configuration en bas de page.

MÉTHODE Installer le module Features en ligne de commande avec Drush $ drush dl features $ drush en -y features


Une fois le module téléchargé et activé, nous trouvons une nouvelle entrée dans le menu d’administration : Structure>Features. Cliquons dessus.

Figure 4–19 Menu Features

Nous arrivons alors sur une page indiquant qu’aucun code Features n’existe et encourageant à en créer ou en importer un.

Figure 4–20 Features - Page de gestion

Nous allons donc créer un code Features pour mettre en package notre type de contenu Restaurant. Pour cela, nous cliquons sur Create Features ; nous arrivons sur une page comprenant trois parties. La première, General Informations, contient les informations décrivant notre code Features.


Figure 4–21 Features - Informations générales sur le code

La seconde partie concerne les options avancées, comme l’adresse de stockage (en ligne) du code Features, le répertoire où il va être créé, etc. (nous laissons ici les options par défaut). La dernière partie traite des composantes qui vont être intégrées, c’est-à-dire les options de configuration que Features doit transformer en code. Nous choisissons ici ce qui concerne notre type de contenu Restaurant.

Figure 4–22 Features - Options avancées


Figure 4–23 Features - Composantes

Nous avons sélectionné le type de contenu pour récupérer les réglages relatifs à celui-ci et les champs qui lui sont associés : fields bases (définition générique d’un champ) et fields instances (utilisation d’un champ pour un type de contenu précis). Une fois ces sélections effectuées, nous téléchargeons le code Features, que nous récupérons sous forme de dossier compressé au format tar. Nous extrayons ensuite notre dossier dans le répertoire /sites/all/modules, puisque tous les codes Features sont des sortes particulières de modules. Notre répertoire contient alors les fichiers suivants.

Figure 4–24 Arborescence d’un code Features

Retournons dans l’interface d’administration Admin>Structure>Features. Notre code est apparu dans la liste.


Figure 4–25 Liste des codes Features

Nous pouvons alors l’activer comme un module (pour l’instant, cela ne changera pas grand-chose sur le site puisque le type de contenu Restaurant et ses champs existent déjà sur notre site de test).

Déploiement d’un code Features et modification Pour aller plus loin, utilisons notre code Features sur notre site de production. Comme pour l’installation d’un module, l’archive tar est décompressée dans le répertoire /sites/all/modules de notre site de production, où nous aurons au préalable bien évidemment téléchargé et activé le module Features. Puis rendons-nous dans Admin>Structure>Features. Une fois sur la liste, activons notre code en cochant la case et en cliquant sur Enregistrer les paramètres.

Figure 4–26 Activation de notre Features

L’activation a pour effet de créer sur notre site de production le type de contenu et les champs que nous avons intégrés dans notre code Features. Nous voyons que l’état est Par défaut. Features va comparer les réglages écrits dans le code que nous venons d’ajouter avec ceux enregistrés dans la base de données du site. Voyons maintenant comment cela se passe si nous retournons sur le site de développement : nous modifions le type de contenu (nous ajoutons une description et désactivons l’aperçu) et constatons le changement dans Admin>Structure>Features.


Figure 4–27 État supplanté

L’état indique maintenant Supplanté, c’est-à-dire que les réglages enregistrés dans le code ne sont plus identiques à ceux qui se trouvent en base de données. Cliquons sur le lien Supplanté. Nous voyons ici la liste des composants de notre code Features ; c’est bien le type de contenu qui est Supplanté. Comme il s’agit de notre site de développement, nous allons donc demander à Features de recréer le code en enregistrant les modifications. Pour ce faire, utilisons l’onglet Recreate.

Figure 4–28 Détails des composants de notre code Features


Figure 4–29 Réenregistrer un code Features

Nous revenons sur la page de création avec la possibilité d’ajouter de nouveaux éléments. Nous nous contentons de cliquer sur Download feature. Nous décompressons ensuite le dossier tar dans le site de production (toujours dans le répertoire sites/all/modules) en remplacement des fichiers existants. Retournons sur notre site de production ; nous constatons que notre code est alors Supplanté.

Figure 4–30 Choix des éléments du Revert

Cette fois-ci, demandons à Features d’appliquer la configuration du code vers la base de données. Cochons donc la case devant les éléments à remplacer et cliquons sur Revert components. Nous obtenons alors un message nous indiquant que nos modifications ont bien été appliquées.

Figure 4–31 Remplacement effectué

Nous constatons que le composant Types de contenu est revenu à l’état Par défaut. Le module Features est très largement utilisé par les distributions Drupal existantes (Open Atrium, Commons et bien d’autres), mais aussi par les équipes de développement Drupal qui souhaitent gagner du temps lors du lancement de leurs projets avec la mise en place rapide de certaines fonctionnalités demandées systématiquement (comme l’éditeur WYSIWYG non inclus par défaut, ou la possibilité de gérer une galerie d’images).


Si nous sommes familiers des outils comme GIT ou SVN, cela nous permet également de gérer en versions la configuration de notre site et ainsi de revenir plus facilement en arrière.

Voir les différences avec Diff Pour aller un peu plus loin avec Features, nous pouvons ajouter une fonctionnalité très pratique qui montre en ligne les différences entre la configuration dans le code Features et celle stockée en base de données. MÉTHODE Installer le module Diff par l’interface Télécharger le module : https://drupal.org/project/diff Décompresser l’archive dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver le module Diff dans la liste et cocher la case pour l’activer. Cliquer sur Enregistrer la configuration en bas de page.

MÉTHODE Installer le module Diff en ligne de commande avec Drush $ drush dl diff $ drush en -y diff

Une fois ce module activé, retournons sur notre code remplacé Admin>Structure>Features ; nous voyons un onglet supplémentaire apparaître.

via

Figure 4–32 Diff sur notre code Features remplacé

Cet onglet Review overrides montre, à gauche, la configuration stockée dans le code Features et, à droite, celle stockée en base de données. Nous pouvons ainsi voir précisément ce qui a été modifié.

La taxonomie Ajouter une taxonomie avec l’interface d’administration


Nous souhaitons ajouter un système de classement sur nos restaurants, afin de trouver rapidement des restaurants de différents types : brasserie, gastronomique, asiatique, fastfood... Pour cela, Drupal met à notre disposition un système de taxonomie pour définir différents vocabulaires. Un vocabulaire est ici vu comme une forme de classification et nous pouvons en créer autant que nous le souhaitons. Créer son premier vocabulaire Pour créer notre premier vocabulaire, nous utilisons le menu Administration>Structure>Taxonomie. Nous accédons alors à la liste des vocabulaires existants.

Figure 4–33 Liste des vocabulaires existants

Un vocabulaire d’exemple existe déjà, appelé Étiquettes. Il fonctionne comme un système de mots-clés sur les articles en saisie libre. Cliquons sur Ajouter un vocabulaire.

Figure 4–34 Ajouter un vocabulaire

Peu d’éléments sont ici à renseigner : un nom, qui doit être unique et obligatoire ; une description, pour définir plus précisément ce que contient ce vocabulaire. Et voici notre vocabulaire lié aux restaurants.


Figure 4–35 Notre vocabulaire Type de restaurant

Notre taxonomie existe donc, mais il nous reste deux étapes avant de pouvoir l’utiliser. D’abord, il faut lui ajouter des termes ; puisque nous souhaitons que notre taxonomie soit un système de classification, les rédacteurs de fiches de restaurants ne pourront donc pas ajouter librement des termes à notre vocabulaire. La seconde étape consiste à donner la possibilité d’utiliser cette taxonomie lors de l’ajout ou de la modification d’une fiche restaurant. Ajouter des termes à notre vocabulaire Nous restons sur la page de nos vocabulaires, accessible via Admin>Structure>Taxonomie. Cliquons sur le lien ajouter des termes de la ligne Type de restaurant.

Figure 4–36 Insertion d’un terme de vocabulaire

Le formulaire nous demande plusieurs éléments : Nom : le terme de taxonomie tel qu’il apparaîtra pour nos rédacteurs ; Description : pour préciser le terme et éventuellement le distinguer d’un autre qui aurait un nom proche ; Alias d’URL : pour retrouver tous les contenus associés à ce terme, directement à


partir d’une URL précise. Si nous descendons dans le formulaire, une autre rubrique apparaît (dépliée sur notre figure) : Relations.

Figure 4–37 Relations entre les termes

Cette rubrique sert à créer une hiérarchie parmi les termes de taxonomie. Nous pouvons donc décrire un arbre de termes de vocabulaire avec plusieurs niveaux à l’intérieur. Il suffit pour cela de sélectionner le terme parent de celui que nous sommes en train de créer. Une fois que nous avons rempli au moins le Nom et la Description (rien ne nous empêche de renseigner le reste), nous cliquons sur Enregistrer. Drupal nous ramène alors sur le formulaire de création vide pour nous permettre d’ajouter un autre terme.

Figure 4–38 Terme enregistré + nouveau formulaire d’ajout

Après avoir ajouté nos quatre termes, il nous reste à indiquer à Drupal que ce vocabulaire peut être utilisé sur notre type de contenu Restaurant. Utiliser un vocabulaire dans un type de contenu Pour utiliser notre vocabulaire Type de restaurant dans notre type de contenu Restaurant, rendons-nous dans la gestion des champs de ce dernier


(Admin>Structure>Types de contenu, puis cliquer sur Gérer les champs de la ligne Restaurant).

Figure 4–39 Ajout d’un champ Référence à un terme

Nous choisissons alors les paramètres suivants dans Ajouter un nouveau champ : étiquette : Type de restaurant ; type de champ : Référence à un terme ; widget : Cases à cocher/boutons radio. Puis nous enregistrons nos modifications. Dans les Paramètres du champ, Drupal nous demande de choisir le vocabulaire : indiquons-lui Type de restaurant.

Figure 4–40 Paramètre d’un champ : référence à un terme

Nous arrivons alors sur les paramètres détaillés du champ.


Figure 4–41 Paramètre détaillé d’un champ référence à un terme

Nous pouvons y définir plusieurs choses : la case Champ requis, à cocher si le champ doit obligatoirement être renseigné ; le texte d’aide pour les rédacteurs ; la valeur par défaut de notre champ ; le nombre de valeurs autorisées ; le vocabulaire utilisé. Pour vérifier que nous pouvons bien utiliser notre vocabulaire, nous ajoutons une nouvelle fiche Restaurant ; nous y retrouvons bien notre champ avec les termes que nous avons définis.

Figure 4–42 Ajout d’un restaurant avec le champ référence à un terme

Nous avons donc toutes les cartes en mains pour ajouter un système de classifications sur notre site.

Gérer les taxonomies par le code Nous pouvons également définir des taxonomies, ainsi que les termes et champs associés, directement par du code. Nous ajoutons donc une taxonomie Lieu à notre entité Menus. Pour cela, nous allons utiliser le module créé précédemment et ajouter certains éléments. Créer un vocabulaire depuis un module Utilisons le fichier menus.install de notre module Menus. Commençons par déclarer le vocabulaire dans la fonction (que nous ajoutons pour l’occasion) menus_install. menus_install() function menus_install() { // On déclare les paramètres du vocabulaire $nouveau_vocabulaire = (object) array( 'name' => 'Lieu', 'description' => 'Les lieux où nos menus peuvent être mangés',


'machine_name' => 'menus_lieu' ); // On crée le vocabulaire taxonomy_vocabulary_save($nouveau_vocabulaire); }

Nous avons donc déclaré notre vocabulaire Lieu et utilisé la fonction de création d’une taxonomie pour qu’il soit enregistré en base de données lors de l’installation de notre module. Déclarer des termes Continuons d’ajouter du code dans notre fichier menus.install, en déclarant quelques termes dans la fonction principale. Déclaration des termes du vocabulaire // On charge le vocabulaire par son nom système pour ajouter // des termes. $vocab = taxonomy_vocabulary_machine_name_load('menus_lieu'); // On crée un tableau avec les termes à ajouter $terms = array( 'à table', 'en pique-nique', 'à l\'apéro', 'sur le pouce', ); // On ajoute les termes au vocabulaire depuis le tableau foreach ($terms as $term){ taxonomy_term_save((object) array( 'name' => $term, 'vid' => $vocab->vid, ) ); };

Nous nous appuyons sur les fonctions fournies par le module Taxonomy pour récupérer le vid (l’identifiant unique du vocabulaire), puis nous créons un tableau pour renseigner les termes (seulement leurs noms dans ce cas précis). Nous enregistrons enfin les termes un par un à l’aide d’une boucle. Développer le champ Lieu pour le bundle Diner Nous avons créé notre vocabulaire et ajouté les termes. Il nous reste à ajouter un champ taxonomy_term_reference à une de nos entités. Pour la démonstration, nous utiliserons le bundle Diner que nous avons créé au début du chapitre. Ajoutons donc deux paragraphes à la fonction menus_install. Pour ce faire, commençons par créer notre champ. Création d’un nouveau champ dans menus_install()


// On crée le champ $field = array( 'field_name' => 'field_menus_lieu', 'type' => 'taxonomy_term_reference', 'settings' => array( 'allowed_values' => array( array( 'vocabulary' => 'menus_lieu', // Utiliser le machine_name du vocabulaire 'parent' => 0 ), ), ), ); field_create_field($field);

Déclarons le champ dans un tableau associatif, puis créons-le avec la fonction field_create_field à laquelle nous donnons notre tableau en paramètre. Ensuite, nous instancions le champ pour l’associer à notre entité. Instanciation du champ Lieu dans menus_install() // On attache le champ à l'entité menu $instance = array( 'field_name' => 'field_menus_lieu', 'entity_type' => 'menus', 'label' => 'Lieu', 'bundle' => 'diner', 'required' => true, 'widget' => array( 'type' => 'options_select' ), 'display' => array( 'default' => array('type' => 'hidden'), 'teaser' => array('type' => 'hidden') ) ); field_create_instance($instance);

Nous utilisons un tableau associatif pour déclarer notre instance, puis nous créons cette dernière avec field_create_instance. Installons notre module (il faut le désactiver puis le désinstaller avant de l’activer de nouveau, pour que le hook menus_install soit appelé et que notre taxonomie soit bien créée avec ses termes et son champ). Ajoutons un nouveau Diner ; nous voyons que notre champ taxonomy_term_reference a été ajouté avec notre vocabulaire et les termes associés.


Figure 4–43 Ajout d’un Diner avec le champ Lieu (taxonomy_term_reference)

Permettre la suppression du vocabulaire lors de la désinstallation Il nous reste, pour permettre la désinstallation propre du module, à ajouter une fonction de suppression de notre vocabulaire. Dans notre menus.install, intégrons une fonction menus_uninstall(). menus_uninstall() // On supprime le vocabulaire créé function menus_uninstall() { $vocab_delete = taxonomy_vocabulary_machine_name_load('menus_lieu'); taxonomy_vocabulary_delete($vocab_delete->vid); }

Et voilà ! nous avons ajouté notre taxonomie, des termes et un champ via le code. Nous pouvons désormais imaginer de nombreux usages de classification sur notre site.


L’affichage avancé avec le module Views

5

Ce chapitre va tout d’abord montrer comment utiliser l’interface utilisateur de vue pour ajouter des affichages singuliers sur notre site. Nous verrons ensuite comment créer une vue par le code et la modifier. Enfin, nous ajouterons des options à Views depuis nos modules personnalisés. SOMMAIRE Présentation du module Views : où le trouver, comment l’installer Présentation de l’interface graphique Les éléments qui composent une vue Personnaliser une vue avec le code Ajouter des fonctionnalités à Views


Views : présentation Qu’est ce que Views ? Views est un module Drupal qui sert à créer des affichages dynamiques de contenus au sein des pages d’un site web. Ainsi, nous choisirons précisément quels champs de nos types de contenus nous voulons voir apparaître ou si les menus de notre site doivent s’afficher par exemple sous forme de listes, de tableaux, etc. MÉTHODE Installer le module Views par l’interface Télécharger le module : https://drupal.org/project/views Décompresser l’archive dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver le module Views dans la liste.

Figure 5–1 Dépendance nécessaire pour l’installation de Views Nous ne pouvons pas cocher la case se trouvant devant la ligne Views car il manque un autre module (appelé une dépendance), en l’occurrence ici le module Chaos Tools que nous trouvons à cette adresse : https://drupal.org/project/ctools Télécharger Ctools dans notre dossier /sites/all/modules. Retourner sur la liste de nos modules (admin/modules). Cocher les cases devant les lignes Chaos Tools, Views et Views UI (pour activer également l’interface utilisateur). Cliquer sur Enregistrer la configuration.

MÉTHODE Installer le module Views en ligne de commande avec Drush $ drush dl views ctools $ drush en -y views views_ui ctools


Liste des vues Pour accéder à l’interface d’administration, rendons-nous dans Admin>Structure>Views. Nous arrivons alors sur une page contenant l’ensemble des vues existantes.

Figure 5–2 Liste des vues présentes lors de l’activation du module

Le module est installé avec différentes vues par défaut que nous pouvons visualiser pour en étudier la construction et mieux en comprendre le fonctionnement.

Ajouter une vue pour lister tous les plats Nous allons créer ensemble une vue afin d’afficher les différents menus (gastronomiques) pour le dîner. Cliquons sur Add new view.

Figure 5–3 Ajout d’une nouvelle vue avec l’interface utilisateur

Nous pouvons alors définir différentes options. Donnons un nom pour notre vue : Dîners.


Renseignons son type (avec l’option Afficher, nous pouvons choisir ce qu’affiche notre vue) : contenu de type Repas étiqueté avec dîner. Cochons la case Créer une page (pour avoir une page contenant tous nos dîners) : titre de la page : Tous les dîners ; chemin : tous-les-diners ; format d’affichage : Tableau sur Champ ; éléments à afficher : 10 ; case Utiliser la pagination cochée ; création d’un lien de menu Menu principal, avec pour texte Dîners. Cochons la case Créer un bloc (pour l’afficher sur la page d’accueil) : titre du bloc : Les 5 derniers dîners ajoutés ; format d’affichage : Liste non mise en forme sur titres ; éléments par page : 5. N’oublions pas de cliquer sur Continuer et modifier (pour nous permettre de détailler cet affichage). Nous arrivons alors sur le détail de notre vue. Voyons ensemble les différentes parties qui composent notre vue.

Figure 5–4 Détail de la vue Tous les dîners

Les onglets en haut de la figure 5-4 contiennent les différents types d’affichage que nous avons définis (ici une page et un bloc). Le bloc Titre reprend le nom que nous avons donné à notre vue. Nous pouvons également nommer nos affichages en cliquant sur le nom de l’affichage par défaut (qui sera Page ou Block).


Format indique la mise en page de nos contenus. Nous pouvons également, via le lien Paramètres, ajouter des classes CSS pour chacune des lignes dans le cas d’une liste, ce qui facilite leur identification lors de la mise en forme. Champs détaille les champs affichés dans la vue. Critères de filtrage limite les contenus affichés en fonction de certains filtres. Par exemple ici, nous avons ajouté le filtre Terme de taxonomie dîner pour n’avoir que les menus du soir. Critères de tri modifie l’ordre d’apparition du contenu sur notre page. Par défaut, le contenu le plus récent apparaîtra en premier, mais nous pouvons aussi décider de trier par ordre alphabétique sur les titres. Paramètres de la page définit ce qui est spécifique au type d’affichage Page, comme son chemin (URL), ou si celle-ci doit apparaître dans un menu spécifique. Par ce biais, nous pouvons limiter l’accès à cette page en choisissant un droit spécifique ou un accès dédié pour les membres. En-tête et Pied de page précisent des textes spécifiques à afficher respectivement en haut et en bas de la page. Il arrive fréquemment que nous ayons besoin d’ajouter un texte statique au début ou à la fin d’une liste de contenu dynamique, comme une introduction ou un lien vers une autre page. Pagination détermine le mode de pagination (complet ou mini, avec tous les éléments ou seulement un nombre défini) et permet également de choisir le nombre d’éléments qui doivent s’afficher par page. Par défaut, seul dix éléments sont affichés ; cela convient lorsque nous voulons présenter les dix articles les plus récents sur un blog, mais si nous n’affichons que les titres de nos contenus, nous augmenterons cette pagination à 25 ou à 50 (en fonction de la mise en forme que nous souhaitons pour notre site). Le lien More link permet d’afficher systématiquement un lien ramenant notre visiteur vers une page qui comporte tous les contenus. Lien More link dans un bloc Si nous utilisons un lien More link dans un bloc, il faudra obligatoirement prévoir un affichage de type page dans la même vue. Le mécanisme interne de Views est prévu pour rediriger notre visiteur sur une page de la même vue.

Nous avons ainsi effectué un tour rapide de l’interface standard. Une partie nommée Avancé est disponible dans l’interface, que nous présenterons dans la deuxième partie de ce chapitre.

Fonctionnalités avancées de Views Développons une vue qui contient les plats créés par un internaute. Elle s’affichera sur la page de l’utilisateur et sera visible par tous. Elle devra donc être contextualisée selon que nous sommes sur notre profil ou sur celui d’un autre utilisateur. Cette vue présentera


également la liste des restaurants dans lesquels ces plats sont servis.

Créer une vue bloc Commençons par ajouter une nouvelle vue avec le menu Structure>Vues>Ajouter une nouvelle vue, avec les paramètres suivants : nom de la vue : Les plats de l’utilisateur ; case Créer une page décochée ; case Créer un bloc cochée. Laissons les paramètres par défaut, puis cliquons sur Continuer et modifier. Concentrons-nous uniquement sur les paramètres les plus avancés.

Les paramètres avancés des vues Il suffit d’ouvrir les options de paramètres avancés pour découvrir les différentes possibilités qu’offre le module Views. Filtres contextuels : limiter aux plats d’un utilisateur Le premier filtre contextualise la vue à la page utilisateur que nous consultons actuellement. Pour cela, ajoutons un filtre contextuel et choisissons uid de l’auteur dans la liste Contenu. Ce filtre affiche uniquement les plats qui ont été ajoutés par l’utilisateur et que nous passerons à la vue en tant qu’argument. S’il n’est pas précisé, cet argument est par défaut pris dans l’URL de la vue. Nous choisissons ici : Afficher le contenu de « Aucun résultat trouvé ».

Figure 5–5 Configuration d’un filtre contextuel : quel comportement doit avoir la vue lorsque l’argument n’est pas disponible ?

Nous pouvons également fournir des informations supplémentaires si l’argument est présent. Ici, nous choisissons deux options : Supplanter le titre : Les plats de %1 (pour obtenir le nom de l’utilisateur) ; Spécifier le critère de validation :


Validateur : Utilisateur ; Action à mener si la valeur du filtre ne passe pas la validation : Cacher la vue. Pensons bien à appliquer les modifications pour qu’elles soient prises en compte. Nous constatons ensuite dans l’aperçu de la vue qu’aucun plat n’est proposé par défaut. Si nous affichons 1 (en ayant créé des contenus auparavant en tant qu’administrateur de Drupal), les plats que nous avons créés apparaîtront. Relation : ajouter les restaurants et leurs adresses Nous souhaitons ensuite faire apparaître l’adresse des restaurants dans cette vue. Si nous essayons d’ajouter un champ, nous avons bien Contenu : Restaurant, mais nous n’avons aucun accès aux champs du type de contenu Restaurant. Pour cela, nous devons créer une relation vers l’entité Contenu référencée via le champ field_restaurant. Il s’agit d’obtenir les informations des restaurants qui servent ce plat. Nous laissons l’identifiant par défaut et nous n’exigeons pas la relation (si nous cochons la case Exiger la relation, les contenus Plats qui n’ont pas de restaurants référencés n’apparaîtront plus dans notre vue). Une fois la relation définie, nous pouvons insérer un champ et nous obtiendrons bien Contenu : Adresse. Dans les paramètres du champ, nous utilisons la relation créée précédemment Entité Contenu référencée par field_restaurant.

Figure 5–6 Paramètres de la relation : contenu/restaurant


Figure 5–7 Paramètres du champ Adresse et sa relation field_restaurant

Si nous rentrons l’argument 1 dans les paramètres de l’aperçu, nous trouvons effectivement le nom des plats créés, le nom des restaurants associés à ce plat et les adresses de ces restaurants.

Figure 5–8 Aperçu du bloc : les plats de l’utilisateur

N’oublions pas d’enregistrer notre vue, avant de changer de page.

Écrire une vue dans un module Pour réutiliser nos vues ou simplement les préparer sans passer par l’interface d’administration, nous pouvons les coder directement dans des modules. Pour cela, nous créons un module dans lequel nous écrirons la vue sur les repas d’un utilisateur.

Création du module et déclaration de l’utilisation de l’API Views Commençons par créer un module. Le fichier repas.info se présente comme suit : repas.info name = Repas description = "Type de contenu repas, restaurant et les vues associés" package = BookDev version = VERSION core = 7.x

Grâce à ce fichier, Drupal détecte le nouveau module. Dépendances Nous ne précisons pas de dépendances à Views dans le fichier .info, car il n’est pas indispensable au fonctionnement du module. L’idée est que si Views est activé, des vues sont existantes et peuvent donc être directement utilisées.

Ensuite, nous allons créer le fichier repas.module et déclarer l’utilisation de l’API


(Application Programming Interface) de Views. Déclaration de l’API de Views dans repas.module /* * Déclaration de l'utilisation de l'API de Views */ function menus_views_api() { return array( 'api' => 3, 'path' => drupal_get_path('module', 'menus') . '/views', ); }

Dans cette fonction, précisons la version de Views utilisée (la version 3 dans notre cas) et le chemin pour accéder à ses fichiers (ici, nous avons choisi de placer les fichiers liés à Views dans un dossier views situé à la racine du dossier de notre module).

Déclaration de la vue Nous allons maintenant déclarer la vue. Pour y parvenir, créons un fichier appelé repas.views_default.inc qui ne contiendra qu’un seul hook, déclarant les vues présentes par défaut dans le module. repas.views_default.inc /* * Hook views_default_views */ function repas_views_default_views() {

Pour commencer, déclarons une nouvelle vue, en précisant un nom machine, une description, la table de base de données utilisée (correspondant au type de vue), le nom lisible par l’utilisateur, la version du cœur de Drupal utilisée, la version de l’API utlisée et le fait que la vue soit activée. Déclaration de la vue $view = new view(); $view->name = 'les_plats_de_l_utilisateur'; $view->description = ''; $view->tag = 'default'; $view->base_table = 'node'; $view->human_name = 'Les plats de l\'utilisateur'; $view->core = 7; $view->api_version = '3.0'; $view->disabled = FALSE; /* Changer à TRUE pour que la vue par défaut soit initialement désactivée. */

Une fois la vue déclarée, définissons les différents affichages en commençant par celui par défaut, appelé Master.


Affichage et paramètres de base (Master) de la vue /* Display: Master */ $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['title'] = 'Les plats de l\'utilisateur'; $handler->display->display_options['use_more_always'] = FALSE; $handler->display->display_options['use_more_text'] = 'plus'; $handler->display->display_options['access']['type'] = 'perm'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['exposed_form']['type'] = 'basic'; $handler->display->display_options['exposed_form']['options'] ['submit_button'] = 'Appliquer'; $handler->display->display_options['exposed_form']['options'] ['reset_button_label'] = 'Réinitialiser'; $handler->display->display_options['exposed_form']['options'] ['exposed_sorts_label'] = 'Trier par'; $handler->display->display_options['pager']['type'] = 'some'; $handler->display->display_options['pager']['options']['items_per_page'] = '5'; $handler->display->display_options['style_plugin'] = 'default'; $handler->display->display_options['row_plugin'] = 'fields';

Ensuite, nous déclarons la relation vers les restaurants. Relation vers les restaurants /* Relation: Contenu : Restaurant (field_restaurant) */ $handler->display->display_options['relationships']['field_restaurant_nid'] ['id'] = 'field_restaurant_nid'; $handler->display->display_options['relationships']['field_restaurant_nid'] ['table'] = 'field_data_field_restaurant'; $handler->display->display_options['relationships']['field_restaurant_nid'] ['field'] = 'field_restaurant_nid'; $handler->display->display_options['relationships']['field_restaurant_nid'] ['delta'] = '-1';

Nous continuons en déclarant les champs à afficher. Champs à afficher dans la vue /* Champ: Contenu : Titre */ $handler->display->display_options['fields']['title']['id'] = 'title'; $handler->display->display_options['fields']['title']['table'] = 'node'; $handler->display->display_options['fields']['title']['field'] = 'title'; $handler->display->display_options['fields']['title']['label'] = ''; $handler->display->display_options['fields']['title']['alter'] ['word_boundary'] = FALSE; $handler->display->display_options['fields']['title']['alter']['ellipsis'] = FALSE; /* Champ: Contenu : Restaurant */ $handler->display->display_options['fields']['field_restaurant']['id'] = 'field_restaurant';


$handler->display->display_options['fields']['field_restaurant']['table'] = 'field_data_field_restaurant'; $handler->display->display_options['fields']['field_restaurant']['field'] = 'field_restaurant'; /* Champ: Contenu : Adresse */ $handler->display->display_options['fields']['field_adresse']['id'] = 'field_adresse'; $handler->display->display_options['fields']['field_adresse']['table'] = 'field_data_field_adresse'; $handler->display->display_options['fields']['field_adresse']['field'] = 'field_adresse';

Nous continuons avec le critère de tri. Critère de tri /* Critère de tri: Contenu : Date de publication */ $handler->display->display_options['sorts']['created']['id'] = 'created'; $handler->display->display_options['sorts']['created']['table'] = 'node'; $handler->display->display_options['sorts']['created']['field'] = 'created'; $handler->display->display_options['sorts']['created']['order'] = 'DESC';

Ajoutons le filtre contextuel. Ajout du filtre contextuel /* Filtre contextuel: Contenu : uid de l'auteur */ $handler->display->display_options['arguments']['uid']['id'] = 'uid'; $handler->display->display_options['arguments']['uid']['table'] = 'node'; $handler->display->display_options['arguments']['uid']['field'] = 'uid'; $handler->display->display_options['arguments']['uid']['exception'] ['title'] = 'Tout'; $handler->display->display_options['arguments']['uid'] ['default_argument_type'] = 'fixed'; $handler->display->display_options['arguments']['uid']['summary']['format'] = 'default_summary';

Précisons les critères de filtrage. Critères de filtrage /* Critère de filtrage: Contenu : Publié */ $handler->display->display_options['filters']['status']['id'] = 'status'; $handler->display->display_options['filters']['status']['table'] = 'node'; $handler->display->display_options['filters']['status']['field'] = 'status'; $handler->display->display_options['filters']['status']['value'] = 1; $handler->display->display_options['filters']['status']['group'] = 1; $handler->display->display_options['filters']['status']['expose'] ['operator'] = FALSE; /* Critère de filtrage: Contenu : Type */ $handler->display->display_options['filters']['type']['id'] = 'type';


$handler->display->display_options['filters']['type']['table'] = 'node'; $handler->display->display_options['filters']['type']['field'] = 'type'; $handler->display->display_options['filters']['type']['value'] = array( 'plat' => 'plat', );

Une fois l’affichage par défaut défini, nous continuons avec l’affichage Block. Déclaration de l’affichage Block /* Display: Block */ $handler = $view->new_display('block', 'Block', 'block'); $translatables['les_plats_de_l_utilisateur'] = array( t('Master'), t('Les plats de l\'utilisateur'), t('plus'), t('Appliquer'), t('Réinitialiser'), t('Trier par'), t('Asc'), t('Desc'), t('field_restaurant'), t('Restaurant'), t('Adresse'), t('Tout'), t('Block'), );

Nous ajoutons la vue que nous venons de déclarer au tableau des vues : $views[$view->name] = $view;

Ensuite, nous retournons l’ensemble des vues : return $views; }

Une fois le fichier enregistré et le module activé, nous voyons apparaître dans la liste des vues celle que nous venons de créer.

Figure 5–9 Liste des vues : la vue Les plats de l’utilisateur a bien été ajoutée.

Vider le cache de Views Si notre vue n’apparaît pas, il faut cliquer sur le bouton Vider le cache de Views dans les


paramètres des Vues, dans l’onglet Avancé (sur la droite).

Figure 5–10 Paramètres avancés de Views

Ajout de fonctionnalités Nous allons continuer avec Views pour voir comment nous pouvons lui ajouter des fonctionnalités. Pour cela, nous réutiliserons l’entité Menus et lui ajouterons un type de vue qui peut afficher ces fonctionnalités.

Ajout d’un type de vue (hook views_data) Réutilisons notre module Menus créé dans le chapitre précédent. Intégrons les fonctionnalités manquantes pour afficher des vues de type Menus. Ajoutons dans le fichier menus.module la déclaration d’utilisation de l’API de Views. Déclaration de l’API de Views /* * Hook views_api */ function menus_views_api() { return array( 'api' => 3, 'path' => drupal_get_path('module', 'menus') . '/views', ); }

Nous n’apportons pas de changement par rapport à l’ajout de vues. Là aussi, nous ajoutons un dossier views à notre module pour gérer les fichiers liés à Views. Nous créons également un fichier menus.views.inc dans le sous-dossier Views, qui pourra accueillir une fonction menus_views_data. Cette dernière sert à déclarer les données supplémentaires que nous voulons que Views soit capable d’afficher. menus_views_data() /* * Hook views_data */ function menus_views_data(){ // On ajoute un groupe de champs Menus


$data['menus']['table']['group'] = t('Menus'); $data['menus']['table']['base'] = array( 'field' => 'mid', 'title' => t('Menus'), 'help' => t('DĂŠfinitions des menus'), ); // On ajoute le champ Menu ID (mid) $data['menus']['mid'] = array( 'title' => t('Menus ID'), 'help' => t('L\'identifiant unique interne du menu.'), 'field' => array( 'handler' => 'views_handler_field_numeric', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_numeric', ), 'sort' => array( 'handler' => 'views_handler_sort', ), 'argument' => array( 'handler' => 'views_handler_argument_numeric', ), ); // On ajoute le champ Nom du Menu $data['menus']['name'] = array( 'title' => t('Nom du menu'), 'help' => t('Le nom du menu'), 'field' => array( 'handler' => 'views_handler_field', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_string', ), 'sort' => array( 'handler' => 'views_handler_sort', ), 'argument' => array( 'handler' => 'views_handler_argument_string', ), ); // On ajoute le champ Type $data['menus']['type'] = array( 'title' => t('Type de menu'), 'help' => t('Le type de menu.'), 'field' => array( 'handler' => 'views_handler_field', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_menus_type', 'label' => t('Type de menus'),


'use equal' => TRUE, ), 'sort' => array( 'handler' => 'views_handler_sort', ), 'argument' => array( 'handler' => 'views_handler_argument_string', ), ); return $data; }

Nous commençons par ajouter un groupe de champs Menus (au même titre qu’il existe un groupe Contenu ou Taxonomie). Nous définissons ensuite les trois champs contenus dans notre entité : mid, name et type. Pour chacun d’eux, nous ajoutons les différents paramètres nécessaires : le champ (field), le filtre (filter), la possibilité de trier (sort) et l’utilisation du champ comme argument (argument). Pour chacun des paramètres, nous spécifions un handler, c’est-à-dire une définition des informations que nous allons afficher et de leur forme (texte brut, liste, tri, etc.). De nombreux handlers sont définis par défaut dans Views. En savoir plus La documentation de l’API de Drupal fournit la liste des handlers définis par Views. https://api.drupal.org/api/views/views.api.php/group/views_handlers/7

Une fois notre fonction ajoutée, si nous allons dans l’interface d’administration de Views, nous constatons qu’il est possible d’insérer une vue de type Menus.

Figure 5–11 Ajout d’une vue de type Menus

Lors de l’ajout d’une vue de type Menus, nous pouvons également gérer nos trois champs : le tri, les filtres et les arguments (les paramètres que nous avons définis juste avant).

Ajout d’un handler : filtre sur les types de menus sous forme d’une liste de sélection Afin de compléter nos données, nous allons ajouter un handler particulier : un filtre sur les types de Menus sous forme de liste déroulante. Il suffit d’insérer une classe dans le


fichier repas.views.inc. Ajout d’un handler dans repas.views.inc class views_handler_filter_menus_type extends views_handler_filter_equality { /* * On fournit une liste de sélection pour le type */ function value_form(&$form, &$form_state) { parent::value_form($form, $form_state); $form['value'] = array( '#type' => 'select', '#title' => t('Type'), '#options' => array( 'diner' => t('Diner'), 'gouter' => t('Gouter'), ), '#default_value' => $this->value, '#required' => FALSE, ); } }

Cette classe nous permet de définir le formulaire de filtre avec un type liste déroulante (select), un titre, des options (avec le nom machine du bundle, à savoir le nom qui apparaît), la valeur par défaut et le fait que le filtre ne soit pas obligatoire. Nous pouvons ainsi ajouter un filtre qui se présente sous la forme d’une liste déroulante.

Figure 5–12 Filtre sur les types de Menus sous forme de liste déroulante

Avec le développement des handlers, nous avons fait le tour des fonctionnalités principales de Views, aussi bien en ce qui concerne l’interface d’administration que les principaux hooks liés à Views.


Moteur de règles et validation

6

Ce chapitre va nous permettre de déclencher des actions comme l’envoi d’e-mails en fonction de différents événements comme l’ajout de procédures de validation et de publication de contenu. SOMMAIRE Créer des actions Les déclencheurs sur des événements spécifiques Ajouter un moteur de règles complexes avec vues Mettre en place un workflow de validation


Commençons par l’utilisation des actions et déclencheurs (triggers), disponibles nativement dans Drupal.

Envoyer un e-mail à l’auteur d’un contenu lors de la publication d’un commentaire Activons le module du cœur de Drupal, Trigger, via Admin>Modules.

Ajouter une action Envoi de courriel Nous trouvons la liste par défaut des actions qu’il est possible de déclencher dans Admin>Configuration>Système>Actions.

Figure 6–1 Liste des actions disponibles par défaut

Parmi ces actions, nous pouvons choisir de dépublier un contenu ou de bloquer un utilisateur (suite à des insultes ou du spam, par exemple). Ajoutons une action d’envoi de courriel. Pour cela, nous utilisons le formulaire de création d’une action avancée en bas de la page.

Figure 6–2 Créer une action avancée

Nous pouvons alors configurer le courriel qui sera envoyé. Certains champs, comme le destinataire ou le corps du message, acceptent les tokens de remplacement. Sur la figure suivante, par exemple, nous avons choisi d’adresser le courriel à l’adresse électronique de l’auteur du nœud.


Figure 6–3 Configuration du courriel pour l’ajout d’un commentaire

Une fois cette action enregistrée, configurons notre déclencheur pour que le courriel soit envoyé.

Déclencher les actions créées Pour déclencher les actions, rendons-nous dans Admin>Structure>Déclencheurs. Nous arrivons alors sur la liste des déclencheurs existants. En haut à droite se trouvent différents onglets correspondant aux différents types de déclencheurs existants. Pour notre exemple, nous nous rendons dans l’onglet Commentaire pour envoyer un courriel à l’auteur d’un nœud dès qu’un commentaire est publié sur celui-ci. Nous sélectionnons ensuite l’action Envoyer le courriel lors de la publication d’un commentaire sur le déclencheur : après l’enregistrement d’un nouveau commentaire. Une fois notre action sélectionnée, cliquons sur Associer. Ce module du cœur de Drupal permet donc de créer et de déclencher des actions de manière basique. Précisons maintenant les conditions de déclenchement.


Figure 6–4 Liste des déclencheurs liés aux nœuds

Figure 6–5 Ajout de l’action d’envoi d’un courriel après l’enregistrement d’un nouveau commentaire

Figure 6–6 Action d’envoi du courriel associée au déclencheur

Choix du déclencheur Le premier déclencheur (lors de l’enregistrement d’un nouveau commentaire ou d’un commentaire existant) aurait également provoqué l’envoi de l’e-mail lors de la mise à jour


d’un commentaire existant ; ce n’est pas le comportement que nous souhaitions obtenir.

Des règles plus souples avec Rules Allons plus loin avec la mise en place d’un moteur de règles, via le module contrib Rules. Commençons par l’installer et l’activer. MÉTHODE Installer le module Rules par l’interface Télécharger le module : https://drupal.org/project/rules Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de votre site (Admin/Modules) et activer Rules.

MÉTHODE Installer le module Rules en ligne de commande avec Drush $ drush dl rules $ drush en -y rules

Comme Rules est avant tout un module API, nous devons également activer Rules UI pour avoir accès à son interface graphique associée.

Figure 6–7 Activation de Rules et Rules UI

Ajouter une règle par l’interface graphique Pour accéder à la configuration du module, rendons-nous dans Admin>Configuration>Processus>Rules. La liste des règles apparaît : aucune n’est créée par défaut.


Figure 6–8 Liste des règles présentes par défaut

Commençons par créer une règle qui, lors de l’ajout d’un nouveau restaurant, l’épinglera en haut des listes (sticky). Pour parvenir à ce résultat, cliquons sur Add new rule.

Figure 6–9 Ajout d’une règle à la création d’un restaurant

Il faut remplir différents champs : Nom : nom qui apparaît dans la liste des règles ; Étiquettes : pour classer nos règles ; React on event : élément déclencheur de la règle (les actions disponibles ne sont pas les mêmes en fonction du déclencheur) ; Restrict by type (lié aux déclencheurs qui concernent les nœuds) : permet de limiter à un type de contenu. Une fois notre règle créée, nous pouvons détailler un certain nombre d’éléments.


Figure 6–10 Détail d’une règle

Nous pouvons supprimer le déclencheur, appelé événement dans Rules. Nous pouvons également intégrer à notre règle des conditions qui s’ajoutent (+ Add and) ou qui s’excluent (que l’événement remplisse l’une ou l’autre des conditions avec + Add or) et définir des actions ou des boucles pour répéter une action (+ Add loop). Dans notre cas, nous allons ajouter une action : Épingler un contenu en haut des listes.

Figure 6–11 Ajout d’une action Épingler un contenu en haut des listes

Il est maintenant possible de paramétrer notre action (ici, nous laissons la configuration par défaut).


Figure 6–12 Paramétrage de l’action Data selector

En revenant à la page principale de notre règle, nous constatons que notre action nouvellement créée est listée. Nous pouvons alors enregistrer les modifications pour que notre règle s'applique.

Figure 6–13 Action ajoutée et paramètres de la règle

Les paramètres nous permettent de modifier le nom de la règle ou les étiquettes de celle-ci, mais aussi de la désactiver et de lui donner un poids, pour qu’elle s’exécute avant - ou après - d’autres règles. Nous avons donc découvert le fonctionnement de Rules et de son interface graphique. Nous pouvons imaginer de nombreuses utilisations de ces règles.

Création d’une règle en programmant Élaborons une nouvelle règle : lors de la création d’un restaurant et de sa classification dans un type, elle affichera un message proposant à l’utilisateur d’en ajouter un autre. Pour cela, nous créons un nouveau module appelé Restaurant Rules. Commençons par écrire le fichier restaurant_rules.info.


Fichier restaurant_rules.info name = Restaurant Rules description = Affiche un message pour l'ajout et le classement d'un restaurant core = 7.x package = Restaurant dependencies[] = rules dependencies[] = rules_admin

Nous créons également un fichier restaurant_rules.module que nous laissons vide (nécessaire à Drupal) et un fichier restaurant_rules.rules_defaults.inc dans lequel nous déclarons notre règle. Fichier restaurant_rules.rules_defaults.inc <?php /** * @file * restaurant_rules.rules_defaults.inc */ /** * Implements hook_default_rules_configuration(). */ function restaurant_rules_default_rules_configuration() {

Nous déclarons un tableau qui va contenir nos règles (une seule ici, mais nous pourrions en déclarer plusieurs) : $items = array();

Nous définissons notre première règle avec la fonction d’import de l’entité, ce qui nous donne un code très simplifié. Règle qui affiche le message invitant à créer un autre restaurant $items['rules_affichage_d_un_message_pour_la_r_daction_compl_te_d_un_res'] = entity_import('rules_config', '{ "rules_affichage_d_un_message_pour_la_r_daction_compl_te_d_un_res" : { // Le nom qui apparaît dans l'UI de Rules "LABEL" : "Affichage d\\u0027un message pour la r\\u00e9daction compl\\u00e8te d\\u0027un restaurant", "PLUGIN" : "reaction rule", "OWNER" : "rules", // Les étiquettes de notre Rules "TAGS" : [ "Restaurant" ], "REQUIRES" : [ "rules" ], // L'action qui déclenche la règle "ON" : { "node_insert--restaurant" : { "bundle" : "restaurant" } }, // Une condition avec un test IF négatif (si le champ n'est // pas vide) "IF" : [ { "NOT data_is_empty" : { "data" : [ "node:field-type-de-


restaurant" ] } } ], // L'action à effectuer "DO" : [ { "drupal_message" : { "message" : "F\\u00e9licitations vous avez ajout\\u00e9 un restaurant et class\\u00e9 celui-ci ! Voulez-vous en \\u003Ca href=\\u0022node\\/add\\/restaurant\\u0022\\u003Eajouter un autre\\u003C\\/a\\u003E ?" } } ] } }');

N’oublions pas de retourner le tableau contenant nos règles : return $items; }

Notre règle est désormais correctement ajoutée. Pour s’en assurer, il faut retourner dans l’interface, après avoir activé Restaurant Rules dans Admin>Modules et vérifier les règles de notre site via Admin>Config>Processus>Rules.

Figure 6–14 Règle ajoutée par un module Si la règle n’apparaît pas, il faut penser à vider le cache de notre site, via Admin>Configuration>Développement>Performance.

Ajouter une règle grâce à du code permet de versionner nos règles et de les réutiliser dans d’autres projets.

Création d’une action, d’une condition et d’un événement par le code Nous allons maintenant montrer comment étendre les actions, conditions et événements proposés par Rules. Pour cela, nous créons au préalable une vue qui liste l’ensemble des restaurants ; en voici les paramètres.


Figure 6–15 Paramètres de la vue Liste des restaurants

Drupal fournit un système comptant le nombre d’affichages d’un nœud, mais pas d’une vue. En nous appuyant sur Views et sur Rules, notre objectif sera ici d’ajouter un compteur pour afficher le nombre de fois que notre page a été chargée. Réutilisons notre module Restaurant Rules et modifions le fichier restaurant_rules.info comme suit. Modification du fichier restaurant_rules.info name = Restaurant Rules description = Création d'une fonctionnalité de comptage pour l'affichage d'une vue et création d'une règle affichant un message pour l'ajout et le classement d'un restaurant core = 7.x package = Bookdev dependencies[] = rules dependencies[] = rules_admin dependencies[] = views dependencies[] = views_ui

Nous créons un fichier restaurant_rules.install où nous ajoutons la table qui va stocker le nombre d’affichages. Création de la table de stockage du nombre d’affichages dans restaurant_rules.install <?php /** * Définit hook_schema() */ function restaurant_rules_schema() {


$schema['restaurant_rules_views_render'] = array( 'description' => 'La table de base pour le comptage des affichages de restaurant rules', 'fields' => array( 'view' => array( 'description' => 'Le nom et l\'identifiant de l\'affichage de la vue', 'type' => 'varchar', 'length' => '32', 'not null' => TRUE, 'default' => '', ), 'rendered' => array( 'description' => 'Le nombre d\'affichages de la vue', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, ), ), 'primary key' => array('view'), ); return $schema; }

Déclarons maintenant l’événement dans le fichier restaurant_rules.rules.inc que nous créons pour l’occasion. Déclaration de l’événement dans restaurant_rules.rules.inc <?php /* * Définit hook_rules_event_info * */ function restaurant_rules_rules_event_info() { return array( 'restaurant_rules_views_render' => array( 'label' => 'Une vue est affichée', 'group' => 'Restaurant Rules', 'variables' => array( 'view' => array( 'type' => 'restaurant_rules_view_datatype', 'label' => t('La vue qui est affichée'), ) ) ) ); }

Cette fonction déclare l’événement que nous nommons « Une vue est affichée » et que nous plaçons dans le groupe Restaurant Rules. Cet événement s’appuie sur le type (qui est l’élément déclencheur) restaurant_rules_view_datatype. Views n’est pas disponible nativement dans Rules ; il faut déclarer ce type d’information dans les


hook_rules_data_info.

Déclaration d’objets Views dans restaurant_rules_rules_data_info() /** * Définit hook_rules_data_info() * Ici nous indiquons à Rules qu'il s'agit d'un objet de type View. */ function restaurant_rules_rules_data_info() { return array( 'restaurant_rules_view_datatype' => array( 'label' => t('view'), ) ) }

Il nous reste à préciser que cet événement doit être associé à l’affichage d’une vue. Nous utilisons donc le hook_views_pre_render, qui nous permet de déclencher une fonction juste avant l’affichage d’une vue, et nous appelons la fonction rules_invoke_event_by_args qui invoque l’événement créé dans notre module Restaurant Rules. Appel de l’événement juste avant l’affichage de la vue /** * Définit hook_view_pre_render * Invoquer notre événement personnalisé à l'affichage de la vue */ function restaurant_rules_views_pre_render(&$view) { rules_invoke_event_by_args('restaurant_rules_views_render', array($view)); }

Nous définissons ensuite notre condition de sélection de la vue qui déclenche l’événement. Condition de sélection de la vue déclenchant l’événement /** * Définit hook_rules_condition_info * Nous déclarons notre condition */ function restaurant_rules_rules_condition_info() { return array( 'restaurant_rules_views_condition' => array( 'label' => t('La vue affichée est'), 'parameter' => array( 'view' => array( 'type' => 'text', 'label' => t('Vue et affichage'), 'options list' => 'restaurant_rules_view_list', 'description' => t('Sélectionner la vue et l\'id de


l\'affichage'), 'restriction' => 'input', ), ), 'group' => t('Restaurant Rules'), ), ); }

Dans

la

déclaration

de notre condition, restaurant_rules_view_list qu’il nous faut définir.

nous

appelons

une

fonction

Fonction restaurant_rules_view_list /** * Fonction qui renvoie la liste de toutes les vues activées du site */ function restaurant_rules_view_list() { $views = array(); foreach (views_get_enabled_views() as $view_name => $view) { foreach ($view->display as $display_name => $display) { $views[$view_name . '-' . $display_name] = check_plain($view>human_name) . ' - ' . check_plain($display->display_title); } } return $views; }

Nous

devons

également

définir la fonction déclarée dans condition_info, restaurant_rules_views_condition, qui va comparer le nom de la vue sélectionnée à celui de la vue affichée et ne déclencher l’action que si la condition renvoie TRUE. Fonction restaurant_rules_views_condition() /** * Callback fonction pour notre condition personnalisée * Le nom de la fonction doit correspondre à la clé du tableau dans notre restaurant_rules_conditition_info */ function restaurant_rules_views_condition($view = array()) { $current_view = views_get_current_view(); $parts = explode('-', $view); if(($parts[0] == $current_view->name) && ($parts[1] == $current_view>current_display)) { return TRUE; } return FALSE; }

Maintenant que notre condition est écrite, il nous reste à intégrer notre action. Comme pour l’événement et la condition, nous devons commencer par déclarer notre action avec le hook_rules_action_info.


Déclaration avec restaurant_rules_rules_action_info() /** * Définit hook_rules_action_info */ function restaurant_rules_rules_action_info() { return array( 'restaurant_rules_update_table' => array( 'label' => t('Mise à jour de la table des affichages de vues'), 'parameter' => array( 'view' => array( 'type' => 'restaurant_rules_view_datatype', 'label' => t('La vue affichée'), ), ), 'group' => t('Restaurant Rules'), ), ); }

Nous devons également déclarer la fonction correspondante. restaurant_rules_update_table() /** * La fonction de base de données appelée par l'action de Rules * Le nom de la fonction doit être le même que celui déclaré dans le hook_rules_action_info */ function restaurant_rules_update_table($view) { // On teste pour vérifier que la vue est bien un objet if (!is_object($view)) { return FALSE; } // On sélectionne la vue concernée en base $result = db_select('restaurant_rules_views_render','r') ->fields('r') ->condition('view', $view->name .'_'. $view->current_display, '=') ->execute() ->fetchAssoc(); // S'il y a des résultats sur le select, on met à jour if($result) { $update = db_update('restaurant_rules_views_render') ->expression('rendered', 'rendered + :one', array(':one' => 1)) ->condition('view', $view->name .'_'. $view>current_display, '=') ->execute(); } else {


$insert = db_insert('restaurant_rules_views_render') ->fields(array( 'view' => $view->name .'_'. $view->current_display, 'rendered' => 1 )) ->execute(); } }

Il ne nous reste plus qu’à créer notre règle en utilisant tous les éléments que nous venons d’ajouter. Pour cela, nous retournons dans l’interface des règles via Admin>Configuration>Processus>Rules. Nous ajoutons une règle que nous appelons Compter le nombre d’affichage de la liste des restaurants et qui se déclenche sur notre événement « Une vue est affichée ».

Figure 6–16 Création de la règle de compteur d’affichage

Nous ajoutons une condition pour sélectionner la vue Liste des restaurants.

Figure 6–17 Ajoutons une nouvelle condition.

Puis il nous reste à insérer notre action et voilà notre règle dans son intégralité.


Figure 6–18 Compter le nombre d’affichages de la liste des restaurants

Nous avons donc terminé avec le module Rules ; à nous d’être créatifs pour ajouter événements, conditions, actions et toutes les règles que nous souhaitons.

Gérer un workflow de publication simple avec Drupal Drupal propose nativement de nombreuses façons de gérer un workflow de publication (ou processus de publication). Par défaut, un utilisateur qui peut créer des contenus (nœuds) peut choisir s’il enregistre son contenu dans un état Publié ou Non publié. Mais Drupal ne permet pas de définir précisément les droits des utilisateurs liés à la publication ou la modification des contenus en fonction de leur état. Pour que l’utilisateur puisse choisir s’il veut ou non publier son contenu, nous devons lui donner des droits très étendus qui permettent également de modifier tous les nœuds du site, ce que nous ne voulons pas forcément faire. Voyons comment nous pouvons contourner ce problème en utilisant un module contribué. Deux autres possibilités sont également disponibles : Promu en page d’accueil et Épinglé en haut des listes. Ces deux options servent à mettre en avant un contenu particulier et nécessitent la permission Administrer les nœuds. Plutôt que de donner la permission d’administrer les nœuds à un utilisateur, nous allons utiliser un module personnalisé : Override node options.


Figure 6–19 Options de publication d’un contenu

MÉTHODE Installer le module Override node options par l’interface Télécharger le module : https://drupal.org/project/override_node_options Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver le module dans la liste et l’activer en cochant la case.

MÉTHODE Installer le module Override node options en ligne de commande avec Drush $ drush dl override_node_options $ drush en -y override_node_options

Une fois le module téléchargé et activé via Administrer>Modules, rendons-nous dans la page des permissions pour vérifier chaque type de contenu existant sur notre site et choisir précisément quelles options sont autorisées selon les rôles que nous voulons définir (nous reviendrons sur les rôles dans le chapitre 7). Nous avons ici donné la possibilité aux utilisateurs authentifiés, c’est-à-dire ceux qui ont un compte sur le site et qui se connectent, de promouvoir les contenus de type Restaurant en page d’accueil, de les épingler en haut des listes et de les enregistrer en Non publié en leur attribuant les permissions correspondantes (donc non visible par les visiteurs de notre site). Cela permet à nos auteurs de choisir finement les options de publication et cela nous laisse gérer (avec le droit Supplanter les options de publication) un workflow simple avec un contenu d’abord créé en brouillon (Non publié), puis Publié (et donc visible par n’importe quel visiteur) une fois qu’il a été retenu.


Figure 6–20 Les droits du module Override Node Options

En créant un rôle Relecteur, nous allons ajouter une nouvelle règle chargée, à la création d’un contenu Non publié, d’envoyer un courriel aux relecteurs du site, qui valideront alors le contenu et sa publication. Créons une nouvelle règle dans le menu Administration>Configuration>Processus>Rules. La figure suivante montre ce que nous obtenons dans l’interface.

Figure 6–21 Règle pour l’envoi d’un e-mail aux relecteurs lors de la proposition d’un nouveau restaurant

Dans sa version de base, Drupal autorise la mise en place d’un workflow simple. Pour aller plus loin, utilisons un autre module dédié.

Un circuit plus complexe avec le module Workflow Si nous avons besoin d’un workflow plus complexe avec différentes étapes de validation, comme une validation du contenu, puis une relecture et enfin une publication, nous allons


rapidement devoir utiliser un module contrib supplémentaire. Parmi les différents outils existants, nous avons choisi de présenter Workflow qui reste l’un des plus utilisés aujourd’hui. MÉTHODE Installer le module Workflow par l’interface Télécharger le module : https://drupal.org/project/workflow Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver le module et l’activer en cochant la case.

MÉTHODE Installer le module Workflow en ligne de commande avec Drush $ drush dl workflow $ drush en -y workflow

Puis, dans l’interface, partons à la découverte des modules de Workflow. Workflow access sert à définir des droits de lecture/modification en fonction de l’état de Workflow. Workflow actions and trigger permet d’interagir avec les actions et déclencheurs fournis par le cœur de Drupal. Workflow API doit être activé pour utiliser les autres sous-modules. C’est lui qui fournit les fonctionnalités de base de Workflow. Workflow clean up supprime les états (étapes de validation dans le circuit de publication) lors de la suppression d’un workflow (/!\ à utiliser avec précaution). Workflow field ajoute un champ de type workflow à n’importe quelle entité de notre site. Workflow Node assure la compatibilité avec les anciennes versions du module. Sans contrainte spécifique liée à un site existant, nous conseillons d’utiliser Workflow field. Workflow node search API intègre la recherche fournie par Search API. Workflow Revert revient à l’état de workflow précédent. Workflow Rules permet l’intégration des workflows pour la création de règles avec le module Rules. Workflow UI est l’interface graphique d’administration du module Workflow. Workflow VBO permet l’intégration avec Views Bulk Operation et ses actions en masse sur les contenus. Workflow Views permet l’intégration avec le module Views. Pour démarrer, nous activerons les modules suivants de Workflow : API, Fields et UI.

Création de notre premier workflow Rendons-nous dans Administration>Configuration>Processus. Nous arrivons sur une liste vide et la possibilité d’ajouter un workflow (traduit en français par processus).


Figure 6–22 Ajouter un processus

Pour créer notre workflow, il suffit dans un premier temps de lui choisir un nom.

Figure 6–23 Nommer le nouveau processus

Nous arrivons sur la page de création des états du workflow. En dehors de l’état (création), qui existe par défaut lors de la création d’une entité, nous pouvons concevoir autant d’états que nécessaire. Dans notre exemple, nous créons : Brouillon, À relire et Validé.

Figure 6–24 Définition des états du workflow

Une fois nos états de workflow créés, nous devons définir les rôles qui sont autorisés à effectuer des transitions (des changements d’état de workflow). Pour cela, nous cliquons su r + Transitions et nous obtenons un tableau avec, à gauche, les différents états de départ des entités et, en haut, les états d’arrivée. La liste des rôles potentiellement concernés est placée à chaque intersection ligne/colonne.


Figure 6–25 Définition des transitions du workflow

Pour avoir une vue d’ensemble, nous cliquons sur + Résumé.

Figure 6–26 Résumé de notre worflow

Il nous reste désormais à indiquer à Drupal sur quelle entité il est possible d’utiliser ce workflow.

Utilisation d’un workflow sur une entité Comme pour les taxonomies, nous devons ajouter un champ à notre entité dans Administration>Structure>Types de contenu. Sur la ligne Restaurant, nous choisissons Gérer les champs, puis nous créons un champ de type Workflow (Processus) en utilisant le widget Processus.


Figure 6–27 Ajout d’un champ de workflow sur un type de contenu

Dans les paramètres du champ, nous choisissons le workflow créé à l’étape précédente, puis nous sélectionnons l’affichage des choix de workflow.

Figure 6–28 Paramètres du champ de workflow

La deuxième partie des paramètres du champ sert à définir si nous voulons que l’historique des modifications de workflow soit enregistré et qui peut y avoir accès.

Figure 6–29 Paramètres du champ de workflow : workflow history

Une fois les paramètres du champ spécifique à Workflow enregistrés, nous avons la possibilité de préciser des paramètres communs à chaque champ, comme l’étiquette ou le


texte d’aide.

Figure 6–30 Paramètre du champ commun de workflow

Nous en avons terminé. Voici ce que nous obtenons si nous ajoutons un nouveau restaurant avec un utilisateur ayant un rôle d’administrateur.

Figure 6–31 Ajout d’un restaurant avec le champ de workflow

Nous avons présenté les bases du module Workflow. N’hésitez pas à regarder les autres modules disponibles (Workflow Rules, Workflow Trigger, Workflow Views, etc.)


Gérer les groupes d’utilisateurs et leurs spécificités avec Organic Groups

7

Drupal permet de gérer aisément plusieurs types d’utilisateurs et de leur donner l’accès uniquement à ce que nous souhaitons. Nous allons également aborder dans ce chapitre la création de communautés d’utilisateurs avec Organic Groups.

SOMMAIRE Les utilisateurs, les permissions et les rôles : ce que c’est, à quoi ça sert et comment on les gère L’ajout par les codes d’utilisateurs et de rôles La longue liste des permissions La gestion des permissions en développant La gestion des groupes d’utilisateurs avec Organic Groups


Le concept d’utilisateur et de rôles dans Drupal Drupal, comme de nombreux autres CMS, nous permet de créer des comptes utilisateurs sur notre site. Dans notre site exemple, les comptes serviront par exemple pour autoriser les utilisateurs à ajouter de nouveaux plats, de nouveaux restaurants ou menus. Ainsi, un utilisateur est un visiteur qui a la particularité de posséder un compte sur notre site, et donc de pouvoir s’y connecter. Pour éviter de devoir gérer les utilisateurs individuellement, Drupal utilise également un système de rôles, correspondant à des groupes d’utilisateurs qui ont des permissions identiques.

À la découverte de l’interface d’administration des utilisateurs et des rôles Accédons au menu Personnes de l’interface d’administration de Drupal. Nous arrivons alors sur une page qui liste l’ensemble des utilisateurs inscrits sur le site ; elle se présente sous la forme d’un tableau, avec les derniers utilisateurs inscrits en tête de liste.

Figure 7–1 La liste des utilisateurs inscrits sur le site

Ajouter un utilisateur Il suffit de cliquer sur le lien Ajouter un utilisateur et un formulaire de création de compte s’affiche. Voici quelques précisions sur les champs proposés : Nom d’utilisateur - C’est l’identifiant utilisé par l’internaute pour se connecter sur notre site. Adresse de courriel - Il s’agit de l’adresse à laquelle l’utilisateur pourra récupérer son mot de passe ou les notifications liées au site. Mot de passe - Il doit être confirmé en le saisissant une deuxième fois. Statut - Un utilisateur qui a un statut Bloqué possède un compte sur le site mais ne peut pas s’y connecter. Par défaut, les comptes ont un statut Actif. Rôles - Nous devons cocher tous les rôles désirés pour l’utilisateur.


Il est possible de Notifier l’utilisateur de la création de son nouveau compte (un message lui parvient alors par courriel). Nous pouvons choisir la langue par défaut de l’utilisateur.

Figure 7–2 Formulaire d’ajout d’un utilisateur

Lorsque nous avons rempli l’ensemble des champs (ou au moins ceux qui sont obligatoires), Drupal affiche par défaut un nouveau formulaire d’ajout. Pour retrouver notre utilisateur nouvellement créé, il faudra de nouveau cliquer sur Personnes et consulter la liste des utilisateurs de notre site. Rôles existants et ajout de rôle Pour accéder aux rôles existants dans Drupal, il nous faut cliquer sur Personnes, puis sur l’onglet Droits (à droite de la page) et enfin sur le sous-onglet Rôles. Nous voyons dans la liste trois rôles proposés par défaut : utilisateur anonyme : correspond aux utilisateurs non connectés sur le site. utilisateur authentifié : tous les utilisateurs possédant un compte sont inscrits automatiquement dans ce rôle. administrator : il s’agit du rôle auquel on donne généralement le plus de permissions, puisqu’il correspond à la poignée de personnes qui vont administrer l’ensemble du site. Le compte créé lors de l’installation possède ce rôle.


Figure 7–3 La liste des rôles existants dans Drupal

Nous allons ajouter un modérateur, pour permettre à plusieurs utilisateurs de vérifier les contenus écrits par les autres utilisateurs et les modifier si nécessaire. Remplissons donc le champ texte en bas de la page et cliquons sur Ajouter un rôle. Le rôle apparaît alors dans la liste. Nous allons les réordonner pour les classer du rôle qui a le moins de droits (utilisateur anonyme) à celui qui en a le plus (administrator).

Figure 7–4 Réordonner les rôles dans Drupal

La ligne concernée est alors surlignée en jaune et un message nous informe que les changements n’ont pas été effectués. Cliquons sur Enregistrer l’ordre pour que les modifications soient bien sauvegardées dans notre base de données. Nous avons ainsi découvert comment créer les utilisateurs et les rôles dans Drupal. Voyons maintenant comment le faire via du code PHP, en utilisant l’API du CMS.

L’ajout d’utilisateurs et de rôles par la programmation Les rôles peuvent également être intégrés dans nos modules pour faciliter leur réutilisation d’un site à l’autre. De plus, lors des phases de tests (voir le chapitre 9), nous aurons besoin de créer automatiquement des utilisateurs fantômes sans passer par un navigateur. Commençons par créer le rôle de modérateur dans notre module Menus. Pour cela, nous utilisons le fichier menus.install, auquel nous ajoutons la fonction menus_install suivante. menu_install() /* * Hook hook_install pour ajouter des rôles */ function menus_install() { $role = new stdClass(); $role->name = 'moderateur'; $role->weight = 10; user_save_role($role); };

Nous venons de créer un rôle appelé moderateur qui a un poids de 10. Il n’aura par défaut aucune permission. Nous verrons dans la partie suivante comment ajouter des permissions à un rôle.


Pour créer un utilisateur, nous restons dans la fonction menus_install et ajoutons le code suivant. user_role_load_by_name() /* * Ajout d'un utilisateur */ // On récupère l'id du rôle $role = user_role_load_by_name('moderateur'); $role_id = $role->rid; $new_user = new stdClass(); $new_user->name = 'jean martin'; $new_user->pass = 'jmartin' // Le mot de passe est ici en clair // lors de la création $new_user->mail = 'jeanmartin@bookdev.com'; $new_user->roles = $role_id; $new_user->status = 1 // Le compte est actif // On sauvegarde l'utilisateur créé user_save($new_user);

Nous avons ainsi ajouté un nouvel utilisateur. Attention, cette méthode nous oblige à écrire le mot de passe en clair ; elle peut donc être utilisée pour des tests, mais n’est pas recommandée pour créer des utilisateurs réels sur notre site.

La gestion des profils utilisateurs Maintenant que nous avons vu ensemble comme ajouter des utilisateurs et des rôles, il nous reste à expliquer comment ajouter des champs de profils à nos utilisateurs. Gestion du profil par l’interface d’administration Pour que nos utilisateurs puissent ajouter des informations sur leur profil, Drupal nous propose d’utiliser l’entité Utilisateur et, comme pour tout type d’entité, de lui ajouter des champs. Pour cela, nous nous rendons dans le menu Configuration>Personnes>Paramètres de compte. Nous arrivons alors sur un écran similaire à celui de la configuration des types de contenus avec des paramètres, la gestion des champs et la gestion de l’affichage.


Figure 7–5 Paramètres d’un compte utilisateur

Nous définissons alors des paramètres d’inscription pour les utilisateurs, comme l’obligation de confirmer leur inscription par l’envoi d’un courriel contenant un lien, ou la possibilité seulement pour les administrateurs de créer des comptes (les visiteurs anonymes ne peuvent alors plus se créer de compte seul). Il est également possible de configurer les courriels envoyés aux utilisateurs lors des différentes étapes de gestion de leur compte (création, approbation, etc.). Dans l’onglet Gérer les champs, nous pouvons ajouter de nouveaux champs comme nous l’avons fait sur un type de contenu au chapitre 4. Ici, nous ajoutons un champ Age de type Entier à notre entité Utilisateur. Ainsi, nous sommes en mesure de gérer des profils utilisateurs, en ajoutant autant de champs que nécessaire à notre entité. Cela aura l’immense avantage de s’appuyer sur le core de Drupal et, donc, les champs seront facilement exploitables avec les fonctions de base du CMS.

Figure 7–6 Ajout d’un champ Age à l’entité Utilisateur

Ajout de champs à l’entité Utilisateur par le code Nous allons créer un nouveau module, appelé Menus Utilisateurs. Passons sur les fich iers menus_utilisateurs.info et menus_utilisateurs.module, vides pour l’instant, et concentrons-nous sur le fichier menus_utilisateurs.install.


menus_utilisateurs_install() /* * Hook hook_install */ function menus_utilisateurs_install() { // On créer le champ field_create_field(array( 'field_name' => 'age', 'cadinality' => 1, 'type' => 'number_integer', // number_decimal, text_long, text )); // On ajoute le champ au Bundle field_create_instance(array( 'field_name' => 'age', 'label' => 'Instance pour le champs age', 'entity_type' => 'user', 'bundle' => 'user', )); }

Nous avons ici créé le champ Age et nous l’avons attaché au bundle user de l’entité user. Nous pouvons ainsi créer des modules réutilisables qui ajoutent des champs à notre entité. Pour voir notre champ apparaître, il faut penser à activer le module Menus Utilisateurs que nous venons de créer.

La gestion des droits Drupal offre une très grande souplesse dans la gestion des droits. En effet, le cœur du CMS et chacun des modules qu’il utilise ajoutent un ensemble de permissions que les administrateurs du site doivent ensuite accorder à des rôles, voire à des utilisateurs précis. Nous allons donc expliquer dans un premier temps comment les droits sont présentés dans l’interface d’administration et comment nous pouvons donner des droits supplémentaires à notre rôle de modérateur. Puis nous verrons comment ajouter des permissions spécifiques à l’entité que nous avons créée au chapitre 4.

Gestion des droits avec l’interface d’administration Pour afficher la liste des droits définis sur notre site, nous nous rendons dans Personnes, puis sur l’onglet Droits.


Figure 7–7 Liste des droits

Les droits se présentent sous la forme d’un tableau avec des cases à cocher, chaque ligne correspondant à une permission et chaque colonne à un rôle. La liste est assez longue, mais cela nous permet de définir finement qui est autorisé à faire quoi. À chaque ajout de modules, il est important d’aller contrôler les droits associés. Ces derniers sont classés en catégories, ce qui aide à retrouver les permissions liées à un module ou à une grande fonctionnalité.

Ajouter des permissions à notre entité Menus Pour ajouter de nouvelles permissions, il faut obligatoirement les créer dans un module dédié. Reprenons notre module Menus et ajoutons dans menus.module une permission qui nous permettra d’administrer spécifiquement les menus. menus_permission() /* * Implementation hook_permission */ function menus_permission() { return array( 'administer menus' => array( 'title' => t('Administrer les menus'); 'description' => t('Administrer les entités menus et leurs bundles'), ); }

Des groupes d’utilisateurs (OG) Pour ajouter des groupes d’utilisateurs, nous allons utiliser un module contrib de Drupal : Organic Groups, ou OG.


MÉTHODE Installer le module OG par l’interface 1. Télécharger les modules Organic Groups, Entity, Entityreference et Views Bulk Operations : https://drupal.org/project/og https://drupal.org/project/entity https://drupal.org/project/entityreference https://drupal.org/project/views_bulk_operations 2. Décompresser les archives dans notre dossier /sites/all/modules. 3. Aller à la page des modules de notre site (Admin/Modules). 4. Trouver les modules ci-dessus dans la liste et les activer.

MÉTHODE Installer le module OG en ligne de commande avec Drush $ drush dl og entity entityreference views_bulk_operations $ drush en -y og entity entityreference views_bulk_operations

Le module Views Bulk Operations permet de créer des groupes d’utilisateurs, un groupe étant considéré comme un nœud. Sa particularité est que plusieurs utilisateurs du site peuvent devenir membres d’un ou de plusieurs groupes. Commençons donc par télécharger le module VBO, l’installer et l’activer sur notre site. Ensuite, nous expliquerons comment ajouter un groupe et quels contenus peuvent lui être spécifiques. Nous présenterons comment des utilisateurs peuvent devenir membres et quelles sont les permissions spécifiques que cela leur donne. Enfin, nous verrons comment on peut avec Views afficher les différents éléments d’un groupe sur des blocs.

Figure 7–8 Liste des modules d’Organic Groups

Sur la page des modules, nous voyons que plusieurs composants sont disponibles en plus d’Organic Groups. Détaillons ces différents modules.


Organic groups est le module principal, celui qui nous permet de créer des groupes et d’y affecter membres et contenus. Organic groups access control sert à gérer plus finement les droits d’accès aux groupes et à leur contenu. Organic groups context permet de récupérer un groupe (celui du contenu que l’on consulte ou celui lié à l’utilisateur) dans une page. Organic groups field access définit des permissions spécifiques aux champs d’un type de contenu groupe. Organic groups register affecte un ou plusieurs groupes à un utilisateur lors de son inscription sur le site. Organic groups UI permet de configurer graphiquement Organic Groups et d’ajouter des groupes depuis l’interface de Drupal.

Création d’un groupe et paramétrages Activons les modules Organic Groups et Organic Groups UI. Un groupe n’est rien d’autre qu’un type de contenu particulier qui contient certains champs spécifiques. Commençons par créer un nouveau type : Structure>Type de contenu>+ Ajouter un type de contenu. Nommons-le Groupe. Nous remarquons qu’une nouvelle rubrique a fait son apparition.

Figure 7–9 Paramètres d’Organic Groups sur un type de contenu

Deux options sont proposées. Groupe définit que ce type de contenu est un groupe. C’est la case que nous allons cocher. Contenu de groupe permet de rattacher un contenu à un groupe. Lorsque nous choisissons Groupe, le type de contenu est alors ajouté. Examinons-en les spécificités. Lors de l’ajout d’un contenu Groupe, aucun champ spécifique ne lui est par


défaut associé. Nous avons seulement les champs Titre et Body. Ajoutons un type de contenu Ville en cochant la case Groupe. Ainsi, nos utilisateurs pourront être membres d’une ville et rattacher des plats et des restaurants à cette dernière.

Figure 7–10 Ajout d’un type de contenu Ville comme Groupe

Ajoutons maintenant un contenu nommé Lyon, de type Ville.

Figure 7–11 Nouveau contenu groupe ajouté

Nous voyons certaines options spécifiques apparaître : Une indication précise que l’utilisateur connecté est le group manager : c’est systématiquement et par défaut l’utilisateur qui crée le groupe qui aura ce rôle. Un onglet Groupe contient différentes options spécifiques. Nous pouvons définir pour chaque groupe un certain nombre d’éléments : ajouter des utilisateurs en tant que membres ; gérer des permissions spécifiques ; gérer les membres (les supprimer, ou leur donner des rôles spécifiques) ; modifier les rôles spécifiques aux groupes. Nous verrons l’ensemble de ces réglages spécifiques dans la partie « Membres et permissions ».


Figure 7–12 Les paramètres spécifiques à un groupe

Contenus spécifiques aux groupes Nous devons maintenant rattacher aux groupes certains types de contenus. Cela donne à nos membres accès à certains types d’informations spécifiques ou liées à un groupe. Par exemple, au sein d’une ville, nous allons rattacher des restaurants. Nous allons donc modifier le type de contenu Restaurant, en passant par Admin>Structure>Types de contenu>Restaurant>Modifier, puis en choisissant l’onglet Organic Groups.

Figure 7–13 Transformation du type de contenu Restaurant en Contenu de groupe

Une fois cette modification effectuée, nous ajoutons un nouveau restaurant et constatons qu’un champ supplémentaire est apparu dans le formulaire d’ajout de contenu. Ce champ supplémentaire laisse choisir à quel groupe appartient le contenu que nous sommes en train de créer (ou de modifier). La liste contient exclusivement les groupes dont nous sommes déjà membres. Cependant, comme nous sommes connectés avec un compte administrateur, nous pouvons également décider de rattacher ce contenu à un autre groupe dont nous ne sommes pas membre avec le champ Autres groupes.


Figure 7–14 Réglages du groupe dans lequel le contenu apparaîtra.

Un contenu peut être rattaché à plusieurs groupes. Il sera alors visible de l’ensemble des membres de ces différents groupes.

Membres et permissions d’un groupe Les groupes sont avant tout un moyen pour des utilisateurs de se réunir par centre d’intérêt. Dans notre exemple, nous avons souhaité regrouper par ville ; ainsi, les utilisateurs habitant cette ville ou venant y passer quelques jours peuvent rejoindre le groupe pour avoir accès à son contenu associé. Gestion des membres d’un groupe Par défaut, les utilisateurs demandent à rejoindre un groupe, puis les administrateurs les y ajoutent et valident leur inscription. Lorsque nous arrivons sur la page d’un groupe dont nous ne sommes pas membre, nous trouvons un lien pour demander à rejoindre le groupe.

Figure 7–15 Lien pour demander l’adhésion à un groupe

Puis un écran nous demande de confirmer que nous souhaitons rejoindre le groupe et nous propose d’indiquer un message spécifique pour étayer cette demande.


Figure 7–16 Confirmation de la demande d’adhésion à un groupe

Ensuite, l’administrateur du groupe voit apparaître la demande dans les utilisateurs du groupe (menu Personnes), avec le statut En attente.

Figure 7–17 Liste des membres d’un groupe ou des personnes qui ont demandé à rejoindre le groupe.

Pour valider une adhésion à un groupe, l’administrateur doit cocher la case devant l’utilisateur concerné et choisir Modifier le statut d’un membre dans la liste déroulante des actions, puis cliquer sur Exécuter.

Figure 7–18 Modification du statut d’un membre

Ce dernier doit ensuite choisir Actif dans les état proposés et confirmer son choix. L’administrateur du groupe peut également Ajouter des utilisateurs dans le menu Groupe. Ils seront membres actifs, sans besoin de confirmer leur adhésion.


Figure 7–19 Ajouter des utilisateurs dans un groupe

L’administrateur a donc toute latitude pour choisir quel utilisateur il souhaite ajouter au groupe et lui donner directement le rôle d’administrateur. Il peut également ajouter un message qui sera envoyé aux membres ainsi ajoutés. Gestion des permissions et des rôles d’un groupe Le point essentiel à comprendre sur l’accès aux contenus dans les groupes est que les restrictions qui leur sont spécifiques (définies par l’appartenance ou non en tant que membre) viennent s’ajouter aux permissions génériques définies pour l’ensemble du site. Par exemple, même si un utilisateur a la permission de modifier tous les contenus de type Restaurant, il ne pourra pas modifier ceux du groupe Lyon s’il n’est pas membre de ce dernier. Les rôles qui sont définis par défaut pour chaque groupe sont les suivants. Le non-membre ne fait pas partie du groupe. Le membre fait partie du groupe. Le membre administrateur peut gérer les membres et les réglages de ce groupe.

Figure 7–20 Liste des rôles par défaut d’un groupe

Ces rôles sont génériques, c’est-à-dire qu’ils sont valables pour n’importe quel groupe. Pour ajouter des rôles (ou en supprimer), nous utilisons le menu Configuration>Organic Groups>OG roles overviews. Nous arrivons alors sur la liste des types de contenu que nous avons définis en tant que Groupe.


Figure 7–21 Listes des types de contenus groupes pour la modification des rôles

Cliquons sur Modifier pour ajouter un rôle à nos groupes.

Figure 7–22 Ajout d’un rôle dans les groupes

Le rôle que nous avons ajouté sera disponible pour l’ensemble des groupes. Pour chacun des rôles, des permissions spécifiques à un groupe sont définies.

Figure 7–23 Permissions dans un groupe

Chaque permission est donnée ou non à un rôle. Nous sommes ici dans un groupe spécifique et les permissions étant en lecture seule, nous ne pouvons pas les modifier. Il faut passer par Configuration>Organic Groups>OG Permissions Overview pour arriver sur une liste des types de groupes.

Figure 7–24 Liste des types de groupes pour les permissions

Il faut cliquer sur Modifier pour changer les permissions.


Figure 7–25 Modifications des permissions des nœuds de type groupe

Les modifications que nous apporterons ici s’appliqueront à l’ensemble des groupes de ce type (Ville dans notre cas). N’oublions pas de cliquer sur Enregistrer les droits d’accès pour valider nos modifications.

Pour régler les permissions de manière spécifique à chaque groupe, nous devons activer les modules Organic Groups access control et Organic Groups field access. Nous obtenons alors le message suivant :

Figure 7–26 Message d’erreur : les permissions d’accès au contenu doivent être reconstruites.

Ce message signifie que le module a modifié des permissions déjà enregistrées dans la base de données et que Drupal a besoin de les réorganiser pour que le module activé fonctionne. Cliquons ensuite sur Reconstruire les permissions et confirmons notre choix. Ajoutons un champ spécifique permettant de personnaliser les permissions et les rôles pour chaque groupe. Pour cela, nous nous rendons dans Configuration>Organic Groups>Paramètres des champs. Nous avons alors la possibilité d’ajouter des champs à certains bundles, ce que nous allons faire avec le bundle Groupe.


Figure 7–27 Ajout d’un champ à un bundle Groupe

Nous choisissons un champ Rôles et droits du groupe puis nous cliquons sur Ajouter un champ. Pour vérifier que l’ajout de notre champ a été effectué correctement, rendons-nous dans le gr o u p e Lyon et cliquons sur Modifier. Cela nous renvoie sur le formulaire de modification d’un contenu de type Groupe. Un champ est bien apparu (en dessous du champ Body), qui s’appelle Rôles et droits du groupe. Il permet de garder les rôles et droits par défaut, ou de les surcharger.

Figure 7–28 Champs Rôles et droits du groupe

En choisissant Override default roles and permissions, nous voyons dans le menu Groupes que les items Permissions et Rôles, ne sont plus en lecture seule.

Figure 7–29 Menu Groupes sans lecture seule

Nous pouvons enfin définir des rôles et permissions spécifiques à notre groupe.


Gérer les terminaux mobiles

8

Ce chapitre explique comment adapter notre site pour que l’utilisateur puisse le consulter et ajouter facilement du contenu depuis différents terminaux mobiles, comme des smartphones ou des tablettes. Nous aborderons également la communication entre sites à partir de webservices.

SOMMAIRE Un site Drupal adaptable au mobile Détection du terminal de consultation Thème en Responsive Design Création de webservices


Avant d’entrer dans le vif du sujet, une précision est nécessaire. Lorsque nous parlons dans ce chapitre de terminaux mobiles, nous faisons évidemment référence au matériel de consultation (smartphone ou tablette). Toutefois, il s’agit de façon plus générale du fait de consulter un site web depuis des écrans dont les tailles et surtout les vitesses de connexion sont extrêmement variées. Le terme « mobile » est donc à la fois lié aux périphériques et au contexte d’utilisation du site web. Nous pouvons maintenant détailler les différents outils qui nous aideront à gérer ces cas d’utilisation de plus en plus fréquents. Nous allons voir dans ce chapitre que plusieurs stratégies existent pour prendre le mobile en considération, aucune n’étant plus à conseiller que les autres. Le même site pourra en effet être décliné de différentes façons pour le mobile.

Un seul site avec un affichage et un contenu adapté ? Pour adapter l’affichage de notre site en fonction du contexte, nous poserons deux axes de travail. Nous concevrons plusieurs affichages, car un utilisateur ne recherche pas les mêmes informations et ne les consulte pas de la même façon selon son contexte de navigation. Nous avons donc mis de côté le mythe qui consiste à penser que l’affichage d’un site web peut rester le même et s’adapter à tout type d’écran ; cela reste l’idéal à atteindre, mais c’est extrêmement compliqué à mettre en œuvre dans la pratique. Nous fournirons par défaut au visiteur une certaine version du site, que nous pensons être la plus lisible et la plus agréable à utiliser en fonction de son contexte. Toutefois, nous laisserons le choix à l’utilisateur de consulter une autre version du site. En effet, il lui serait très désagréable de ne pas trouver sur son smartphone une information qu’il sait exister sur la version Bureau du site. Il faudra donc garder une certaine souplesse pour ne pas frustrer notre visiteur.

Adapter la mise en forme avec un thème en Responsive Design L’affichage de notre site, via son thème, peut être construit de manière à permettre la consultation sur différents périphériques. Cette partie traitera donc de ce qu’on appelle communément le Responsive Design, qui consiste à adapter l’affichage d’un site web à la taille du périphérique de consultation. Cette méthodologie s’appuie principalement sur l’évolution des technologies d’affichage du Web, avec l’arrivée depuis quelques années des langages HTML 5 et CSS 3. La combinaison de ces deux technologies permet de connaître la taille de l’écran de consultation et d’adapter en conséquence la présentation des informations. ALLER PLUS LOIN Responsive Design Voir le blog d’Ethan Marcotte : www.alistapart.com/articles/responsive-web-design/ Ethan Marcotte, Responsive Web Design, Eyrolles, 2012


Jérémie Patonnier, Rudy Rigot, Projet Responsive Web Design, Eyrolles, 2013

Le principe de base du Responsive Design utilise les media queries, qui sont des outils recherchant des informations auprès des clients. Découverte et installation d’un thème Nous allons partir d’un thème existant, Zen, compatible avec le Responsive Web Design. Toutefois, d’autres thèmes existent et sont également prévus nativement pour s’adapter sur différentes tailles d’écran. Quelques thèmes https://drupal.org/project/zen https://drupal.org/project/adaptivetheme https://drupal.org/project/bootstrap

Pour installer Zen, rendons-nous dans Admin>Apparence, puis cliquons sur le bouton + Installer un nouveau thème. L’installation se déroule de la même façon que pour un module. Nous insérons donc l’URL dans le champ prévu à cet effet et nous cliquons sur Installer.

Figure 8–1 Installer un thème

Dans le bas de la page d’accueil de l’apparence, nous trouvons la liste des thèmes désactivés, c’est-à-dire ceux qui sont installés mais ne sont pas utilisés. Par défaut, un seul thème peut être utilisé sur notre site.


Figure 8–2 Thèmes désactivés

Cliquons sur le lien Activer et choisir par défaut correspondant à Zen. Ce dernier est désormais le thème par défaut sur notre site. Revenons à notre page d’accueil ; elle a changé d’aspect.

Figure 8–3 Page d’accueil avec le thème Zen installé et activé

Cette page d’accueil est très blanche, mais présente l’énorme avantage, si la taille d’écran change, d’adapter la présentation du contenu. Les figures suivantes montrent par exemple à quoi ressemble le site depuis un écran de tablette tactile et sur un smartphone.


Figure 8–4 Accueil en taille d’écran tablette

Figure 8–5 Accueil Zen sur un smartphone

Certains blocs de contenu ont disparu ; l’affichage du site s’adapte correctement à la taille de l’écran. C’est le principe de base du Responsive Design. Si le Responsive sous la forme de thèmes utilisant les media queries ne gère pas la problématique de l’adaptation du contenu aux écrans et aux types d’informations cherchées, il évite à l’utilisateur de passer son temps à zoomer et à faire défiler les contenus. Création d’un thème à partir de Zen Profitons de cette installation vierge de Zen pour comprendre comment nous pouvons


créer un thème de toute pièce. Nous allons utiliser pour ce faire le principe des starterkits présents dans plusieurs thèmes Drupal. Ceux-ci nous permettent de ne pas partir d’une feuille blanche lors de la création de notre thème. Si nous regardons l’arborescence du dossier contenant le thème Zen, nous voyons qu’il contient un sous-dossier nommé STARTERKIT. Commençons donc par copier ce dossier et l’intégralité de ses fichiers vers notre répertoire /sites/all/themes. BONNE PRATIQUE Copie du thème En copiant et modifiant notre sous-thème dans un répertoire de notre site, nous facilitons la maintenance du thème Zen. Lorsque la communauté fournit des mises à jour de celui-ci, nos modifications ne sont pas écrasées. Tout comme pour les modules, prenons tout de suite de bonnes habitudes pour ne pas perdre notre travail.

Nous continuons en renommant notre dossier. Nous avons choisi de l’appeler bookdev, qui sera le nom de notre thème. Nous avons donc deux dossiers à la racine de sites/all/themes : Zen ; bookdev. Nous allons désormais travailler exclusivement dans le dossier bookdev. À l’intérieur se trouve un fichier nommé STARTERKIT.info.txt, que nous renommons bookdev.info pour déclarer notre thème Drupal. Nous allons y préciser le nom du thème, les feuilles de styles et les codes JavaScript à utiliser, ainsi que la description des divers blocs le composant. ATTENTION Données en cache Drupal 7 stocke en cache les données du .info. Si nous modifions quelque chose dans ce fichier, nous devons rafraîchir le cache, simplement en visitant la page Admin/Apparence.

Fichier bookdev.info : description générale ; Le nom, la description et la figure définis ici ; sont utilisés pour décrire le thème dans la ; page Admin/Apparence. screenshot = screenshot.png name = BookDev description = Thème créé pour le livre Drupal Avancé à partir du starterkit de Zen.

; Ce thème est compatible avec le core Drupal 7. ; Il s’agit d’un sous-thème de Zen. core = 7.x base theme = zen

Cette première partie nous donne des informations sur le thème, comme son nom, sa


description ou le fait qu’il soit un sous-thème de Zen compatible avec Drupal 7. Dans la seconde partie du fichier .info, nous déclarons les feuilles de styles CSS (stylesheets en anglais) que nous allons utiliser. Celles-ci se trouvent dans le sous-dossier CSS de notre répertoire bookdev. Nous pouvons agir de trois façons avec les lignes stylesheet : ajouter une nouvelle CSS à notre thème, simplement en précisant son nom ; remplacer une feuille de styles d’un module ou du core Drupal, en fournissant une CSS de même nom ; supprimer une feuille de styles existante, en déclarant son nom mais sans fournir de fichier . ALLER PLUS LOIN CSS et media queries CSS 2.1 media types : http://www.w3.org/TR/CSS21/media.html#media-types CSS 3 media queries : http://www.w3.org/TR/css3-mediaqueries/

Fichier .info : déclaration des CSS ; Les déclarations sont de la forme : ; stylesheets[MEDIA][] = FILE ; où FILE est le nom de la feuille de styles à ; ajouter, remplacer ou supprimer. ; et MEDIA est un type de terminal ou une media query. ; Les principaux types sont "all", "screen", "print" ; et "handheld". ; Une media query classique est ; "screen and (max-width: 320px)". ; ; D’abord, nous supprimons les styles système des menus ; et messages puisque Zen a les siens. stylesheets[all][] = system.menus.css stylesheets[all][] = system.messages.css stylesheets[all][] = system.theme.css ; Ensuite, nous ajoutons nos propres feuilles de styles. stylesheets[all][] = css/styles.css

ALLER PLUS LOIN Feuilles de styles conditionnelles La prise en charge des feuilles de styles conditionnelles a été supprimée de Zen 7.x-5.x : ; stylesheets-conditional[lte IE 8][all][] = css/ie8.css En remplacement, il est recommandé d’ajouter des classes HTML particulières dans des commentaires conditionnels, comme .lt-ie9, .lt-ie8, .lt-ie7. Pour plus d’information : http://paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ Si nous voulons malgré tout utiliser des feuilles de styles conditionnelles, il nous faut installer


un autre module : https://drupal.org/project/conditional_styles

Dans la partie suivante, nous déclarons les fichiers JavaScript nécessaires à notre thème. Ceux-ci sont placés dans le sous-dossier js. Ici, script.js n’est pas appelé puisque la ligne qui le fournit est commentée. Fichier .info : déclaration des fichiers JavaScript ; Ajout éventuel de codes JavaScript à notre thème ; scripts[] = js/script.js

Dans la partie suivante, nous définissons les régions du thème dans lesquelles nous placerons nos blocs dans l’administration de Drupal. Fichier .info : définition des régions du thème ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

Cette section liste les régions définies par défaut dans les fichiers page.tpl.php and maintenance-page.tpl.php de Zen. Le nom machine de la région est entre crochets. Le texte placé derrière le signe = est une courte description utilisée dans la page admin/structure/blocks page. Le contenu de la région est fourni via les variables $page['MACHINE-NAME'] dans page.tpl.php et $MACHINE-NAME dans maintenance-page.tpl.php. Par exemple, avec la ligne suivante dans le fichier .info : regions[header_top] = Header top nous écrirons <?php print render($page['header_top']); ?> dans page.tpl.php: et <?php print $header_top; ?> dans maintenance-page.tpl.php.

regions[header] = Header regions[navigation] = Navigation bar regions[highlighted] = Highlighted regions[help] = Help regions[content] = Content regions[sidebar_first] = First sidebar regions[sidebar_second] = Second sidebar regions[footer] = Footer regions[bottom] = Page bottom ; Les régions page_top et page_bottom sont nécessaires ; au bon fonctionnement de html.tpl.php. ; Il ne faut donc pas les effacer. regions[page_top] regions[page_bottom]

= Page top = Page bottom

Même si page_top et page_bottom n’apparaissent pas dans la page d’administration des blocs, elles sont obligatoires pour l’ensemble des sous-thèmes Zen puisque c’est dans ces régions que sont notamment déclarées l’inclusion des fichiers et d’autres fonctions utiles


via le fichier html.tpl.php (nous y reviendrons plus loin). Viennent ensuite la définition des fonctionnalités activées dans la page générale de réglage des thèmes, puis les déclarations des paramètres spécifiques à Zen et ses sous-thèmes. ALLER PLUS LOIN Éléments visibles sur la page Admin/Apparence Guide pour les thèmes Drupal 7 : https://drupal.org/node/171205#features

Fichier .info : fonctionnalités de réglage du thème ; ; ; ;

De nombreux éléments de la page peuvent être affichés sur la page Admin/Apparence ou en être supprimés. Ils sont déclarés à l’aide du mot-clé features. Pour supprimer un élément dont nous n’avons pas l’usage, il suffit de ne pas le lister.

features[] features[] features[] features[] features[] features[] features[] features[]

= = = = = = = =

logo name slogan node_user_picture comment_user_picture favicon main_menu secondary_menu

; Valeurs par défaut des éléments de theme-settings.php. settings[zen_breadcrumb] = yes settings[zen_breadcrumb_separator] = ' › ' settings[zen_breadcrumb_home] = 1 settings[zen_breadcrumb_trailing] = 0 settings[zen_breadcrumb_title] = 0 settings[zen_skip_link_anchor] = main-menu settings[zen_skip_link_text] = Jump to navigation settings[zen_html5_respond_meta][] = respond settings[zen_html5_respond_meta][] = html5 settings[zen_html5_respond_meta][] = meta settings[zen_rebuild_registry] = 1 settings[zen_wireframes] = 0

Nous avons ensuite la possibilité de définir notre thème en tant que thème d’administration pour permettre l’apparition des liens contextuels. Fichier .info : déclaration d’un thème d’administration ; Pour déclarer en tant que thème d’administration, ; décommenter la ligne suivante. ;settings[shortcut_module_link] = 1

Enfin, Zen propose d’intégrer des modèles Panels directement dans le thème. Panels est un module contrib, qui sert à définir graphiquement différents modèles d’affichage (layouts) pour nos pages via l’interface graphique (nous y reviendrons dans la partie suivante).


ALLER PLUS LOIN Modèles Panels https://drupal.org/node/495654

Fichier .info : insertion de modèles Panels ; Pour insérer un modèle Panels (layout), ; décommenter la ligne suivante. ;plugins[panels][layouts] = panels-layouts

Une fois notre fichier .info défini, nous devons encore remplacer, cette fois dans le fichier template.php, chaque occurrence de STARTERKIT par le nom de notre thème. Ce fichier de template nous permet de déclarer des fonctions spécifiques pour modifier le comportement du fil d’ariane (breadcrumb) ou surcharger des fonction de preproccess sur des nœuds, des blocs ou d’autres éléments fournis par Drupal (voir le chapitre 3 « Les modules » pour en savoir plus). Nous devrons également remplacer le mot STARTERKIT par bookdev dans le fichier themesettings.php. Ce dernier définit les réglages de notre thème (modifie la couleur des liens, par exemple). Il ne nous reste plus qu’à nous rendre dans l’interface de Drupal, aller dans Apparence et y définir notre thème comme celui par défaut. La figure suivante montre le résultat sur notre page d’accueil.

Figure 8–6 Page d’accueil avec le thème Bookdev par défaut

C’est logiquement la même page que celle que nous utilisions avec le thème Zen. L’avantage est que désormais nous allons pouvoir personnaliser ce thème. Les différents fichiers qui composent un thème Commençons par examiner les feuilles de styles qui se trouvent dans le dossier CSS de notre répertoire bookdev.


Figure 8–7 Arborescence du dossier CSS

Ce dossier comprend de nombreux fichiers. Dans le dossier layouts, se trouvent les CSS qui permettent de basculer entre un site en Responsive Design et un site fixe. Les feuilles de styles du dossier components définissent l’aspect d’un ensemble d’éléments indépendamment du layout choisi. Les feuilles de styles à la racine de notre site sont celles que nous pouvons personnaliser. Nous allons principalement apporter des modifications au fichier style.css. En ajoutant les quelques lignes suivantes, nous arrivons déjà à un résultat un peu plus graphique. Fichier style.css : premières modifications d’affichage body { background : none repeat scroll 0 0 #232323; color : #FFFFFF; } a { text-decoration: none; color : #666666; } #header { background : #F5F5F5; } .container { max-width : 1200px; margin : auto; color : #333333; } #name-and-slogan { margin-right: 2%; } #navigation ul li { display : block; float : left; font-size :1.2em;


text-align : center; text-transform: uppercase; } #navigation ul li a { padding : 30px; } #main { background : none repeat scroll 0 0 #FFFFFF; }

Voici le résultat que nous obtenons.

Figure 8–8 Page d’accueil avec une légère personnalisation CSS

Il reste encore du travail, mais l’objet n’est pas ici d’apprendre le langage CSS. C’est à nous d’habiller le site en fonction de nos envies et des contraintes graphiques que nous (ou nos clients) aurons fixées. Les autres fichiers et dossiers du thème sont les suivants : images : icônes et images utilisées par le thème ; images-source : fichier original utilisé pour la capture d’écran ; js : fichiers JavaScript des fonctions utilisées par notre thème ; sass et sass-extensions : fichiers nécessaires pour utiliser Zen ou un sous-thème avec le framework Sass ; Templates : ensemble des fichiers de templates qui définissent le rendu de nos différentes pages (voir section suivante) ; Config.rb : nécessaire pour utiliser Sass et Compass ; favicon.ico : favicon qui apparaît dans le navigateur ; logo.png : logo utilisé par défaut quand il n’est pas surchargé par l’interface d’administration de Drupal ; README.txt : informations utiles pour les personnes utilisant et modifiant le thème ; screenshot.png : aperçu du thème, que l’on retrouve lors du choix du thème dans l’UI de Drupal ; template.php : fonctions spécifiques de notre thème (voir ci-après). En plus de modifier le style de notre site, attardons-nous sur le système de templates de Drupal et sur les fonctions proposées dans le fichier template.php.


Partons d’un exemple. Nous souhaitons obtenir une région supplémentaire au-dessus de notre en-tête (header). Elle permettra de retrouver notre slogan et notre logo, un formulaire de connexion pour les anonymes et le menu utilisateur pour les personnes déjà authentifiées. Pour ce faire, commençons par déclarer notre nouvelle région dans bookdev.info en ajoutant la ligne suivante dans le bloc contenant nos régions. Fichier bookdev.info : déclaration d’une nouvelle région regions[top-header]

= Top Header

Si nous allons voir l’aperçu de la présentation des blocs (via Structures>Blocs, puis en cliquant sur le lien Aperçu des régions des blocs), voici ce que nous devrions obtenir.

Figure 8–9 Aperçu des régions des blocs

Notre nouvelle région n’est pas encore visible. Pour qu’elle apparaisse, il faut préciser, dans les fichiers de template, à quel endroit cette région se trouve. Les deux fichiers de templates indispensables à tout thème sont html.tpl.php et page.tpl.php. Le premier contient la déclaration de doctype ainsi que l’appel aux différents autres fichiers nécessaires (comme les feuilles de styles, les fichiers .js et les autres fichiers de templates). Le second contient ce qui se trouve dans la balise body de notre page HTML. Pour débuter, nous copions ces deux fichiers depuis le répertoire /sites/all/themes/zen/templates vers /sites/all/themes/bookdev/templates. Pour que notre nouvelle région (Top Header) apparaisse, nous modifions le fichier page.tpl.php de bookdev comme suit. ALLER PLUS LOIN Fichier page.tpl.php https://drupal.org/node/1728148

Fichier page.tpl.php : déclaration d’une nouvelle région <?php /**


* @file * Renvoie le code HTML d’une page Drupal. * * Documentation complète disponible en ligne : * https://drupal.org/node/1728148 * @see */ ?> <div id="page"> <header class="header" id="header" role="banner"> <div class="container"> <?php print render($page['top-header']); ?> <?php if ($logo): ?> <?php $logo_view="<img src='$logo' alt='".t('Home')."' class='header__logoimage' />"; print l ($logo_view, '', array ( 'attributes' => array ( 'title' => t('Home'), 'rel' => 'home', 'class'=>'header__logo', 'id' => 'logo' ), 'html' => TRUE ) ); ?> <?php endif; ?> <?php if ($site_name || $site_slogan): ?> <div class="header__name-and-slogan" id="name-and-slogan"> <?php if ($site_name): ?> <h1 class="header__site-name" id="site-name"> <?php print l ($site_name, '', array ( 'attributes' => array ( 'title' => t('Home'), 'rel' => 'home', 'class'=>'header__site-link', 'id' => 'logo' ), 'html' => TRUE ) ); ?> </h1> <?php endif; ?> <?php if ($site_slogan): ?> <div class="header__site-slogan" id="site-slogan"><?php print $site_slogan; ?></div> <?php endif; ?> </div> <?php endif; ?>


<?php if ($secondary_menu): ?> <nav class="header__secondary-menu" id="secondary-menu" role="navigation"> <?php print theme('links__system_secondary_menu', array( 'links' => $secondary_menu, 'attributes' => array( 'class' => array('links', 'inline', 'clearfix'), ), 'heading' => array( 'text' => $secondary_menu_heading, 'level' => 'h2', 'class' => array('element-invisible'), ), )); ?> </nav> <?php endif; ?> <div id="navigation"> <?php if ($main_menu): ?> <nav id="main-menu" role="navigation" tabindex="-1"> <?php // Cette partie du code est difficile à modifier. // Nous recommandons de désactiver le "Main menu" // dans les réglages du sous-thème, de supprimer ce // bloc de code PHP et d’utiliser à la place le // module "Menu block" : // @see https://drupal.org/project/menu_block print theme('links__system_main_menu', array( 'links' => $main_menu, 'attributes' => array( 'class' => array('links', 'inline', 'clearfix'), ), 'heading' => array( 'text' => t('Main menu'), 'level' => 'h2', 'class' => array('element-invisible'), ), )); ?> </nav> <?php endif; ?> <?php print render($page['navigation']); ?> </div> <?php print render($page['header']); ?> </div> </header> ... Nous laissons la suite du fichier telle qu’elle est définie.

BONNE PRATIQUE Nous avons remplacé la balise 'href' en HTML par la fonction l() de l’API Drupal pour


respecter les préconisations du CMS.

Une fois ceci fait, la nouvelle région apparaît bien et nous pouvons positionner notre bloc d’identification à l’intérieur.

Figure 8–10 Bloc de connexion dans la région Top Header

Si nous nous déconnectons, voilà ce que cela donne.

Figure 8–11 Bloc de connexion dans le Top Header-Aperçu

Pour supprimer le titre, il faut aller configurer le bloc (Structure>Blocs>Connexion utilisateur>Configurer) et entrer <none> dans le champ titre. Nous allons ensuite réordonner les éléments pour que les liens de création des comptes et de demande de mot de passe apparaissent après le bouton Connecter. Pour cela, nous ajoutons deux fonctions dans le fichier template.php.


Figure 8–12 Configuration du bloc Connexion utilisateur

Fichier template.php : ajout de fonctions pour déplacer des liens function bookdev_theme(&$existing, $type, $theme, $path) { $hooks['user_login_block'] = array( 'template' => 'templates/user_login', 'render element' => 'form', ); return $hooks; } function bookdev_preprocess_user_login_block(&$variables) { $variables['username'] = drupal_render($variables['form']['name']); $variables['password'] = drupal_render($variables['form']['pass']); $variables['submit'] = drupal_render($variables['actions']['submit']); $variables['links'] = drupal_render($variables['form']['links']); $variables['rendered'] = drupal_render_children($variables['form']); // Obligatoire pour pouvoir se loguer, insère tous les éléments invisibles du formulaire mais nécessaires à l’authentification }

La première fonction déclare le template utilisé. Nous indiquons ici à Drupal que pour user_login_block, ce sera le fichier user-login.tpl.php qui se trouve dans le dossier templates. La deuxième fonction nous permet de récupérer chaque morceau du formulaire de manière séparée. En effet, à l’origine, les éléments sont tous générés en un seul bloc via un drupal_render. Ici, nous demandons à Drupal de découper drupal_render en plusieurs variables correspondant aux différentes parties de notre formulaire. Il nous reste alors à créer notre fichier user-login.tpl.php dans lequel nous plaçons le code suivant. Fichier user-login.tpl.php <div class="bookdev-login-block"> <?php print $username; print $password;


print $submit; print $rendered; print $links; ?> </div>

Ici, nous plaçons les liens pour créer un nouveau compte et demander un nouveau mot de passe après le bouton de soumission.

Figure 8–13 Bloc de connexion utilisateur avec les fonctions de thème

Ajoutons un peu de CSS pour mettre en forme les trois premières parties du formulaire : #block-user-login label, .form-item, .form-actions { display : inline; }

Nous voilà proches du résultat souhaité.

Figure 8–14 Bloc de connexion utilisateur en ligne

Il nous reste à remplacer les liens par des images avec des infobulles et à les mettre sur la même ligne que le reste du formulaire. Dans le fichier user-login.tpl.php, nous remplaçons la ligne print $links par le code suivant. Fichier user-login.tpl.php : remplacement des liens par des images <div id="login-links"> <?php $img_new="<img src='".base_path() . path_to_theme()."/images/new-user.png' />"; print l ( $img_new, '/user/register', array ( 'attributes' => array ( 'title' => t('Se créer un compte'), ), 'html' => TRUE ) );


print " | "; $img_pass="<img src='".base_path() . path_to_theme()."/images/key.png' />"; print l ($img_pass, '/user/password', array ( 'attributes' => array ( 'title' => t('Demander un nouveau mot de passe'), ), 'html' => TRUE ) ); ?> </div>

Fichier style.css : ajout de l’identifiant du div et d’une taille pour nos icônes #block-user-login label, .form-item, .form-actions, #login-links { display : inline; } #login-links img { height: 20px; }

Nous arrivons enfin au résultat souhaité.

Figure 8–15 Bloc de login à l’horizontale

Passons maintenant à une partie intéressante de la personnalisation du thème de Drupal : la gestion des templates. La figure suivante schématise comment une page peut être composée par différents fichiers templates.

Figure 8–16 Encapsulation des fichiers templates

Nous pouvons partir de templates génériques (page.tpl.php) et aller vers des besoins plus


spécifiques (node.tpl.php qui concerne tous les nœuds quels que soient leurs types). Nous pouvons également créer des templates pour les blocs (user-login.tpl.php) ou spécifiques à une vue particulière (views-view--les-plats-de-l-utilisateur.tpl.php). Ce système, un peu complexe de prime abord, permet de définir précisément le rendu de chaque page et chaque affichage comme on le souhaite. Pour terminer sur cette partie, nous allons construire ensemble un template de type node pour voir comment récupérer les informations et comment les utiliser. Pour faciliter la visualisation de nos modifications, nous devons forcer Drupal à relire systématiquement les fichiers tpl.php à chaque chargement de page (le temps de chargement étant donc un peu plus long, ces manipulations ne sont à faire que durant la construction des fichiers tpl.php). Rendons-nous dans Configuration>Devel settings. En bas de la fenêtre, nous trouvons une case à cocher Reconstruire le registre de thème à chaque chargement de page. Cochons-la et cliquons sur Enregistrer la configuration.

Figure 8–17 Reconstruire le registre de thème avec Devel

Une fois ceci fait, nous commençons par créer un fichier node.tpl.php dans notre répertoire /sites/all/themes/bookdev/templates/. Il contiendra les différents éléments à afficher pour notre nœud. ALLER PLUS LOIN Éléments disponibles https://drupal.org/node/1728164

Dans ce fichier, nous définissons une classe avec node et le numéro du nœud (pour le cas où nous en aurions besoin en CSS ou en JS) et nous affichons le titre avec un lien sur le nœud dans une balise <header>. Fichier node.tpl.php : définition d’une classe pour le nœud <?php /** * @file * Renvoie le code HTML d’un nœud. * * Pour plus d’information sur ce fichier : * @see https://drupal.org/node/1728164 */ ?> <article class="node-<?php print $node->nid; ?> <?php print $classes; ?> clearfix"<?php print $attributes; ?>>


<header> <h2> <?php print l ($title, $node_url, array ( 'attributes' => array ( 'title' => t($title), ), 'html' => TRUE ) ); ?> </h2> </header>

Enfin, nous affichons le contenu du nœud et nous fermons la balise <article>. Fichier node.tpl.php : affichage du nœud <?php // Nous cachons les commentaires et les liens // pour les afficher plus tard. print 'mon template de nœud' ; print render($content); ?>

</article>

La figure suivante montre le résultat obtenu.

Figure 8–18 Exemple de nœud avec le début d’un node.tpl.php

Le titre apparaît donc deux fois, puisqu’il est déjà appelé par page.tpl.php. Nous devons donc le supprimer. Nous allons également faire apparaître une div spécifique pour le nom de l’auteur et son image. Nous supprimons aussi la phrase que nous avions insérée manuellement. Fichier node.tpl.php : cacher le titre


<article class="node-<?php print $node->nid; ?> <?php print $classes; ?> clearfix"<?php print $attributes; ?>> <div id="node-author"> <?php print $user_picture; print $name; ?> </div> <?php // Nous cachons les commentaires et les liens // pour les afficher plus tard. print render($content); ?>

</article>

Voilà le résultat obtenu :

Figure 8–19 Template d’un nœud avec l’auteur et sa photo

Un peu de CSS nous permet de placer l’auteur et sa photo dans un bloc coloré sur la droite du texte principal. Fichier style.css #node-author { width : 30%; float : right; border : solid 1px #0099FF; border-radius: 3px; background: #99CCFF; }


Figure 8–20 Template d’un nœud avec un bloc auteur

Pour détailler les champs disponibles, Devel nous permet d’afficher dans un tableau le contenu de $content, en ajoutant la ligne suivante dans le fichier node.tpl.php : dpm($content);

Figure 8–21 Tableau du contenu de $content dans un template de nœud

Ce tableau montre les différents éléments de $content. Nous pouvons ainsi réordonner les différents éléments comme suit en leur ajoutant des div et des classes spécifiques. Fichier node.tpl.php : réordonner le contenu <?php /** * @file * Renvoie le code HTML d’un nœud. * * Pour plus d’information sur ce fichier : * @see https://drupal.org/node/1728164 */ ?> <article class="node-<?php print $node->nid; ?> <?php print $classes; ?> clearfix"<?php print $attributes; ?>> <div id="node-author"> <?php print $user_picture; print $name; ?> </div>


<div id="body-node"> <?php print render($content['body']); ?> </div> <div id="node-og-audience"> <?php print render($content['og_group_ref']); ?> </div> <div id="comment-node"> <?php print render($content['comments']); ?> </div> <div id="node-links"> <?php print render($content['links']); ?> </div>

</article>

La figure suivante montre le résultat.

Figure 8–22 Affichage d’un nœud avec le template node.tpl.php

Nous avons présenté les bases de la création de template. Il ne faut pas hésiter à examiner les fichiers fournis par Zen pour trouver plus d’informations et à lire la documentation sur drupal.org.

Proposer des webservices pour un site ou une


application mobile Une autre approche pour le mobile consiste à se dire que nous allons faire un site spécifique et/ou une ou plusieurs applications mobiles. Cette solution a pour immense avantage de profiter des spécificités du mobile comme les fonctions de géolocalisation ou d’enregistrement de contacts, mais présente l’inconvénient d’augmenter considérablement le temps et donc le coût de réalisation. Dans certains projets (en fonction des objectifs, des cibles, etc.), cela s’avère indispensable ; dans ce cas-là, Drupal permet de récupérer le contenu et d’interagir avec notre site en utilisant des webservices. Un webservice est la possibilité pour une application externe de se connecter à un site web pour en récupérer des informations (des contenus par exemple), ou lui en transmettre (ajout d’un article sur le site).

Utiliser le module Services Pour proposer des flux sur lesquels les applications externes se connecteront, nous utiliserons le module Services (et Libraries, dont il dépend). MÉTHODE Installer le module Services par l’interface Télécharger les modules Services et Libraries : https://drupal.org/project/services https://drupal.org/project/libraries Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver les modules dans la liste et les activer.

MÉTHODE Installer le module Services en ligne de commande avec Drush $ drush dl services libraries $ drush en -y services libraries

Commençons par installer et activer les modules suivants : Libraries ; Services ; REST Server. ALLER PLUS LOIN Architecture REST Le troisième module sert à transformer Drupal en un serveur (fournisseur) de webservices REST. Le site suivant précise ce qu’est le style d’architecture REST : http://fr.wikipedia.org/wiki/Representational_State_Transfer

Rendons-nous ensuite dans l’interface d’administration de Services via Admin>Structure>Services. Nous arrivons alors sur la liste des services disponibles.


Figure 8–23 Liste des services disponibles par défaut

Ajoutons un service. Pour cela, nous cliquons sur Ajouter. Puis nous renseignons les différentes informations, la principale à définir étant le endpoint, c’est-à-dire le chemin à partir duquel Drupal sera capable de comprendre que c’est un webservice et non une page du site, et nous renverra les bonnes informations.

Figure 8–24 Ajout d’un service

Une fois le service créé, nous pouvons activer certaines fonctionnalités comme l’affichage des nœuds ou la connexion utilisateur. Elles sont proposées par défaut par le module Services et concernent principalement les fonctionnalités natives de Drupal. Ainsi, nous pourrons afficher un nœud ou même en ajouter un facilement. Nous retrouvons ces fonctionnalités dans la liste des actions correspondant au service que nous venons de créer.

Figure 8–25 Liste des services existants

Commençons par gérer les ressources disponibles pour ce service.


Figure 8–26 Liste des ressources d’un service

Nous pouvons choisir dans cette liste quels seront les services disponibles. Nous sélectionnons ici la possibilité de retrouver un nœud pour afficher les restaurants dans notre site mobile.

Figure 8–27 Ressource : node retrieve et son alias

Nous pouvons à présent appeler notre webservice depuis un site mobile, par exemple avec l’adresse http://notresite/services/node/4. La fin de l’adresse est composée de <notre endpoint>/<l’alias que nous avons défini>/<le numéro du nœud à consulter>. Si nous ne précisons pas de format, le contenu de notre nœud est fourni en XML.


Figure 8–28 Contenu du nœud en XML

Nous avons donc la possibilité d’appeler nos nœuds directement depuis un autre site ou depuis un site dédié au mobile. Par exemple, pour afficher un nœud Drupal dans une page HTML 5, voici une méthode à suivre après avoir défini le service et les ressources associées. Nous créons une page index.html. Fichier index.html <html> <head> <link rel="stylesheet" href="mobile.css" type="text/css" /> <link rel="stylesheet" href="jquery-mobile.css" type="text/css" /> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="jquery-mobile.js"></script> <script type="text/javascript" src="iphone.js"></script> <meta name="viewport" content="user-scalable=no, width=device-width" /> <title>Maquette application agora</title> </head> <body> <h1>Ma page restaurant</h1> <div data-role="page" id="home" class="pages" <div data-role="content" id="content"> Le contenu </div> </div> </body> </html>


Dans cette page, et puisque nous nous appuyons sur jQuery et sa version mobile, nous devons charger les fichiers nécessaires. Sans appel au webservice, la page n’affiche rien d’intéressant.

Figure 8–29 Page index HTML statique (sans appel au webservice)

Nous allons donc lui ajouter un script JavaScript pour qu’elle aille chercher l’article sur notre Drupal. Nous créons pour cela un fichier bookdev.js que nous intégrons dans notre index.html. Appel à bookdev.js dans index.html <script type="text/javascript" src="bookdev.js"></script>

Fichier bookdev.js <script> $(document).ready(function() { $.getJSON ("http://bookdev.hello-design.fr/?q=services/node/4.json", function(data) { console.log(data); }); }); </script>

Notre page peut désormais appeler le nœud choisi. Pour se connecter avec Services Pour se connecter depuis un webservice en dehors des règles de sécurité élémentaires (créer un utilisateur spécifique, un rôle spécifique et lui donner des droits limités), voici les étapes à suivre : Appeler system/connect pour obtenir un token de session (sessid). Appeler user/login en passant en paramètre le token obtenu à l’étape précédente. Sans token, l’utilisateur ne pourra pas se connecter.

Développer des ressources supplémentaires pour Services Maintenant que nous savons comment utiliser les webservices et leurs ressources


associées, voyons comment ajouter notre entité Menus comme ressource disponible. Commençons par nous assurer que les fonctions de CRUD (Create, Retrieve, Update, Delete) nécessaires au fonctionnement des webservices sont présentes. Pour cela, ouvrons le fichier menus.module et ajoutons (si elles ne sont pas déjà présentes) les fonctions suivantes. Fichier menus.module /** * Obtenir un menu par son id. * * @param int $id * @return object */ function menus_get_menu($id) { return db_fetch_object(db_query("SELECT * FROM {menus} WHERE id=:id", array( ':id' => $id, ))); } /** * Écrire un menu dans la base de données * * @param object $menu * @return void */ function menus_write_menu($menu) { $primary_key = !empty($menu->id) ? array('id') : NULL; drupal_write_record('menus', $menu, $primary_key); } /** * Supprimer un menu de la base de données * * @param int $id * @return void */ function menus_delete_menu($id) { db_query("DELETE FROM {menus} WHERE id=:id", array( ':id' => $id, )); } ?>

Nous sommes désormais certains d’avoir les fonctions nécessaires à l’ajout de ressources. De plus, ces fonctions CRUD sont également utiles pour rendre notre module compatible avec d’autres modules Drupal. Écrivons maintenant un module spécifique, qui se nommera menus_ressources ; commençons par sa description. Fichier menus_ressource.info


name = Menus Resource description = Integration des menus en tant que ressources package = Bookdev dependencies[] = services core = 7.x

Ensuite, nous créons le fichier menus_ressource.module dans lequel nous déclarons l’ensemble des fonctions utilisées et l’endroit où elles sont stockées. Pour cela, nous utilisons le tableau 'file' => array('type' => 'inc', 'module' => 'menus_ressource') exprimant que les fonctions se trouvent dans le fichier menus_ressource.inc, à créer par la suite. Fichier menus_ressource.module : fonctions du service <?php /** * Définition de hook_services_resources(). */ function menus_ressource_services_ressources() { return array( 'menus' => array( 'retrieve' => array( 'help' => 'Retrouver un menu', 'file' => 'menus_ressource.inc', 'callback' => '_menus_ressource_retrieve', 'access callback' => '_menus_ressource_access', 'access arguments' => array('view'), 'access arguments append' => TRUE, 'args' => array( array( 'name' => 'id', 'type' => 'int', 'description' => 'L\'id du menu à récupérer', 'source' => array('path' => '0'), 'optional' => FALSE, ), ), ), 'create' => array( 'help' => 'Créer un menu', 'file' => 'menus_ressource.inc', 'callback' => '_menus_ressource_create', 'access arguments' => array('menu ressource create'), 'access arguments append' => TRUE, 'args' => array( array( 'name' => 'menu', 'description' => 'L\'objet menu', 'source' => 'data', 'optional' => FALSE, 'type' => 'array', ), ), ), 'update' => array( 'help' => 'Mettre à jour un menu', 'file' => 'menus_ressource.inc',


'callback' => '_menus_ressource_update', 'access callback' => '_menus_ressource_access', 'access arguments' => array('update'), 'access arguments append' => TRUE, 'args' => array( array( 'name' => 'id', 'type' => 'int', 'description' => 'L\'identifiant du menu à mettre à jour', 'source' => array('path' => '0'), 'optional' => FALSE, ), array( 'name' => 'data', 'type' => 'array', 'description' => 'Les données de l\'objet menu', 'source' => 'data', 'optional' => FALSE, ), ), ), 'delete' => array( 'help' => 'Supprimer un menu', 'file' => 'menus_ressource.inc', 'callback' => '_menus_ressource_delete', 'access callback' => '_menus_ressource_access', 'access arguments' => array('delete'), 'access arguments append' => TRUE, 'args' => array( array( 'name' => 'nid', 'type' => 'int', 'description' => 'L\'id du menu à supprimer', 'source' => array('path' => '0'), 'optional' => FALSE, ), ), ), 'index' => array( 'help' => 'Trouver la liste des menus', 'file' => 'menus_ressource.inc', 'callback' => '_menus_ressource_index', 'access arguments' => array('access content'), 'args' => array(array( 'name' => 'page', 'type' => 'int', 'description' => '', 'source' => array( 'param' => 'page', ), 'optional' => TRUE, 'default value' => 0, ), array( 'name' => 'parameters', 'type' => 'array',


'description' => '', 'source' => 'param', 'optional' => TRUE, 'default value' => array(), ), ), ), ), ); } ?>

Ajoutons les permissions liées au module. Fichier menus_ressource.module : permissions <?php /** * Définition de hook_perm(). */ function menus_ressource_perm() { return array( 'menus ressource create', 'menus ressource view any menu', 'menus ressource view own menus', 'menus ressource edit any menu', 'menus ressource edit own menus', 'menus ressource delete any menu', 'menus ressource delete own menus', ); } ?>

Nous créons ensuite le fichier menus_ressource.inc qui va contenir les fonctions appelées en callback dans le fichier .module. Commençons avec la ressource de création de menus. Fichier menus_ressource.inc : création de menus <?php /** * Callback pour créer des menus. * * @param object $data * @return object */ function _menus_ressource_create($data) { global $user; unset($data->id); $data->uid = $user->uid; $data->created = time(); $data->modified = time(); if (!isset($data->subject)) { return services_error('Titre du menu manquant', 406); } if (!isset($data->menu)) { return services_error('Corps du menu manquant', 406);


} menus_ressource_write_menu($data); return (object)array( 'id' => $data->id,'uri' => services_ressource_uri(array('menus', $data>id)), ); } ?>

Nous vérifions l’existence d’un titre et du contenu principal du menu ; si les deux sont présents, nous enregistrons le nouveau menu. Pour la fonction de mise à jour, le fonctionnement est quasiment identique, les vérifications en moins (puisqu’elles ont déjà été faites lors de la création). Fichier menus_ressource.inc : mise à jour de menus <?php /** * Callback pour mettre à jour les menus. * * @param int $id * @param object $data * @return object */ function _menus_ressource_update($id, $data) { global $user; $menu = menus_ressource_get_menu($id); unset($data->created); $data->id = $id; $data->uid = $menu->uid; $data->modified = time(); menus_ressource_write_menu($data); return (object)array( 'id' => $id, 'uri' => services_ressource_uri(array('menus', $id)), ); } ?>

Les deux fonctions suivantes sont très simples, puisqu’elles se contentent de passer l’ID en paramètre et d’appeler les fonctions définies précédemment dans menus.module. Fichier menus_ressource.inc : recherche et suppression de menus <?php /** * Callback pour retrouver un menu. * * @param int $id * @return object */ function _menus_ressource_retrieve($id) { return menus_ressource_get_menu($id);


} /** * Callback pour supprimer un menu. * * @param int $id * @return object */ function _menus_ressource_delete($id) { menus_ressource_delete_menu($id); return (object)array( 'id' => $id, ); } ?>

Nous ajoutons enfin la fonction d’index pour afficher tous les menus créés par l’utilisateur connecté. Dans le fichier .module, nous avons spécifié des arguments qui nous permettraient d’ajouter un filtre ou une pagination sur l’index. Ces arguments ne sont pas exploités dans cette version simplifiées de l’index.

Fichier menus_ressource.inc : fonction d’index simple <?php /** * Callback pour lister les menus. * * @param int $page * @param array $parameters * @return array */ function _menus_ressource_index($page, $parameters) { global $user; $menus = array(); $res = db_query("SELECT * FROM {menus} WHERE uid=:uid ORDER BY modified DESC", array( ':uid' => $user->uid, )); while ($menu = db_fetch_object($res)) { $menus[] = $menu; } return $menus; } ?>

Nous avons terminé de déclarer les fonctions dans le fichier inclus. Il nous reste à nous occuper des fonctions liées aux permissions appelées via les access callback lors de la déclaration des ressources. Ces fonctions sont à ajouter au fichier menus_ressource.module. Fichier menus_ressource.module : fonctions de permissions


<?php /** * Access callback pour la ressource menus. * * @param string $op * L'action qui va être réalisée. * @param array $args * Les arguments à fournir au callback. * @return bool * Si l'accès est donné ou non. */ function _menus_ressource_access($op, $args) { global $user; $access = FALSE; switch ($op) { case 'view': $menu = menus_ressource_get_menu($args[0]); $access = user_access('menus ressource view any menu'); $access = $access || $menu->uid == $user->uid && user_access('menus ressource view own menus'); break; case 'update': $note = menus_ressource_get_menu($args[0]->id); $access = user_access('menus ressource edit any menu'); $access = $access || $menu->uid == $user->uid && user_access('menus ressource edit own menus'); break; case 'delete': $menu = menus_ressource_get_menu($args[0]); $access = user_access('menus ressource delete any menu'); $access = $access || $menu->uid == $user->uid && user_access('menus ressource delete own menus'); break; } return $access; } ?>

Maintenant que nous avons écrit le module avec les ressources pour notre entité Menu, nous pouvons ajouter ces ressources aux endpoint que nous avons définis dans la partie précédente. Pour cela, retournons dans l’interface de Drupal, dans le menu Structure>Services. Sur la ligne correspondant à notre service, modifions les ressources ; nous voyons apparaître celles que nous avons créées.


Figure 8–30 Ressources rendues disponibles dans le service

Nous en avons terminé avec la création de ressources pour un webservice.

Panels/Panelizer : présentation Lorsque nous souhaitons concevoir des pages personnalisées ou complexes, avec du contenu riche, il est possible d’utiliser des modules complémentaires. Ces derniers vont briser le concept de Drupal « région/contenu/bloc » que nous pouvons connaître. Ainsi, les administrateurs ou les webmasters peuvent personnaliser directement les contenus et les rendre cohérents pour les différents types de pages.

Quels-sont ces modules ? Nous utiliserons deux modules dans cette partie. Panels est un module pour Drupal qui permet de créer l’affichage de contenu personnalisé dans la région CONTENT (voir chapitre concerné). Panelizer simplifie les possibilités de Panels et améliore ses fonctionnalités. MÉTHODE Installer les modules Panels et Panelizer par l’interface Télécharger les modules : https://drupal.org/project/panels https://drupal.org/project/panelizer Décompresser l’archive dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver les modules Panels et Panelizer dans la liste et les activer.

MÉTHODE Installer les modules Panels et Panelizer en ligne de commande avec Drush $ drush dl panels panelizer


$ drush en -y panels panelizer Le module CTOOLS est nécessaire mais il a déjà été installé dans le chapitre sur Views.

Figure 8–31 Identification des modules Panels

Construire sa propre page Définir ce qui sera personnalisé Pour configurer le module Panelizer et le rendre disponible dans l’interface administrateur, nous nous rendons à la partie configuration de celui-ci : Configuration> Rédaction de contenu>Panelizer. L’écran propose de choisir parmi les types de nœud déjà existants. Chacun d’entre eux peut être utilisé avec Panelizer si nous le souhaitons. Pour notre exemple, nous cochons la page de base avec son contenu et son accroche. Chaque ligne affichée permet de définir les différentes possibilités. Pour les afficher, il est important de cocher celles qui nous intéressent. Nous enregistrons la configuration.

Figure 8–32 Configurer Panelizer

Choisir ce qui sera disponible Pour cette étape, nous devons déterminer précisément ce qui sera disponible au niveau du type de contenu. Nous nous rendons dans Admin>Structure>Types de contenu. L’écran montre une nouvelle action par rapport à ce que nous avions coché précédemment. Il s’agit de l’action panelizer sur le type de contenu Page de base.


Figure 8–33 Nouvelle action du type de contenu

Configurons Panelizer pour le type de contenu que nous avons sélectionné. Nous obtenons l’écran suivant.

Figure 8–34 Activer les valeurs par défaut

Nous cochons les cases du menu Default settings et nous cliquons sur Enregistrer. Suite à l’activation des valeurs par défaut, l’écran propose plus d’options de configuration. De nombreuses informations concernant les contenus, les blocs, les entités, etc. sont proposées et activées par défaut. Toutes ces possibilités permettent de créer facilement une page Panelizer. Bien sûr, si nous souhaitons désactiver manuellement une option de contenu, puis décocher l’option par défaut et la configurer manuellement, c’est tout à fait possible. Enfin, l’onglet Select allowed layouts montre différents templates proposés par le module Panels. Nous retrouvons également notre template (voir chapitre concerné).

Figure 8–35 Activer les valeurs par défaut


Configuration de la présentation Configurons maintenant les éléments de contenu que nous souhaitons afficher sur notre page (par exemple, le titre, l’auteur, le contenu, les champs additionnels). Nous nous rendons à Admin>Contenu>Panelizer.

Figure 8–36 Choisir sa présentation (layout)

Nous choisissons un des layouts disponibles, que nous avons configurés précédemment (pour notre exemple, deux colonnes verticales). Configurer le contenu Il faut ensuite configurer le contenu pour l’afficher dynamiquement. Pour cela, nous renseignons les informations générales, comme le montre l’image suivante.

Figure 8–37 La configuration de base

Nous précisons un titre ainsi qu’une feuille de styles (si nécessaire). La partie basse de l’écran a été décrite dans un autre chapitre. Ici, nous avons fermé les commentaires et ajouté un lien dans le menu. Après avoir sauvegardé, le contenu a bien été créé.


Figure 8–38 Le contenu a été créé.

Deux nouveaux onglets sont apparus. Le premier permet de changer le layout (template) de la page. Le deuxième, Panel content, sert à définir le contenu de la page. Il affiche le layout que nous avons sélectionné : une colonne de contenu à gauche et une autre à droite.

Figure 8–39 Le contenu du layout

Ajouter des éléments de contenu Chaque élément de contenu se compose d’un pictogramme (représenté par une roue crantée) et se présente comme un menu si nous cliquons dessus.

Figure 8–40 Le contenu du pignon

Cliquons sur la ligne Ajouter du contenu pour obtenir un nouvel écran de paramétrage.


Figure 8–41 Ajout d’un contenu

Pour le layout de gauche, nous choisissons Widgets>Contenu récent, c’est-à-dire que nous afficherons dans cet emplacement un flux d’information. Nous sauvegardons et ajoutons le widget Connexion utilisateur sur le layout de droite. Nous en profitons pour Supplanter le titre de ce bloc comme le montre la figure suivante, c’est-à-dire que nous remplaçons le titre par défaut du bloc par un autre de notre choix.

Figure 8–42 Remplacer le titre

Lorsque nous cliquons sur le bouton Finish, nous revenons à l’interface de configuration. Voir le résultat Notre mise en page n’est pas très jolie car il s’agit de montrer la position des différents éléments de contenu qui seront affichés.


Figure 8–43 Différents éléments affichés dans la page

Nous pouvons cliquer sur le bouton Aperçu pour prévisualiser le contenu. Toutefois, nous allons plutôt nous déconnecter et voir sur le site notre page « Menu de fête ». URL : http://votresite/menu-de-fete

Figure 8–44 Résultat de la page

Le résultat montre que nous n’avons pas touché au template qui a été présenté dans l’ouvrage, mais nous retrouvons les deux éléments ajoutés, dont la partie identification a bien été remplacée par notre nouveau titre. Personnaliser les éléments de contenu Le module Panels permet de personnaliser tous les éléments, d’en ajouter et de modifier leurs emplacements en mode glisser/déposer.


Retournons sur notre page pour effectuer un certain nombre de modifications. Comme le montre la figure suivante, chaque élément du layout affiche un pictogramme (représentant une roue crantée) et propose de nombreuses fonctionnalités pour personnaliser l’élément.

Figure 8–45 Personnaliser un élément

Pour l’exemple, nous modifions deux paramètres de cet élément. Tout d’abord, nous remplaçons le titre par « Les dernières actualités ». Ensuite, nous changeons le style CSS en choisissant les coins arrondis.

Figure 8–46 Résultat des modifications de l’élément

Pour le layout de gauche, Left side, nous ajoutons l’actualité promue en page d’accueil (node>promu en page d’accueil). Pour celui de droite, Right side, nous ajoutons le menu de navigation (Menus>Navigation). Comme il se positionne en dessous de l’autre élément (Connexion utilisateur), nous pouvons glisser/déposer le titre de l’élément pour le mettre au-dessus. Puis nous enregistrons la configuration.


Figure 8–47 L’ensemble des nouveaux éléments

Observations des modifications Lorsque nous retournons sur la page d’accueil de notre site, nous voyons l’ensemble des éléments créés.

Figure 8–48 Résultat final


Les tests

9

Ce chapitre explique comment utiliser des applications externes pour effectuer des tests unitaires et fonctionnels garantissant la pérennité de notre développement de modules et de notre projet.

SOMMAIRE Utiliser le bootstrap de Drupal Faire différents types de tests : unitaires et fonctionnels Associer les tests avec PHPUnit/Selenium HQ/Drupal


Bootstrap Qu’est-ce que le bootstrap ? Le bootstrap est un script d’amorçage qui sert à lancer d’autres outils, comme Drupal. Il aide Drupal à identifier les différents modules présents et installés et à appeler les bonnes fonctions au bon moment pour afficher les pages de notre site web.

Étendre le bootstrap Comme nous allons utiliser un peu plus loin des applications externes pour effectuer nos tests, nous devons étendre le programme d’amorçage bootstrap de Drupal, pour le rendre compatible avec PHPUnit et Selenium HQ. Le script proposé dans cette partie s’insère dans les autres scripts utilisés plus loin (fichier module.test.php) ; il n’est pas prévu de l’exécuter à ce niveau.

Afin qu’il fonctionne aussi bien sous Linux que Windows ou Mac, nous réalisons le script ci-après, qui se décompose comme ceci : définition du serveur où se trouve le fichier ; déclaration du format des barres obliques en fonction de notre système d’exploitation ; recherche de la racine du dossier Drupal ; chargement du bootstrap.inc du CMS ; lancement de la fonction drupal_bootstrap. Bootstrap de Drupal <?php $_SERVER['REMOTE_ADDR'] = 'localhost' ; define('DS', DIRECTORY_SEPARATOR); define ('PATH', DS);

// ou 127.0.0.1;

define('DRUPAL_ROOT', realpath(dirname(__FILE__)) . PATH); set_include_path(DRUPAL_ROOT . get_include_path()); include_once DRUPAL_ROOT . 'includes' . DS . 'bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); ?>

Ce petit script nous sera utile pour les différents exemples de ce chapitre. La seule particularité de ce code est la constante PATH que nous devons ajuster si le module à tester se trouve dans un autre dossier.

Tests unitaires


Les tests unitaires sont utiles lorsque nous développons et ajoutons du code à travers des modules spécifiques. Pour tester notre code, il existe différents frameworks d’applications. Les plus répandus sont les suivants : SimpleTest : le framework d’origine pour Drupal, mais vieillissant ; PHPUnit : un framework moderne ; Atoum : une alternative à PHPUnit. Nous choisissons PHPUnit pour effectuer les tests unitaires de cet ouvrage.

Qu’est-ce que PHPUnit ? Il s’agit d’un framework de tests unitaires à part entière, toujours actif et open source, dédié au langage PHP. Il automatise les tests et est compatible avec les autres frameworks du même langage à travers une interface commune. L’automatisation permet de répéter autant de fois que nécessaire l’exécution des fonctionnalités développées au fil de l’avancement de notre projet pour détecter ses erreurs dès que possible. ALLER PLUS LOIN PHPUnit http://phpunit.de/

Installer PHPUnit PHPUnit s’installe sous la forme d’un paquet PHAR (géré en natif depuis PHP 5.3). Pour ce faire, nous utiliserons la console pour installer le framework de la façon suivante : $ wget https://phar.phpunit.de/phpunit.phar

Ensuite, nous vérifions la version de PHPUnit : $ phpunit --version

Figure 9–1 Version installée de PHPUnit

PHPUnit avec Drupal PHPUnit est un projet externe au CMS et ne possède actuellement pas de modules natifs


pour Drupal 7. Cependant, les fonctionnalités sont en cours d’implémentation pour la version 8. SimpleTest est un autre outil pour réaliser des tests unitaires qui, lui, possède déjà des modules Drupal.

Pour utiliser ce framework de tests avec le CMS, nous devons personnaliser le fichier bootstrap fourni par Drupal, que nous avons étendu au début du chapitre. Pour réaliser notre premier test unitaire, nous créons un fichier debutant.test.php que nous plaçons à la racine du site Internet. Le test portera sur une comparaison triviale de résultat et vérifiera que la valeur retournée par l’addition 1+1 est bien égale à 2. Dans cette optique, nous étendons la classe PHPUnit_Framework_TestCase pour insérer la fonction voulue. Fichier debutant.test.php <?php //Ne pas oublier le code de connexion au bootstrap class debutant_test extends PHPUnit_Framework_TestCase { public function test_two_plus_two_is_four() { $this->assertEquals(2+2,4); } } ?>

Pour exécuter le code avec n’importe quel système d’exploitation, il est préférable d’ouvrir la console ou un terminal : $ cd notreSite $ phpunit debutant.test.php

Figure 9–2 Premier test avec PHPUnit et Drupal

Le résultat obtenu montre que le test s’est bien déroulé. Cependant, il existe différents symboles que nous aurions pu afficher et qui donnent des informations plus précises sur les tests : . : le test est réussi ; F : l’assertion a échoué ;


E : l’exécution du test a provoqué une erreur ; S : un problème inconnu est apparu, donc le test est sauté ; I : le test est incomplet ou non implémenté.

Préparer son module de test C’est le module Menu pour tous précédemment réalisé qui va nous servir de base pour effectuer nos tests unitaires et montrer comme il est facile de les automatiser. Fichier <monmodule>.test.php Le fichier de test contenant le script de contrôle se termine par .test.php pour ne pas le mélanger avec les autres fichiers du même dossier. Emplacement du module Menu pour tous sites/all/modules/menu_for_all/

Nous nous appuyons tout d’abord sur le bootstrap vu au début du chapitre. La seule différence concerne le chemin d’accès au fichier : la constante PATH correspond à quatre sous-dossiers par rapport à l’emplacement du bootstrap. Déclaration du bootstrap <?php $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; define('DS', DIRECTORY_SEPARATOR); define ('PATH', DS . '..' . DS . '..' . DS . '..' . DS . '..' . DS ); define('DRUPAL_ROOT', realpath(dirname(__FILE__) ) . PATH ); set_include_path(DRUPAL_ROOT . get_include_path()); include_once DRUPAL_ROOT . 'includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); ?>

Comme nous vérifions que le code va retourner des résultats égaux, nous utilisons les TestCase de PHPUnit. Extension de TestCase <?php class menu_for_all_test extends PHPUnit_Framework_TestCase { // Notre code } ?>

Créer des fonctions de test


À l’intérieur de notre classe étendue, nous allons réaliser quelques tests spécifiques que nous pouvons appeler à tout moment. Premier test : un hook Nous commençons par vérifier si le hook_help() retourne bien les informations souhaitées. La fonction se découpe de la manière suivante : préparation du texte qui doit s’afficher ; comparaison du contenu affiché avec le texte en mémoire à partir de la fonction assertEquals. Test du hook_help() public function test_function_help() { $output = '<h3>À propos du module : Menu for all</h3>'; $output .= '<p>Exemple de module pour le livre : Drupal avancé aux éditions Eyrolles</p>'; $this->assertEquals( menu_for_all_help('admin/help#menu_for_all'), $output); }

Deuxième test : une page Le deuxième test concerne la création et l’affichage d’un nœud de type page. Pour cela, nous réalisons deux fonctions : une création de nœud pour appeler la fonction de création de page ; un affichage de nœud pour vérifier si la création s’est bien déroulée. Test de création d’une page public function test_ajouter_page() { $status_noeud=$this->creation_page(); $this->assertEquals(1, $status_noeud->status); }

La création d’un nœud se décompose de la manière suivante : appel de la classe stdClass() ; ajout d’un titre ; ajout d’un contenu dans le corps ; spécification du type de contenu ; publication de la page ; sauvegarde. Test de création d’un nœud public function creation_page()


{ $node = new stdClass(); $node->title = "Page de test"; $node->body = "Une page de test avec PHPUnit"; $node->type = "page"; $node->promote = 1; node_save($node); return $node; }

Le nœud retourné correspond à une page qui sera affichée dans le site web.

Lancer les tests Nous nous positionnons à la racine et exécutons notre test : $ cd notreSite $ phpunit sites/all/modules/menu_for_all/menu_for_all.test.php

Figure 9–3 Test du module menu_for_all avec PHPUnit et Drupal

Le résultat montre que les deux tests ont bien été effectués et ont été réalisés avec succès.

Tests fonctionnels Le test fonctionnel est un autre type de test automatisé. Il se préoccupe du fonctionnement de l’application sans s’occuper du code qui a été exécuté : un navigateur et un robot simulent les actions des utilisateurs ou des internautes. Ce type de test permet de maximiser la qualité des écrans en minimisant les risques de régression du point de vue de l’utilisateur final du site (vérification de la présence des fonctionnalités attendues et de leur bon fonctionnement via le déroulement d’un scénario d’utilisation).

Qu’est-ce que Selenium HQ ? Selenium HQ est un framework de tests unitaires orienté fonctionnel avec une interface IDE nommée Selenium IDE. Il permet de réaliser des tests automatiques directement dans un navigateur. Il est compatible avec Firefox, Chrome, Opera, Safari et Internet Explorer. COMPATIBILITÉ Selenium HQ, les systèmes d’exploitation et les navigateurs http://www.seleniumhq.org/about/platforms.jsp


Bien entendu, chaque navigateur possède son interface pour utiliser ce logiciel : http://docs.seleniumhq.org/download/

Installer Selenium IDE Nous choisissons ici d’utiliser la version Selenium IDE avec le navigateur Firefox de Mozilla. Il faut d’abord télécharger l’add-on correspondant. https://addons.mozilla.org/fr/firefox/addon/selenium-expert-selenium-ide/

Une fois Selenium installé, nous le lançons à partir de la barre de navigation de Firefox. Sa configuration proposée nativement permet de mémoriser les scénarios et la navigation que nous déterminons à travers une interface, comme le montre la figure suivante.

Figure 9–4 Interface Selenium HQ

Nous testons ici la page utilisateur de notre application. Pour cela, nous naviguons dans le site pour obtenir le script suivant. Le code généré par Selenium HQ est un format XML et


se présente de la manière suivante : <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head profile="http://selenium-ide.openqa.org/profiles/test-case"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="selenium.base" href="http://localhost/" /> <title>selenium</title> </head> <body> <table cellpadding="1" cellspacing="1" border="1"> <thead> <tr><td rowspan="1" colspan="3">selenium</td></tr> </thead><tbody> <tr> <td>open</td> <td>/drupal/</td> <td></td> </tr> <tr> <td>clickAndWait</td> <td>link=Menu de fete</td> <td></td> </tr> <tr> <td>clickAndWait</td> <td>link=Créer un nouveau compte</td> <td></td> </tr> <tr> <td>clickAndWait</td> <td>link=Accueil</td> <td></td> </tr> <tr> <td>type</td> <td>id=edit-name</td> <td>admin</td> </tr> <tr> <td>type</td> <td>id=edit-pass</td> <td>admin</td> </tr> <tr> <td>clickAndWait</td> <td>css=a[title="Se créer un compte"] > img</td> <td></td> </tr> <?xml ver<tr> <td>type</td> <td>id=edit-name</td> <td>admin</td> </tr> <tr>


<td>type</td> <td>id=edit-mail</td> <td>admin</td> </tr> <tr> <td>clickAndWait</td> <td>id=edit-submit</td> <td></td> </tr> <tr> <td>clickAndWait</td> <td>link=Se connecter</td> <td></td> </tr> <tr> <td>type</td> <td>id=edit-name</td> <td>admin</td> </tr> <tr> <td>type</td> <td>id=edit-pass</td> <td>admin</td> </tr> <tr> <td>clickAndWait</td> <td>id=edit-submit</td> <td></td> </tr> <tr> <td>clickAndWait</td> <td>css=li.menu-14.last > a</td> <td></td> </tr> </tbody></table> </body> </html>

Selenium HQ et Drupal Il existe un module Selenium pour Drupal, qui permet de réaliser des tests fonctionnels. Ce module s’appuie sur le framework SimpleTest. Nous n’en parlerons pas, car nous avons choisi de présenter PHPUnit. Pour le moment, aucun module stable Selenium avec PHPUnit n’est disponible, mais il existe des solutions pour les faire cohabiter, que nous allons présenter ci-après. ALLER PLUS LOIN Utiliser conjointement PHPUnit et Selenium http://phpunit.de/manual/current/en/selenium.html


Associer les tests L’association de tests unitaires et de tests fonctionnels peut sembler lourde pour des petits projets. Elle s’avère cependant indispensable sur les longs projets. C’est pourquoi nous associerons PHPUnit et Selenium HQ pour tester un module Drupal. Pour notre exemple, nous choisissons le module Menus qui a été décrit dans les précédents chapitres. Nous allons tester notre formulaire en effectuant quelques tests unitaires et fonctionnels. Bien entendu, PHPUnit propose de nombreuses fonctions pour exécuter et suivre les tests fonctionnels avec Selenium. Toutes les fonctionnalités sont détaillées dans la documentation de PHPUnit.

Installer Selenium HQ server Il faut tout d’abord télécharger Selenium HQ Server, puis déplacer le fichier dans le dossier /usr/local/bin/. http://docs.seleniumhq.org/download/

Ensuite, il faut mettre en place le serveur. Lorsque nous souhaitons exécuter des tests fonctionnels, nous simulons deux ordinateurs (le serveur et le client). Nous lançons un terminal et saisissons la ligne suivante : $ java -jar /usr/local/bin/selenium-server-standalone-2.37.0.jar

Cette opération permet de communiquer avec le navigateur et les tests unitaires.

Préparer son module de test fonctionnel Fichier <monmodule>.test.php Le fichier de test contenant le script de contrôle se termine par .test.php pour ne pas le mélanger avec les autres fichiers du même dossier. Emplacement du module Menus sites/all/modules/menus/

Nous nous appuyons tout d’abord sur le bootstrap vu au début du chapitre. La seule différence concerne le chemin d’accès au fichier : la constante PATH correspond à quatre sous-dossiers par rapport à l’emplacement du bootstrap. Déclaration du bootstrap <?php $_SERVER['REMOTE_ADDR'] = '127.0.0.1';


define('DS', DIRECTORY_SEPARATOR); define ('PATH', DS . '..' . DS . '..' . DS . '..' . DS . '..' . DS ); define('DRUPAL_ROOT', realpath(dirname(__FILE__) ) . PATH ); set_include_path(DRUPAL_ROOT . get_include_path()); include_once DRUPAL_ROOT . 'includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); ?>

Comme nous vérifions que le code va retourner des résultats égaux, nous utilisons les TestCase de PHPUnit_extensions_seleniumTestCase. Extension de la classe PHPUnit_Extensions_SeleniumTestCase class menus_test extends PHPUnit_Extensions_SeleniumTestCase { // votre code }

Créer des fonctions de tests À l’intérieur de notre classe étendue, nous allons réaliser cinq tests spécifiques que nous pouvons appeler à tout moment. Premier test : connexion avec le navigateur Nous vérifions d’abord la présence du navigateur Firefox. Le test va permettre de lancer le site web en saisissant directement l’URL dans le navigateur sur le port 4444. Test 1 : connexion avec le navigateur protected function setUp() { $this->setHost ('localhost'); $this->setPort (4444); $this->setBrowser ('firefox'); $this->setBrowserUrl ('http://localhost/drupal/'); } public function testSite() { $this->setBrowserurl ('index.php'); }

Ce premier test est obligatoire car s’il échoue il est impossible de simuler la navigation, la saisie et les actions des formulaires. Deuxième test : détection du module Nous vérifions que le module est bien actif, c’est-à-dire que la case spécifique est cochée. Si ce n’est pas le cas, la lettre E apparaît, qui signale un problème avec cette ligne. Test 2 : détection du module


function testMonModule() { $this->open ("/"); module_invoke ('menus', 'testMonModule', $this); }

Troisième test : ouverture d’une page La fonction assertElementValueEquals sert à vérifier si un élément d’une page (ici, un champ du formulaire) est vide. Test 3 : ouverture d’une page public function testOuverturePageTypeMenu() { $this->open ( "http://localhost/drupal/?q=admin/menus/diner"); $this->assertElementValueEquals ('name', ''); }

Si la valeur de l’élément est égale à 1 au lieu de vide, le test signale un problème.

Figure 9–5 Erreur sur l’élément ajouté dans le formulaire

Quatrième test : insertion de données Le quatrième test vérifie si les données saisies dans la page s’enregistrent correctement dans la base de données. Il se décompose de la manière suivante : ouverture de la page ; saisie d’une valeur dans le champ name du formulaire ; simulation du clic de la souris sur le bouton submit ; envoi de l’ensemble de ces informations directement dans le module. Test 4 : insertion de données function testAjouterUnNomMenu() { $this->open ("http://localhost/drupal/?q=admin/menus/diner"); $this->type ("name", "essai55");


$this->click ("edit-add"); module_invoke ('menus', 'testAjouterUnNomMenu', $this); }

Si toutes les étapes se sont bien déroulées, le test est représenté par un point. Cinquième test : affichage de la page visible La dernière étape de cette série de tests vérifie la page du module du côté FRONT. La fonction setBrowserurl charge la page dans le navigateur par rapport à son URL.

Test 5 : affichage de la page visible public function testModule() { $this->setBrowserurl ('?q=menus/diner'); }

Exécuter l’ensemble des tests Lorsque tous les tests fonctionnels sont prêts, nous saisissons les instructions suivantes en ligne de commande : $ cd votreSite $ phpunit sites/all/modules/menus/menus.test.php

Figure 9–6 Exécution de l’ensemble des tests

Le résultat montre que les cinq tests ont été réalisés avec une insertion dans la base de données.

Conclusion Il existe de nombreux moyens d’effectuer des tests unitaires et des tests fonctionnels. Nous n’avons montré que l’usage de PHPUnit et Selenium HQ, mais d’autres outils peuvent être ajoutés à volonté.


La recherche : native et étendue avec Solr et Facet API

10

La recherche de contenu est l’une des fonctionnalités les plus demandées sur un site web. Ce chapitre nous permettra de comprendre le fonctionnement de la recherche, mais aussi de découvrir comment Drupal peut être étendu de ce côté-là et monter en puissance avec un affichage par facettes. SOMMAIRE À la découverte de la recherche dans Drupal Améliorer la recherche avec Apache Solr Créer une recherche par facettes avec Facet API


Drupal nous permet de rechercher dans tous ses contenus, c’est-à-dire les nœuds et les champs associés, les termes de taxonomie, les commentaires et les utilisateurs. Nous allons voir les étapes nécessaires au fonctionnement de cette recherche.

La recherche native dans Drupal Activation et mise en place de la recherche Drupal fournit un module natif, Search, pour effectuer des recherches. Nous devons donc commencer par l’activer dans Admin>Modules.

Figure 10–1 Activation du module Search

Il existe deux moyens de faire apparaître la recherche : utiliser le bloc fourni par le module ; créer un lien de menu vers la page de recherche. Pour créer un bloc, rendons-nous dans Administration>Structure>Blocs. Dans la liste affichée, nous choisissons de mettre le bloc Formulaire de recherche dans la région Entête.

Figure 10–2 Placement du bloc Formulaire de recherche dans la région Entête

N’oublions pas de cliquer sur Enregistrer les blocs. La figure suivante montre ce que cela donne pour un utilisateur authentifié.

Figure 10–3 Résultat de l’affichage

Pour ajouter un lien de menu qui pointe directement vers notre page de recherche, créons ce lien via Admin>Structure>Menus>le menu de notre choix et indiquons search dans le champ Chemin. ATTENTION Seuls les administrateurs ont accès à la recherche Il faut penser à aller dans Personnes>Droits et cocher la case Utiliser la recherche pour les utilisateurs anonymes et les utilisateurs authentifiés (en fonction de ce que nous souhaitons pour votre site).


Figure 10–4 Droits liés à la recherche

Figure 10–5 Ajout d’un lien de menu vers la recherche

Regardons de plus près le fonctionnement de la recherche. Drupal ne sait chercher que sur des mots complets : si nous entrons « Sil » pour notre restaurant du Silo, nous ne trouverons pas grand-chose.

Figure 10–6 Recherche sans résultat sur un mot incomplet

En revanche, si nous cherchons le mot complet « Silo » (sans les guillemets, sinon Drupal cherchera l’expression complète), nous trouvons bien le résultat escompté.


Figure 10–7 Résultat de la recherche

Comme nous le voyons, il y a deux onglets : une recherche dans le contenu et une dans les utilisateurs. La Recherche avancée nous permet de faire des requêtes un peu plus complexes.

Figure 10–8 Fenêtre de recherche avancée

Si nous souhaitons d’autre critères, comme des recherches partielles, il faudra passer par des modules additionnels. Nous y reviendrons dans la seconde partie de ce chapitre.

Indexation du contenu Avant de voir comment étendre les possibilités en utilisant d’autres modules, voire des outils de recherche externe, nous devons parler de l’indexation. L’indexation, c’est l’action d’enregistrer tout le contenu de notre site pour pouvoir nous


donner des résultats lors de nos recherches. Si le contenu n’est jamais indexé, alors la recherche ne nous retournera jamais ce que l’on souhaite. Pour configurer l’indexation, rendons-nous sur la page Administration>Configuration>Recherche et métadonnées>Paramètres de recherche.

Figure 10–9 Paramètres de recherche : statut et seuil

Nous voyons dans ces paramètres le Statut de l’indexation, c’est-à-dire le pourcentage des contenus et des utilisateurs de notre site qui ont été indexés. L’indexation se fait lors de l’appel de la tâche cron. Cette tâche planifiée exécute de nombreuses actions de maintenance de notre site, dont l’indexation. Pour la configurer, rendons-nous dans Administration>Configuration>Système>Tâche planifiée (cron).

Figure 10–10 Configuration de la tâche planifiée

C’est dans cette page de configuration que nous choisissons la fréquence d’exécution de notre tâche planifiée. Pour un site vitrine ou un blog, une exécution quotidienne suffit amplement. Pour un site avec énormément de contenu (plusieurs milliers d’articles, dont plusieurs ajoutés chaque jour), il nous faudra augmenter la fréquence d’exécution. Retournons à notre page de configuration de la recherche (Administration>Configuration>Recherche et métadonnées>Paramètres de


recherche). Le second paramètre est le Nombre d’éléments à indexer par tâche cron. Si dans les logs de Drupal (Administrer>Rapports>Entrées récentes du journal), ou dans ceux d’Apache, nous constatons de trop nombreuses erreurs de type temps d’exécution dépassé, il faudra réduire le nombre d’éléments à indexer à chaque passage de la tâche cron.

Figure 10–11 Paramètres d’indexation et modules de recherche actifs

Les réglages suivants concernent les Paramètres d’indexation et les Modules de recherche actifs. L a Taille minimale des mots à indexer sert à éviter les mots qui ne feront pas l’objet de recherches, tels que « le, la, et, de... ». La case Gestion CJK simple gère de manière simplifiée l’indexation des caractères chinois, japonais ou coréens. Les Modules de recherche actifs définissent ce qui doit être indexé sur notre site. Nous voyons que, avec son seul module de base, Drupal ne sait indexer que les nœuds et les utilisateurs. L e Module de recherche par défaut correspond à l’onglet proposé systématiquement sur la page de recherche ou lors de l’utilisation du bloc de recherche rapide. Le dernier bloc de paramétrage concerne le classement des résultats de nos recherches. Nous pouvons par exemple afficher en premier les contenus les plus commentés ou les plus récents. Pour cela, il faut modifier le poids de chaque critère. Plus un critère est lourd (son poids se rapproche de 10), plus les contenus correspondants sont placés en premier dans les résultats de recherche.


Figure 10–12 Classement du contenu

Nous avons donc expliqué comment utiliser la recherche native de Drupal. Nous allons désormais voir comment ajouter un module de recherche dans notre entité Menus.

Search API avec Solr pour indexer et rechercher dans notre entité Menus Installation et configuration de Search API Pour effectuer une recherche également dans notre propre entité Menus, nous allons installer un module supplémentaire, Search API, avec sa dépendance Entity API. MÉTHODE Installer le module Search API par l’interface Télécharger les modules Search API et Entity API : https://drupal.org/project/search_api https://drupal.org/project/entity Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver les modules Search API et Entity API dans la liste et les activer (nous verrons les deux autres modules dans la deuxième partie du chapitre).

MÉTHODE Installer le module Search API en ligne de commande avec Drush $ drush dl search_api entity $ drush en -y search_api entity


Figure 10–13 Modules Search disponibles

Nous allons maintenant configurer Search API pour le faire fonctionner avec notre entité Menus. Pour ce faire, rendons-nous dans Admin>Configuration>Search API. Nous arrivons alors sur la liste des index et des serveurs.

Figure 10–14 Search API : liste des index et serveurs par défaut

Comme le précise la figure 10-14, il faut deux choses pour que Search API fonctionne : 1 au moins un index, c’est-à-dire une liste de ce qu’il doit indexer (les nœuds par défaut) ; 2 au moins un serveur, qui est l’endroit où la recherche va être effectuée. Par défaut, il n’y en a pas. Nous allons dans un premier temps utiliser la recherche en base de données.

Installation de Solr et déclaration en tant que serveur de recherche Pour aller plus loin avec la recherche, nous utiliserons le moteur de recherche Apache Solr. Pour cela, nous devons disposer d’une version 1.6 ou supérieure de Java. Après avoir récupéré la dernière version de Solr (4.6.1 dans notre cas) sur le site officiel, nous extrayons l’archive dans notre dossier personnel (dans un terminal Linux, Windows, Mac OS ou Unix) : $ tar -xzvf solr-4.6.1.tgz .

http://lucene.apache.org/solr/

Il nous faut maintenant donner les fichiers de configuration de Search API à Apache Solr pour que le premier détecte correctement le second. Nous allons donc installer le module qui va lier les deux : il s’agit de Search API Solr. MÉTHODE Installer le module Search API Solr par l’interface Télécharger le module : https://drupal.org/project/search_api_solr Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules).


Trouver le module dans la liste et l’activer.

MÉTHODE Installer le module Search API Solr en ligne de commande avec Drush $ drush dl search_api_solr $ drush en -y search_api_solr

Observons son arborescence dans /sites/all/modules/search_api_solr/solr-conf/4.x/.

Figure 10–15 Fichiers de configuration fournis par Search API Solr

Nous

devons

copier

tous

ces fichiers dans le répertoire suivant : /solr4.6.1/example/solr/collection1/conf (le chemin est à adapter en fonction de notre version de Solr et de notre arborescence). Nous pouvons maintenant démarrer Solr en ligne de commande : kovalsky@kovalsky ~/solr-4.6.1/example $ java -jar start.jar

Pour vérifier que notre Solr a bien démarré, ouvrons un navigateur et saisissons l’adresse URL suivante : http://localhost:8983/solr/.


Figure 10–16 Page d’accueil de Solr

Il nous reste à le connecter avec notre Drupal. Pour cela, rendons-nous dans la configuration de Search API (Admin>Configuration>Recherche et métadonnées>Search API). Ajoutons un serveur (+ Add server).

Figure 10–17 Ajout du serveur Solr à Search API

Nous renseignons le nom et une description, puis nous sélectionnons Solr service pour le Service class. Laissons les paramètres de Solr par défaut ; il s’agit de l’adresse pour accéder à notre Solr installé en local.

Figure 10–18 Paramétrage du service Solr

Puis nous créons le serveur (Create Server). Nous sommes redirigés sur la page du serveur Solr que nous venons d’ajouter.


Figure 10–19 Affichage du serveur Solr ajouté

Voilà notre serveur Solr configuré et prêt à l’emploi. Si notre site affiche un message de type « Cannot contact Solr Server », assurons-nous que Solr est démarré et que sa page d’affichage (http://localhost:8983/solr) répond correctement. Sécuriser le serveur Solr Pour empêcher que n’importe qui accède à nos données contenues dans Solr (notamment, tous les éléments du site que nous choisirons d’indexer), il faut penser à sécuriser l’accès à Solr. Pour cela, plusieurs méthodes s’offrent à nous : changer le chemin d’accès à Solr, en renommant le dossier solr par exemple ; mettre en place un accès uniquement depuis le serveur local (avec des outils comme IPTables) ; mettre en place une authentification HTTP (via un fichier Virtual Host par exemple).

Ajout d’un index sur l’entité Menus Retournons dans la configuration de Search API pour ajouter un index (Admin>Configuration>Recherche et métadonnées>Search API) en cliquant sur + Add Index.


Figure 10–20 Ajouter un index

Nous sélectionnons le nom Menus en Item type (le type d’entité à indexer), laissons l’index Activé et renseignons une description. La partie suivante de la configuration apparaît.

Figure 10–21 Paramétrage du serveur pour l'index

Comme serveur, nous choisissons Solr. Nous cochons la case Index items immediately pour que les contenus soient indexés dès leur ajout, mais aussi pour gérer correctement les droits d’accès. Nous laissons la limite d’indexation à 50 items par tâche planifiée (cron). Puis nous cliquons sur Create index, qui nous amène alors sur la page de configuration des champs à indexer pour l’entité sélectionnée.


Figure 10–22 La paramétrage s’est bien déroulé.

Notre champ de taxonomie apparaît. Si nous avions plus de champs dans notre entité, nous pourrions en sélectionner d’autres. Le bloc Add related fields permet d’indexer des champs en rapport avec notre entité, comme la taxonomie sélectionnée ou l’auteur d’un nœud. Une fois les champs enregistrés, nous passons à l’étape suivante : l’altération des données. L’idée n’est pas de modifier les données indexées, mais de permettre à l’utilisateur de les retrouver plus facilement. Ces paramètres spécifient des options en fonction des champs sélectionnés. Dans notre c a s , Index hierarchy nous permettrait d’indexer les termes parents des termes de taxonomie de nos menus. La seconde partie de la configuration sert à paramétrer les traitements avant et après l’envoi de données à Solr, comme l’insensibilité à la casse ou les filtres HTML.

Figure 10–23 Altération des données sur l’index des menus


Figure 10–24 Paramétrage des processeurs pour l’index Menus

ALLER PLUS LOIN Altération de données ou des processeurs https://drupal.org/node/1254452

Une fois l’index créé, nous revenons sur l’onglet Voir, pour vérifier que tout est bon et réindexer notre contenu (cliquons sur Index now pour ne pas attendre la prochaine exécution de la tâche planifiée cron).

Figure 10–25 Voir l’index créé et indexer le contenu

Notre serveur et notre index sont maintenant configurés ; il ne nous reste plus qu’à permettre à nos utilisateurs de faire des recherches dans nos menus.

Affichage de la recherche dans nos menus Nous devons afficher notre option de recherche sur les termes de taxonomie de notre


entité Menus. Pour cela, nous utiliserons le module supplémentaire Search API Page. MÉTHODE Installer le module Search API Page par l’interface Télécharger le module : https://drupal.org/project/search_api_page Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver le module dans la liste et l’activer.

MÉTHODE Installer le module Search API Page en ligne de commande avec Drush $ drush dl search_api_pages $ drush en -y search_api_pages

Une fois le module installé et activé, un nouvel onglet apparaît dans la page de configuration de Search API (Admin>Configuration>Recherches et métadonnées>Search API).

Figure 10–26 Liste des pages de recherche (search pages)

Ajoutons une nouvelle page qui permettra de chercher dans nos menus ; nous cliquons sur + Add search page.


Figure 10–27 Ajouter une page de recherche

Nous donnons un nom à notre page puis nous sélectionnons l’index créé auparavant. Nous ajoutons une description et nous définissons le chemin suivant : search/menus. Nous validons enfin le formulaire en cliquant sur Create page. La deuxième page de configuration détaille ce sur quoi va porter notre recherche (les champs concernés, le nombre de résultats par page, etc.). Une fois la page créée, nous revenons sur la liste des pages de recherche et nous cliquons sur le lien (search/menus dans notre cas) pour voir le résultat. Nous pouvons donc à présent rechercher dans les menus depuis cette page. Un bloc correspondant à la page a également été créé (Admin>Structure>Blocs).

Figure 10–28 Configuration de la page de recherche

Figure 10–29 Affichage de la page de recherche dans les menus

Figure 10–30 Bloc de recherche dans les menus

Nous pouvons afficher également un bloc spécifique pour cette recherche. Nous avons donc vu dans cette partie la configuration de base de Search API avec l’installation d’un moteur de recherche Solr, puis l’affichage de nos recherches


spécifiques. La suite du chapitre nous permettra d’aller plus loin dans l’affichage de nos recherches et de les moduler en utilisant les facettes.

Utilisation de Facet API et de Views pour des recherches par facettes Nous allons créer une page qui contient la liste des restaurants. Nous lui ajouterons des blocs de recherche par facettes, pour filtrer la liste des restaurants sur la taxonomie Type de restaurant et sur la Ville.

Créer l’index des nœuds et la vue associée Commençons par créer un nouvel index : Admin>Configuration>Recherche et métadonnées>Search API>+ Add index.

Figure 10–31 Ajout d’un index des nœuds

Ensuite, nous sélectionnons les informations que nous voulons indexer pour la recherche. Il s’agit des informations des nœuds, mais aussi des champs que nous avons ajoutés. L’altération des données permet d’associer des nœuds indexés à des informations supplémentaires. Par exemple, nous avons choisi de cocher Node access pour que les résultats de la recherche soit filtrés en fonction des droits d’accès aux nœuds de l’utilisateur qui effectue la recherche.


Figure 10–32 Champs de l’index des nœuds (partie haute)

Figure 10–33 Champs de l’index des nœuds (partie basse)

Figure 10–34 Altération des données pour l’index des nœuds

Viennent ensuite les options liées aux processeurs, c’est-à-dire les filtres qui seront appliqués sur les données indexées. Dans l’exemple, nous avons choisi d’ignorer la casse


et de ne pas indexer les balises HTML (qui seront alors retirées des textes indexés).

Figure 10–35 Options liées aux processeurs de l’index des nœuds

Pour chaque processeur sélectionné, des options spécifiques sont disponibles. Les figures suivantes en montre un exemple sur les processeurs Ignore case et HTML filter.

Figure 10–36 Paramètres du processeur Ignore case

Figure 10–37 Paramètres du processeur HTML filter

Nous avons créé notre index. N’oublions pas de revenir sur l’onglet Voir pour lancer l’indexation de nos nœuds. Passons à la création de la vue. Nous devons activer le module Search Views


(Admin>Modules). Ajoutons la vue pour notre page de recherche et de résultats : Administration>Structure>Views>+ Add new view.

Figure 10–38 Ajout d’une vue de type Index nœuds

Il faut entrer un nom pour notre vue puis, dans Afficher, sélectionner l’index (Index nœuds). La figure suivante montre les paramètres à renseigner pour votre vue.

Figure 10–39 Vue Recherche dans les nœuds restaurants

Nous avons choisi un affichage de type Rendered entity, soit l’affichage complet d’une entité sous forme d’accroche ; nous n’aurons donc que le début du nœud affiché, avec les champs que nous pouvons sélectionner dans Structure>Type de contenu>Nom du type de contenu>Gérer l’affichage, sous onglet Accroche. Puis nous avons ajouté un filtre Rechercher : Fulltext search, en cochant le fait que ce filtre soit exposé (Expose this filter to visitors, to allow them to change). Nous avons également défini un nouveau filtre Indexed Nœud : Type de contenu (=Restaurant). Enfin, nous avons ajouté un Global : Result summary sur l’en-tête de la vue.


Les figures suivantes montrent le résultat obtenu sans entrer de terme de recherche, puis en faisant une recherche sur le nom d’un restaurant.

Figure 10–40 Affichage de la vue Restaurants

Figure 10–41 Recherche sur un restaurant

Voilà ! Nous avons configuré notre vue avec la recherche associée. Passons à la suite avec l’intégration des facettes.

Filtrer la recherche avec Facet API Commençons par installer Facet API. MÉTHODE Installer le module Facet API par l’interface Télécharger le module : https://drupal.org/project/facetapi Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver et activer les modules Facet API, Search acets et Current Search Blocks.


MÉTHODE Installer le module Facet API en ligne de commande avec Drush $ drush dl facetapi $ drush en -y facetapi

Retournons dans la configuration de Search API, via Admin>Configuration>Recherche et métadonnées>Search API, et modifions l’Index nœuds que nous avons créé précédemment. Un nouvel onglet concernant les facettes est apparu.

Figure 10–42 Choix des facettes dans l’Index nœuds

Nous sélectionnons des facettes sur le groupe d’appartenance et sur le type de restaurants. Lorsque nous enregistrons nos choix, des informations apparaissent concernant le moyen d’activer les blocs de facettes.


Figure 10–43 Activer les blocs de facettes après leur création

Il nous reste à faire apparaître les blocs sur la page de notre liste de restaurants. Pour cela, nous allons dans la configuration (Admin>Structure>Blocs). Nous voyons apparaître trois nouveaux blocs : un pour chaque facette choisie et un bloc Current search, fourni par le module éponyme. Nous plaçons ces trois blocs dans la deuxième barre latérale.

Figure 10–44 Positionnement des blocs de facettes

Une fois la page des blocs enregistrée, nous retournons sur notre liste de restaurants.


Figure 10–45 Page des restaurants avec les facettes

Nous pouvons donc filtrer avec les facettes. Celles-ci peuvent se compléter, pour filtrer encore plus vos résultats de recherche.

Figure 10–46 Affichage du résultat après utilisation de deux facettes

Nous avons bien ici le résultat attendu avec les facettes. Il nous reste à configurer le bloc Current search pour que celui-ci affiche nos critères de recherche actuels. Pour ce faire, commençons par la configuration générale du module, dans Admin>Configuration>Recherche et métadonnées>Current Search Blocks. Nous arrivons alors sur la liste des blocs (nous pouvons si nécessaire en créer plusieurs).

Figure 10–47 Liste des Current search blocks


Nous choisissons de modifier le bloc existant, appelé standard. Différent paramètres s’offrent à nous, en commençant par la possibilité d’ajouter d’autres items dans ce bloc.

Figure 10–48 Ajout d’item dans un bloc Current search

Nous laissons les items par défaut et descendons dans la page pour voir les autres options disponibles. Le contenu de chaque item peut être configuré en utilisant les tokens. Là encore, nous laissons le paramétrage par défaut (nous pouvons bien sûr le modifier à notre guise), pour continuer dans la page de configuration. Le dernier paramètre de configuration concerne l’affichage du bloc. Nous sélectionnons ici la dernière option : Display when either keyword are entered one or more facet items are active. Cette option indique au bloc de s’afficher lorsque au moins un mot a été saisi dans la barre de recherche ou lorsque au moins une facette est active. Pour enregistrer le tout, il faut remonter en haut de la page de configuration. Nous retournons enfin sur notre page Restaurants et activons les deux mêmes facettes. Nous avons donc une page qui liste les restaurants et dans laquelle on peut faire une recherche ou filtrer les résultats par facette (voire les deux).

Figure 10–49 Configuration de l’item Results dans le bloc Current search standard


Figure 10–50 Paramètres d’affichage du bloc Current search standard

Figure 10–51 Affichage du bloc de recherche courante

Aller plus loin avec les modules complémentaires de Search API Pour cette dernière partie, précisons que la majorité des modules présentés ici ne fonctionnent qu’avec un serveur Solr installé et opérationnel. Autocomplete Nous allons ajouter une autocomplétion sur notre champ de recherche dans la vue Recherche dans les restaurants. Pour cela, nous avons besoin d’installer et d’activer un module supplémentaire : Search API Autocomplete. MÉTHODE Installer le module Search API Autocomplete par l’interface Télécharger le module : https://drupal.org/project/search_api_autocomplete Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver et activer le module.


MÉTHODE Installer le module Search API Autocomplete en ligne de commande avec Drush $ drush dl search_api_autocomplete $ drush en -y search_api_autocomplete

Pour configurer l’autocomplétion, rendons-nous dans Admin>Configuration>Recherche et métadonnées>Search API et sélectionnons Autocomplete sur Index nœuds.

Figure 10–52 Autocomplétion sur Index nœuds

Nous arrivons alors sur la liste des vues utilisant cet index et nous sélectionnons la vue Recherche dans les restaurants.

Figure 10–53 Vue utilisant l’autocomplétion avec Search API

Nous devons donner la permission aux utilisateurs d’utiliser l’autocomplétion. Rendonsnous dans Admin>Personnes>Droits et sélectionnons les droits adéquats.

Figure 10–54 Permissions liées à Search API Autocomplete

Avant de tester l’autocomplétion, nous allons lui demander d’afficher le nombre de résultats estimés en sélectionnant Modifier sur la ligne correspondante.


Figure 10–55 Modification de l’autocomplétion sur la vue Recherche dans les restaurants

Puis nous cochons la case Display result count estimates. Retournons sur notre page de recherche dans les restaurants ; l’autocomplétion fonctionne.

Figure 10–56 Affichage de l’autocomplétion sur la vue

Spellcheck pour obtenir des suggestions en cas d’erreur de frappe Commençons par installer et activer le module Search API Spellcheck. MÉTHODE Installer le module Search API Spellcheck par l’interface Télécharger le module : https://drupal.org/project/search_api_spellcheck Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver le module dans la liste et l’activer.

MÉTHODE Installer le module Search API Spellcheck en ligne de commande avec Drush $ drush dl search_api_spellcheck $ drush en -y search_api_spellcheck


Ajoutons les suggestions dans la vue via Admin>Structure>Vues. Nous ajoutons un entête Rechercher : Spellcheck. Puis nous enregistrons notre vue et allons voir le résultat sur la page Recherche dans les restaurants

Figure 10–57 Ajout d’un en-tête Spellcheck à une vue

Figure 10–58 Utilisation de Spellcheck dans notre vue

Saved searches pour que nos utilisateurs retrouvent leurs recherches Ici nous utilisons Search API Saved Searches. MÉTHODE Installer le module Search API Saved Searches par l’interface Télécharger le module : https://drupal.org/project/search_api_saved_searches Décompresser les archives dans notre dossier /sites/all/modules.


Aller à la page des modules de notre site (Admin/Modules). Trouver le module dans la liste et l’activer.

MÉTHODE Installer le module Search API Saved Searches en ligne de commande avec Drush $ drush dl search_api_saved_searches $ drush en -y search_api_saved_searches

Commençons par activer la sauvegarde de recherche en nous rendant de nouveau dans la configuration de Search API via Admin>Configuration>Recherche et métadonnées>Search API. Sur la ligne Index nœuds, nous sélectionnons Saved searches. Nous activons la sauvegarde des recherches et la possibilité pour les utilisateurs de supprimer ces sauvegardes.

Figure 10–59 Paramétrage des recherches sauvegardées pour Index nœuds

Ensuite, et comme le principe est d’envoyer un e-mail aux utilisateurs lorsqu’un nouveau résultat à leur recherche est apparu, plusieurs options sont configurables, en commençant par les intervalles de notification.

Figure 10–60 Réglage des intervalles de notification pour les recherches sauvegardées


Le bloc de paramétrage qui apparaît ensuite concerne les courriels envoyés, en commençant par celui d’activation pour les utilisateurs anonymes.

Figure 10–61 Paramétrage du courriel d’activation pour les recherches sauvegardées

Nous retrouvons ensuite le paramétrage du courriel de notification avec un encapsulage des différents niveaux : d’abord le sujet et le corps de l’e-mail.

Figure 10–62 Paramétrage du corps du courriel pour la recherche sauvegardée

Puis viennent l’affichage des résultats de la recherche, chaque item de celle-ci et le nombre maximal de résultats à afficher.


Figure 10–63 Paramétrage des résultats de recherche sauvegardés dans le courriel de modification

Enfin, nous avons la possibilité de laisser les utilisateurs créer des recherches sauvegardées sans avoir une première fois exécuté cette recherche.

Figure 10–64 Donner la possibilité de création manuelle de la recherche sauvegardée

Une fois ces paramétrages effectués, rendons-nous dans Admin>Structure>Blocs. Nous retrouvons un bloc lié à cette recherche sauvegardée, que nous plaçons dans la seconde barre de navigation avec notre autre bloc lié à la recherche.

Figure 10–65 Bloc Index nœuds : Save search

Retournons sur notre page de recherche des restaurants et effectuons une recherche : nous voyons bien notre bloc apparaître.


Figure 10–66 Affichage du bloc Save search

Nous avons donc terminé la mise en place de notre page de recherche spécifique avec des filtres à facettes sur les résultats de notre recherche. Cela nous a permis de comprendre comment fonctionnent Search API et ses facettes en les utilisant pour créer une nouvelle recherche. Nous allons maintenant voir comment remplacer le bloc de recherche standard de Drupal par un bloc de recherche s’appuyant sur Search API. Multi-index searches : remplacer le bloc de recherche natif de Drupal Comme pour le reste, nous commençons par installer et activer le module Search API Multi-index Searches. Une petite précision Ce module va nous permettre de remplacer le bloc de recherche et la page de recherche par défaut, mais comme par défaut Search API ne gère pas la recherche multi-index, celle-ci n’est pas intégrée avec les autres modules contrib (Facet, Autocomplete, Spellcheck, etc.).

MÉTHODE Installer le module Search API Multi-index Searches par l’interface Télécharger le module : https://drupal.org/project/search_api_multi Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver le module dans la liste et l’activer.

MÉTHODE Installer le module Search API Multi-index Searches en ligne de commande avec Drush $ drush dl search_api_multi $ drush en -y search_api_multi

Ce module nous permet de créer une vue offrant un bloc de recherche multi-index (pour


rechercher dans nos nœuds et nos menus, puisque ce sont les deux index que nous avons créés). Dans cette vue, nous ajoutons un filtre Rechercher : fulltext search.

Figure 10–67 Vue basée sur Multi-index Searches

Une fois la vue créée, nous passons dans ses paramètres avancés pour afficher notre bloc de recherche (Filtre>Rechercher : Fulltext search) en tant que filtre exposé.

Figure 10–68 Filtre exposé de recherche multi-index

Pour créer le bloc de recherche, nous demandons à Views, via les options avancées, d’afficher le filtre exposé en tant que bloc.


Figure 10–69 Affichage d’un filtre de recherche exposé en tant que bloc dans Views

Retournons dans la configuration des blocs (Admin>Structure>Blocs) et désactivons l’affichage du bloc de recherche par défaut pour le remplacer par notre Exposed form : recherche_dans_tout_le_site-page.

Figure 10–70 Recherche dans tout le site

Si nous revenons sur n’importe quelle page de notre site, nous voyons notre filtre apparaître en tant que bloc.

Figure 10–71 Affichage du filtre exposé de recherche

Et voilà une nouvelle recherche dans notre site. À nous de créer les index pour les utilisateurs, les termes de taxonomie et tout ce que nous souhaitons indexer sur notre site. Indexer les fichiers joints avec Search Api Attachments et Apache Tika Les derniers éléments concernant la recherche sont l’indexation et la recherche dans les fichiers attachés à nos contenus. En effet, si nous décidons d’ajouter un champ fichier pour que les restaurateurs puissent mettre leur carte en pièce jointe, il serait intéressant que


notre moteur de recherche recherche également dans ces fichiers. Pour commencer, nous installons et activons le module Search API Attachments. MÉTHODE Installer le module Search API Attachments par l’interface Télécharger le module : https://drupal.org/project/search_api_attachments Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver le module dans la liste et l’activer.

MÉTHODE Installer le module Search API Attachments en ligne de commande avec Drush $ drush dl search_api_attachments $ drush en -y search_api_attachments

Avant de passer à la configuration du module, nous devons installer Tika. wget http://mir2.ovh.net/ftp.apache.org/dist/tika/tika-app-1.4.jar Nous récupérons le fichier tika-app-1.4.jar, que nous plaçons dans /var/ .

Nous allons maintenant configurer Search API Attachments pour qu’il utilise Tika. Rendons-nous dans la configuration via Admin>Configuration>Recherche et métadonnées>Search API>Search API attachments. Une fois le serveur Tika choisi, nous ajoutons le champ contenant nos fichiers dans notre index. Puis, dans les filtres, nous demandons à Search API d’extraire le contenu des fichiers.

Figure 10–72 Configuration de Search API Attachments


Figure 10–73 Ajout d’un champ fichier dans l’indexation des nœuds

Figure 10–74 Ajout du filtre pour l’extraction du contenu des fichiers

Nous réindexons le contenu de l’index des nœuds pour prendre en compte le contenu de nos fichiers.

Figure 10–75 Réindexation du contenu de l’index des nœuds

La figure suivante présente le résultat obtenu si nous faisons une recherche sur un mot contenu seulement dans l’un de nos fichiers (et non pas dans nos nœuds Drupal).


Figure 10–76 Résultat de la recherche sur un terme contenu dans un fichier

Nous en avons terminé avec la recherche de Drupal. À nous d’essayer les différentes possibilités offertes par Search API et Solr.


Gestion avancée des images avec Media

11

La mise en avant d’un contenu peut s’effectuer par l’intermédiaire de visuels ou en insérant des images dans le texte. Ce chapitre va monter comment partager un contenu multimédia pour illustrer nos contenus et améliorer notre page d’accueil.

SOMMAIRE Utiliser le module Media Réaliser un bandeau animé en slideshow


Insérer du multimédia Les images sont gérées à travers un module proposé nativement (Core) par Drupal. Cependant, si nous souhaitons disposer d’une galerie photo ou multimédia et l’intégrer dans un contenu, il faut alors la gérer comme un nœud. Nous devons donc créer un type de contenu et une gestion séparée. Le multimédia sert à illustrer les contenus des pages Internet dans notre projet. Il rassemble des images (PNG, JPEG, GIF...), des vidéos (MP4, MOV, FLV, SWF...) et des fichiers audio (MP3, WAV...), venant de sources internes ou externes (Dailymotion, Vimeo, YouTube...). Il existe différents modules capables de gérer ces fichiers : Media, Scald, Asset. Nous présenterons Media, qui propose une gestion multimédia améliorée.

Le module Media Présentation Media est un module qui étend les fonctionnalités de Drupal pour la gestion des fichiers et des éléments multimédias. Il propose une interface utilisateur unifiée où les éditeurs et les administrateurs peuvent télécharger, gérer et réutiliser les fichiers et les éléments multimédias à l’infini. Il est composé d’un module principal et d’ add-on pour se connecter plus facilement avec certains services web. Nous installons la version 2.x de Media pour bénéficier des nouvelles fonctionnalités. MÉTHODE Installer le module Media par l’interface Télécharger les modules Media, File entity, Media YouTube et Media Dailymotion : https://drupal.org/project/media https://drupal.org/project/file_entity http://drupal.org/project/media_youtube http://drupal.org/project/media_dailymotion Décompresser les archives dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver les modules dans la liste et les activer.

Dans la liste des modules de notre site, nous trouvons toutes les briques qui composent Media. MÉTHODE Installer le module Media en ligne de commande avec Drush $ drush dl media media_youtube file_entity media_dailymotion $ drush en -y media media_youtube file_entity media_dailymotion


Alternative Bien entendu, il existe d’autres plates-formes vidéo sur Internet, comme Vimeo : https://drupal.org/project/media_vimeo

Figure 11–1 Liste des extensions Media présentes lors de l’activation du module

Configuration La liste des extensions La configuration des extensions est importante car elle autorise l’utilisateur à charger (uploader) un certain nombre de formats de fichiers. Pour accéder à l’interface de configuration de Media, nous passons par celle de File entity (Admin/Config/Media/File-settings), pour obtenir l’écran de la figure suivante.


Figure 11–2 Liste des extensions prédéfinies à l’activation du module

Cet écran se décompose en quatre parties. Le champ Taille maximale de transfert limite la taille du fichier à charger. Si nous ne remplissons pas ce champ, il prend la valeur par défaut du serveur (celle qui se trouve dans le fichier php.ini à la valeur max_upload_size). Le champ Default allowed file extensions affiche les extensions de fichiers autorisées. Nous pouvons réduire ou compléter cette liste. Les champs Attribut Alt et Attribut Title définissent le contenu des attributs ALT et TITLE de la balise image, qui, dans nos pages HTML, affichent des informations sur l’image. L’information fournie par défaut peut être changée et le module Media propose une liste de mots-clés sous la forme de tokens. Différents modes d’affichage sont disponibles : dates, fichiers, utilisateurs, etc.

Figure 11–3 La liste des tokens disponibles par catégorie

Le module Ce module, si nous le laissons tel quel, est déjà prêt à l’emploi et l’ajout d’un champ de type Media est déjà disponible dans le type de contenu. Cependant, nous allons configurer la partie Wysiwyg pour éviter d’avoir notre galerie, l’écran de recherche et le formulaire


de chargement dans une même fenêtre. Pour accéder à l’interface de configuration Wysiwyg de Media, nous passons par Admin/Config/Media/Browser. Nous arrivons alors sur une page contenant l’ensemble des vues existantes.

Figure 11–4 Paramétrage du champ Media

L’écran de configuration propose différentes options à activer pour améliorer le module. Il permet entre autres d’habiller ce bloc en choisissant un des thèmes disponibles. Il est ensuite nécessaire de configurer ce qui sera affiché dans l’écran Wysiwyg. Si nous ne cochons aucune case, toutes les possibilités s’afficheront sur un seul écran au lieu de le faire sous forme d’onglets. Nous sélectionnons quelques options : Transférer permet d’utiliser la fonction de chargement ; Library affiche la galerie des fichiers précédemment transférés ; Web stocke un lien Internet (YouTube, Dailymotion...). L’autre partie de l’écran définit les types de fichiers disponibles qui pourront être chargés.


Figure 11–5 Paramétrage du champ Media (suite)

Ces options permettent, lorsque nous définissons un type de contenu, de l’associer avec la galerie multimédia. Nous allons sélectionner l’ensemble des possibilités.

Multimédia dans un champ Type de contenu Pour autoriser l’ajout d’un champ Media dans un contenu, nous nous rendons dans Admin>Structure>Types de contenu. Nous sélectionnons la ligne Article. Pour éviter de perturber le contributeur d’un site web, nous privilégions des champs différents : un champ multimédia ; un champ document.


Figure 11–6 Type de contenu vierge

Le champ multimédia Un champ multimédia se compose d’images, de vidéos et de fichiers audio. Ici, nous pouvons créer une galerie commune à l’ensemble des contenus si nous paramétrons ce widget correctement.

Figure 11–7 Ajouter un nouveau champ Image

Nous remplissons l’étiquette et sélectionnons le type Image. Ce qui varie par rapport à d’habitude est le choix de Media file selector. Ce nouveau widget a été rendu disponible avec l’activation des options (voir partie précédente). Après avoir cliqué sur le bouton Enregistrer, nous devons déterminer les paramètres du champ. La dernière partie de ce champ concerne la configuration de celui-ci qui sera gérée dans un contenu (voir figure 11-2) : champ obligatoire ; formats des images ; dimensions et poids des images ; possibilité de joindre un ou plusieurs fichier(s) ; etc.


Figure 11–8 Paramètres du champ

La première particularité de cette partie concerne l’affichage des onglets, entièrement personnalisable. Nous gardons l’ensemble des onglets définis au début du chapitre.

Figure 11–9 Configuration du sélecteur

L’autre particularité de l’écran concerne les liens externes pris en charge car ils apparaissent suivant les modules que nous avons activés.

Figure 11–10 Liste des liens pris en charge par rapport aux modules activés

Nous sauvegardons après avoir paramétré la configuration de l’affichage du champ. Le champ document Reprenons le même type de contenu que précédemment, c’est-à-dire Article. Nous allons ajouter un champ Fichier pour permettre de charger les fichiers PDF, DOC, ODT, etc. Grâce au widget Media File Selector, tous les documents seront disponibles sur le même principe qu’une galerie d’images.


Figure 11–11 Ajouter un nouveau champ Fichier

L’écran suivant configure le champ qui sera affiché dans le contenu : champ obligatoire ; taille des fichiers ; possibilité de joindre un ou plusieurs fichier(s) ; etc. Nous affinons la configuration des extensions des fichiers à uploader, pour les afficher sous la forme d’onglets.

Figure 11–12 Paramétrage du fichier pour un contenu

Nous sauvegardons après avoir paramétré la configuration de l’affichage du champ. Modifier la valeur du champ image Nous en profitons pour insérer le champ image associé à Media. L’intérêt de cela est d’associer une image à la bibliothèque multimédia ; si nous ne le faisions pas, nous serions obligés de recharger l’image. Pour cela, nous modifions le widget du champ Image.

Figure 11–13 Modification du widget


Le contenu Le contenu s’appuie sur les champs du type de contenu. Créons un Article (par l’URL node/add/article ou par le menu Ajouter un contenu>Article). Nous voyons différents boutons : Image, le formulaire natif de Drupal ; le bouton Multimedia créé pour les images à partir du type de contenu ; le bouton Document pour enregistrer les fichiers, créé à partir du type de contenu.

Figure 11–14 Les différents boutons dans un contenu Article

Le bouton Multimedia Nous utilisons le bouton Multimedia pour accéder à la gestion des images et vidéos que propose le module Media. Une nouvelle fenêtre apparaît pour afficher les différents onglets, définis dans la configuration du module. L’onglet Transférer sert à charger une nouvelle image, associée au contenu (nœud). Les paramètres proposés correspondent à la configuration du champ. Il est possible de les changer en retournant dans la configuration du type de contenu Article.

Figure 11–15 L’onglet pour charger une image

Pour insérer un fichier multimédia, l’opération s’effectue en deux temps. Tout d’abord,


avec le bouton Transférer, nous l’ajoutons à la fois dans notre galerie et au contenu en cours. Lorsque nous passons à la seconde étape avec le bouton Suivant, nous obtenons un écran de saisie composé de deux champs.

Figure 11–16 Texte alternatif

Ces champs sont utiles car ils proposent des informations sur le contenu du fichier multimédia qui sera affiché. L’onglet Web permet d’enregistrer un lien externe (YouTube, Dailymotion) sous la forme d’un nœud.

Figure 11–17 Onglet Web du bouton multimédia

L’onglet Library affiche l’ensemble des images qui ont été chargées dans les autres nœuds. Nous avons la possibilité de filtrer son contenu : sur le nom de fichier ; sur le type de fichier ; en effectuant un tri ; ou en choisissant un ordre.


Figure 11–18 Onglet Library du bouton multimédia

Retournons dans l’onglet Transférer et chargeons une image.

Figure 11–19 Chargeons une image.

En cliquant sur le bouton Suivant, nous obtenons un formulaire pour préciser le contenu des balises.

Figure 11–20 Les balises du fichier

Puis nous cliquons sur le bouton Enregistrer. Nous obtenons dans notre contenu l’affichage de la miniature que nous venons de charger dans notre médiathèque.


Figure 11–21 Contenu illustré

Bien entendu, il est possible de changer notre sélection, en appuyant sur le bouton Retirer. Le bouton Document Il se présente de la même façon que le bouton Multimedia, que nous venons de présenter. La seule différence correspond aux extensions différentes.

Multimédia dans le body (content) Le body correspond, en termes techniques, au content. Celui-ci bénéficie des nombreux avantages présentés au début du chapitre. Ainsi, la personnalisation de notre texte s’effectue avec une image, une vidéo, etc. Configurons Drupal pour autoriser un contributeur à illustrer son contenu.

Installation du module Wysiwyg MÉTHODE Installer le module Wysiwyg par l’interface Télécharger le module : https://drupal.org/project/wysiwyg Décompresser l’archive dans notre dossier /sites/all/modules. Aller à la page des modules de notre site (Admin/Modules). Trouver le module dans la liste et l’activer.

MÉTHODE Installer le module Wysiwyg en ligne de commande avec Drush $ drush dl wysiwyg $ drush en -y wysiwyg

Figure 11–22 Module Wysiwyg installé


Configuration Wysiwyg Wysiwyg signifie « what you see is what you get » (ce que vous voyez est ce que vous obtenez) : une barre d’icônes s’affiche dans la zone content pour faciliter la mise en forme d’un texte, et la mise en page que nous voyons à l’écran (les couleurs, le gras, les paragraphes) est celle que nous créons pour notre site, sans utiliser les balises HTML correspondantes. Le CMS Drupal propose différentes bibliothèques, mais nous choisirons CKEditor. Depuis ses dernières versions, celle-ci intègre la fonction Mediaembed, permettant d’utiliser les fonctionnalités du module Media. Incompatibilité Il ne faut pas utiliser le module wysiwyg_mediaembed-7.x car il n’est pas compatible avec les versions récentes de CKEditor.

Installation de la bibliothèque CKEditor Pour choisir la bibliothèque compatible avec notre CMS, nous nous rendons dans la configuration du module Wysiwyg.

Figure 11–23 Choix de la bibliothèque

MÉTHODE Installer le module CKEditor par l’interface Télécharger le fichier en utilisant le lien de la figure 11-23 (l’adresse exacte est donnée par Drupal pour obtenir la bonne version de CKEditor) : http://ckeditor.com/ Extraire l’archive vers un nouveau dossier : sites/all/libraries/ckeditor.

Pour activer l’installation de la bibliothèque, nous rafraîchissons la page, sélectionnons l’éditeur et cliquons sur Edit.


Figure 11–24 Sélection CKEditor

Configuration Nous arrivons à l’écran de sélection des boutons à afficher dans notre barre. Nous sélectionnons la case Media browser et sauvegardons.

Figure 11–25 Sélection de Media browser

Lorsque nous validons l’icône affichée dans la barre Wysiwyg, une alerte peut apparaître sous la forme suivante.

Figure 11–26 Message d’alerte

Pour faciliter l’affichage dans un contenu lors de la saisie, nous devons convertir les valeurs de code en illustrations. Pour cela, nous nous rendons au lien indiqué pour cocher la case Convert Media tags to markup : lors de la saisie d’un nouvel article, les contributeurs verront alors un message compréhensible. Il est possible d’accéder ultérieurement Configuration>Rédaction de contenu.

à

cet

écran

à

partir

du

menu


Figure 11–27 Activer la conversion des balises de Media

Un message de confirmation nous informe que le format de texte Filtered HTML que nous venons de configurer a bien été mis à jour.

Figure 11–28 Le format Filtered HTML a bien été mis à jour.

Lors de la validation de celui-ci, nous devons (re)cocher la case Media browser pour que ce pictogramme soit bien pris en compte. Nous avons montré comment effectuer une telle action pour la barre Filtered HTML. Nous devons refaire la même opération pour la ligne Full HTML.

Création d’un article Maintenant que nous avons configuré notre nouvelle barre, nous créons un article. À l’emplacement du contenu (Body), la barre Wysiwyg apparaît avec une icône Media, donnant accès à la bibliothèque.


Figure 11–29 Icône Media affichée

Lorsque nous cliquons sur cette icône, une fenêtre apparaît, qui contient les différents onglets présentés précédemment dans ce chapitre. Son utilisation est identique à ce que nous avons déjà expliqué : nous choisissons l’onglet Library pour sélectionner une image déjà téléchargée auparavant.

Figure 11–30 Sélection de l’image

Lors de la validation de notre choix, un écran affiche les informations en mémoire sur cette image.


Figure 11–31 Renseignements connus sur l’image choisie

Ces informations peuvent être ajustées si elle ne nous conviennent pas. Nous cliquons sur le bouton Submit pour valider notre enregistrement.

Figure 11–32 Résultat de l’insertion de l’image

Nous en profitons pour ajouter un titre à notre article et un contenu associé à côté de notre image.

Figure 11–33 Complément du contenu de notre article


Nous sauvegardons le tout, pour obtenir le résultat final de notre article.

Figure 11–34 Résultat de notre article

Nous retrouvons notre titre, le contenu du champ Body et l’image chargée à partir du bouton Multimédia. La mise en forme du contenu pourra bien sûr être améliorée, en sélectionnant l’onglet Modifier qui se trouve en haut à droite de la page (voir au chapitre 8).

Créer une animation bandeau En attirant le regard vers quelque chose qui bouge, les animations mettent en valeur notre site web et le rendent plus attractif. Nous allons créer une bannière rotative, qui sera composée de deux éléments : un type de contenu ; une vue au format bloc.

Installation du module Views Slideshow Il existe différentes manières de réaliser une animation. Nous proposons une solution parmi d’autres, basée sur le module Views Slideshow. MÉTHODE Installer le module Views Slideshow par l’interface Télécharger les modules Views Slideshow, Views Slideshow Cycle et Link : https://drupal.org/project/views_slideshow https://drupal.org/project/views_slideshow_cycle https://drupal.org/project/link Décompresser l’archive dans notre dossier /sites/all/modules.


Aller à la page des modules de notre site (Admin/Modules). Trouver le module Views Slideshow dans la liste et l’activer, ainsi que Cycle et Link.

MÉTHODE Installer le module Views Slideshow en ligne de commande avec Drush $ drush dl views_slideshow, views_slideshow_cycle, link $ drush en -y slideshow, views_slideshow_cycle, link

Configuration du cache Avec Drupal 7, Imagecache, qui fait partie des modules de base, est utilisé en tant que modèle d’image. Cette possibilité de configurer le cache image est importante pour définir la dimension à afficher dans notre bandeau. La configuration de celui-ci est disponible à partir du menu Admin>Config>Media>Image-styles. Nous définissons tout d’abord un nom de style de l’image, par exemple bandeau 930x240.

Figure 11–35 Nom du style de l’image

Lors de la définition d’un nouveau style, il est possible d’appliquer différents filtres sur nos images mises en cache. Nous appliquons ensuite un ou plusieurs effets pour améliorer le rendu. Nous choisirons le redimensionnement automatique si les photos chargées ultérieurement ne correspondent pas à la résolution souhaitée.

Figure 11–36 Effet supplémentaire

Nous sauvegardons ensuite ces modifications.

Création du type de contenu Nous créons un type de contenu spécifique pour gérer ce bandeau animé. Pour cela, nous


nous rendons sur l’écran Admin>Structure>Types de contenu. Nous renseignons le nom (slideshow) et une courte description.

Figure 11–37 Création d’un type de contenu pour le bandeau animé

Nous décochons : Publier à Home page ; les auteurs et les dernières informations ; les commentaires ; le lien du menu. Après avoir sauvegardé, nous créons les champs dont nous avons besoin. Nous ajoutons également deux nouveaux champs : un champ field_slide_image ; un champ field_slide_lien. De plus, nous supprimons le champ Body qui est ici inutile.

Figure 11–38 Création d’un type de contenu Le widget Image n’est pas associé au widget Media car les bandeaux sont gérés séparément à cause de leurs dimensions.

Après avoir enregistré la configuration du champ, nous paramétrons certaines informations : champ obligatoire ; nom d’un répertoire : slideshow ;


réglage des tailles et des résolutions ; activation des champs Alt et Titre.

Figure 11–39 Paramètres du champ image

Le champ slide lien est créé selon le même principe. L’objectif, en associant une image et un lien, est de faire pointer l’image du bandeau vers un contenu node ou externe.

Nous personnalisons uniquement la partie Titre du lien car celui-ci sera notre image. C’est pourquoi nous cochons Aucun Titre.

Figure 11–40 Paramètres du champ slide lien

Création d’un contenu Nous ajoutons différents contenus liés à notre exemple à partir de l’interface (Contenu>Ajouter du contenu>slideshow).

Figure 11–41 Saisie d’un contenu image

Nous obtenons les différents champs de saisie créés et remplissons :


le nom ; une image ; un lien externe ou interne (alias ou node).

Figure 11–42 Résultat de la saisie d’un contenu

Bien entendu, nous devons saisir plusieurs contenus pour obtenir l’animation de notre bandeau.

Afficher notre bandeau Nous affichons notre bandeau slideshow dans une vue, que nous rendons visible uniquement pour la page d’accueil du site web. C’est pourquoi nous configurons notre vue pour le rendre disponible dans un bloc. Pour cela, nous devons nous rendre dans la structure puis cliquer sur Admin>Structure>Views et ajouter une nouvelle vue : nom : slideshow_vue ; un descriptif ; Afficher un contenu de type slideshow ; case Créer une page décochée ; case Créer un bloc cochée ; format d’affichage : Slideshow sur champs.


Figure 11–43 Création d’un bloc vue

Nous cliquons sur Sauvegarder et continuer pour configurer notre vue et obtenir l’écran suivant. Pour afficher notre animation, nous avons besoin d’une image et de son lien associé. Pour cela, nous supprimons la ligne de titre qui ne nous est pas utile et nous ajoutons le champ lien et l’image de notre node : slideshow.

Figure 11–44 Détail de la vue Voir le chapitre 5 (Affichage avancé) qui traite du module Views.


Figure 11–45 Ajouter des champs

La configuration des champs doit s’effectuer dans un ordre précis : nous ajoutons d’abord le lien et ensuite l’image. Nous décochons l’étiquette (label) du champ lien de notre configuration puis nous sauvegardons. Cochons enfin la case Exclure de l’affichage.

Figure 11–46 Configuration du champ lien

Nous décochons l’étiquette du champ image de notre configuration et nous choisissons le style d’image que nous avons créé précédemment.


Figure 11–47 Configuration du champ image

Pour associer l’image à son lien, nous restons sur le même écran de configuration et descendons jusqu’à la partie Réécrire les résultats. Nous cochons la case Afficher ce champ en tant que lien et remplissons la case avec le type fied_slide_lien.

Figure 11–48 Associer image et lien

Les autres possibilités pour remplir le chemin du lien sont listées dans la partie Motifs de remplacement.


Figure 11–49 Motifs de remplacement

Et nous sauvegardons à nouveau.

Améliorer l’animation Pour améliorer les effets de transition entre deux images de l’animation, il est possible de personnaliser les paramètres de la zone Format. Pour effectuer des transitions entre deux images, nous nous appuyons sur jQuery et son extension cycle. jQuery:cycle http://malsup.com/jquery/cycle

Nous copions l’extension dans le dossier jquery.cycle du dossier libraries.


Figure 11–50 Emplacement de la bibliothèque

Après avoir copié ce fichier dans son emplacement, nous nous rendons aux options de style du slideshow. Les effets de transition sont nombreux. Nous appliquons l’effet choisi et sauvegardons notre vue.

Figure 11–51 Choisir un effet

Publier notre vue Pour publier notre vue, nous la plaçons dans une région de notre thème qui a été créée dans le chapitre 8 de l’ouvrage. Pour cela, nous nous rendons dans la partie bloc de l’administration (Admin>Structure>Bloc) et affichons la vue slideshow_vue dans la région Entête.


Figure 11–52 Afficher la vue dans une région

Ensuite, nous la configurons. Nous ne souhaitons pas afficher le titre du bloc : nous mettons <none>.

Figure 11–53 Afficher la vue dans une région

Comme nous souhaitons afficher l’animation slideshow sur la page d’accueil, nous ajoutons le critère <front>.

Figure 11–54 Spécifier la page

Nous sauvegardons. Ce bloc est désormais visible sur notre site Internet de développement.


Figure 11–55 Résultat de la page d’accueil de notre site


Déploiement

12

Notre projet est désormais terminé. Il nous reste une dernière étape à franchir : il faut le déployer sur Internet. Pour cela, nous migrerons nos fichiers du serveur de développement vers notre serveur de production.

SOMMAIRE Déploiement par FTP et phpMyAdmin Utiliser Drush et Drush make pour industrialiser les déploiements


Déploiement avec FTP et phpMyAdmin Nous allons démarrer avec une méthode graphique que nous pouvons utiliser chez n’importe quel hébergeur de site web.

Transférer les fichiers avec FileZilla Il s’agit du moyen le plus ancien et le plus rapide car il suffit d’utiliser un client FTP pour copier nos fichiers. Pour cela, notre hébergeur nous a fourni des codes, notamment un hôte, un identifiant et un mot de passe, éventuellement complétés par un port spécifique. Nous allons utiliser le logiciel libre FileZilla. https://filezilla-project.org/

Une fois le logiciel installé (et les codes sous la main), découvrons son interface.

Figure 12–1 L’interface à l’ouverture de FileZilla

Dans le cadre du haut, nous entrons les identifiants.

Figure 12–2 Les identifiants données par l’hébergeur sont à renseigner dans ce cadre.

Une fois les identifiants saisis, la liaison à l’hébergeur est activée par le clic sur le bouton Connexion rapide. Une confirmation est affichée par le log de connexion au serveur, dans la fenêtre juste en dessous du cadre d’identification.


Figure 12–3 Affichage du log de connexion au serveur

Dans la partie centrale de l’écran, nous trouvons deux arborescences : à gauche, les fichiers se trouvant sur notre ordinateur ; à droite, les fichiers se trouvant sur le serveur. Pour envoyer notre site sur le serveur, nous glissons/déposons des fichiers de Drupal depuis notre ordinateur vers le serveur (donc de la gauche vers la droite).

Figure 12–4 Les fichiers se trouvant sur notre machine (à gauche) et sur le serveur (à droite)

Des informations sur l’état du transfert des fichiers s’affichent en bas de notre site comme la liste des fichiers transférés avec succès.

Figure 12–5 La liste des fichiers en cours de transfert, échoués et réussis

Une fois le transfert effectué, si nous nous rendons à l’adresse de notre site, nous obtenons un message d’erreur.

Figure 12–6 Page d’erreur de connexion à la base de données

En effet, nous avons bien transféré les fichiers, mais il nous reste deux étapes avant d’en avoir terminé avec le déploiement de notre site sur un serveur de production. La première consiste à modifier la chaîne de connexion à la base de données dans le fichier settings.php. Celui-ci se trouve dans sites/default sur notre serveur. Il faut donc


remplacer les informations de connexion à la base de données par celles fournies par votre hébergeur. $databases = array ( 'default' => array ( 'default' => array ( 'database' => 'nomdemabasededonnees', 'username' => 'logindemabasededonnes', 'password' => 'motdepassedemabasededonnees', 'host' => 'localhost', 'port' => '', 'driver' => 'mysql', 'prefix' => '', ), ), );

Une fois cela terminé, nous obtenons un autre message d’erreur sur notre site.

Figure 12–7 Erreur nous signalant l’absence des tables SQL nécessaires à Drupal

Notre site est donc bien connecté à la base de données, mais les tables sont absentes de cette dernière.

Transfert de la base de données avec phpMyAdmin Nous allons exporter notre base de données locale avec phpMyAdmin vers la base de données située sur le serveur de production. Au préalable, il faut se connecter sur notre site en tant qu’administrateur et vider tous les caches via Admin>Configuration>Développement>Performance. Il faut penser également à désactiver la réécriture d’URL via Admin>Configuration>Recherche et métadonnées>URL simplifiées. Pour cela, nous utilisons notre phpMyAdmin installé en local, nous nous rendons dans la base de données de notre site et sélectionnons l’onglet Exporter.


Figure 12–8 L’onglet Exporter de phpMyAdmin

Nous laissons la méthode rapide et le format SQL pour le fichier et cliquons sur Exécuter. Nous obtenons alors un fichier nommé nomdemabaselocale.sql. Nous allons maintenant importer ce fichier chez l’hébergeur qui nous a fourni l’URL de phpMyAdmin, un identifiant, un mot de passe et le nom de la base. Nous sélectionnons la base concernée et cliquons sur l’onglet Importer. Dans le sélecteur de fichiers, nous retrouvons celui que nous venons d’exporter/importer. Nous laissons les options cochées par défaut et cliquons sur Exécuter en bas de page. Une fois l’import terminé, nous retournons sur notre site.

Figure 12–9 Importation de notre base de données


Figure 12–10 Notre site est en ligne.

Nous avons donc terminé la mise en ligne de notre site. Pour la mise à jour de celui-ci, il faudra réutiliser FileZilla afin de transférer les nouveaux modules et fonctionnalités développés. Le FTP et phpMyAdmin sont donc des solutions pour démarrer un site web. Cependant, en cas de mises à jour très régulières de notre site ou d’ajout fréquent de fonctionnalités, nous aurons rapidement besoin d’une autre solution.

Déploiement avec Drush Drush et les alias pour déployer facilement Nous allons utiliser Drush avec une connexion SSH pour synchroniser notre serveur de développement (notre propre machine en l’occurrence) et celui de production. Pour cela, nous créons un fichier aliases.drushrc.php dans un nouveau répertoire sites/all/drush. Ce fichier demandera directement à Drush de synchroniser nos fichiers locaux (les features que nous avons modifiées par exemple) et ceux présents sur le serveur de production. Voici les informations que nous renseignons. Elles seront à adapter en fonction des serveurs. Fichier aliases.drushrc.php <?php //Alias pour le serveur de développement $aliases['dev'] = array( 'uri' => 'localhost', 'root' => '/var/www/drupal', 'remote-user' => 'kovalsky', ); // Alias pour le serveur de production $aliases['prod'] = array(


'uri' => 'bookdev.hellodesign.fr', 'root' => '/var/www/bookdev', 'remote-user' => 'bookdev', ?>

Ces alias définissent au minimum trois types d’information. L’uri est l’adresse du site (URI). Le root est la racine de nos fichiers Drupal. Le remote-user est l’utilisateur autorisé à se connecter en SSH. Une fois ce fichier créé, nous utilisons de nouvelles commandes Drush. Par exemple, synchronisons le dossier dans lequel nous avons ajouté de nouveaux modules lors de notre développement : drush rsync @dev:sites/all/modules/ @prod:sites/all/modules/

Nous synchronisons de la sorte les fichiers du répertoire sites/all/modules de notre site de développement vers notre serveur de production. Pour synchroniser notre base de données, nous allons par exemple récupérer les dernières données écrites sur notre site avec la commande suivante : drush sqlsync --cache @prod @dev

La syntaxe est toujours la même : nous désignons d’abord l’endroit depuis lequel les données (base de données ou fichiers) viennent, puis l’endroit où nous voulons les récupérer en utilisant les alias créés précédemment (avec le @nomdemonalias que nous avons défini dans le fichier aliases.drushrc.php). Pour automatiser nos mises en production, nous pouvons ainsi créer un fichier Bash qui ressemblerait au suivant. Exemple d’un fichier synchro.sh automatisant la mise en prodution # !/bin/bash # Script de mise en production de nouvelles fonctionnalités Drupal // On commence par vider les caches sur la production. drush @prod cc all // On récupère la base de production. drush sql-sync @prod @dev // On fait un revert sur nos features en local avec la base de production. drush @dev fra -y // On envoie les fichiers modules du dev vers la production. drush rsync @dev:sites/all/modules @prod:sites/all/modules // On synchronise la base de développement vers la base de production. drush sqlsync @dev @prod

Nous n’avons plus qu’à lancer le script synchro.sh pour effectuer chaque mise à jour de


notre site.

Drush make Drush make est un outil très puissant si nous travaillons simultanément sur plusieurs projets Drupal. C’est un moyen rapide de déployer Drupal, avec des modules contrib et des bibliothèques externes, sans avoir besoin de les télécharger manuellement. Le principe est simple : nous renseignons un fichier make avec les modules et les bibliothèques souhaités, puis nous demandons à Drush de l’utiliser pour déployer notre site Drupal. Construisons ensemble ce fichier, que nous appellerons bookdev.make. Fichier bookdev.make ; Base Drupal core = 7.x ; La version de l'API de Drush make api = 2 ; Modules ; Si aucune version n'est précisée, Drush installe la dernière version stable du module projects[ctools][subdir] = "contrib" projects[devel][subdir] = "contrib" projects[devel_themer][subdir] = "contrib" projects[entity_api][subdir] = "contrib" projects[features][subdir] = "contrib" projects[jquery_update][subdir] = "contrib" projects[libraries][subdir] = "contrib" projects[panels][subdir] = "contrib" projects[pathauto][subdir] = "contrib" projects[services][subdir] = "contrib" projects[token][subdir] = "contrib" projects[views][subdir] = "contrib" projects[webform][subdir] = "contrib" projects[wysiwyg][subdir] = "contrib" ; Themes projects[zen][type] = "theme" ; ; ; ;

Bibliothèques Merci de suivre le modèle suivant. Le type peut être get, git, bzr ou svn et l'URL est celle de téléchargement.

libraries[ckeditor][download][type] = "file" libraries[ckeditor][download][url] = "http://ckeditor.com/onlinebuilder/releases/minified/4.3.3/moono/4.3.3/ckeditor_4.3.3.zip" libraries[ckeditor][directory_name] = "ckeditor" libraries[ckeditor][destination] = "modules/contrib/ckeditor"

Nous avons donc déclaré la version du cœur de Drupal utilisé (la 7.x), les modules à télécharger, ainsi que notre thème et notre bibliothèque CKEditor.


Pour lancer notre installation, il nous suffit d’exécuter la commande suivante : drush make bookdev.make bookdev -y

L’option -y répond systématiquement oui aux demandes de téléchargement de Drush, ce qui est très pratique pour appeler cette commande dans un script Bash par exemple.

Nous avons ainsi un Drupal prêt à être installé en appelant le fichier install.php. Si nos modules, nos features et nos thèmes sont disponibles sur un serveur, nous pouvons même les insérer dans ce fichier make. Si notre module bookdev_menus est sur github, il nous suffira d’ajouter les lignes suivantes à notre fichier make. Fichier bookdev.make (complément) projects[bookdev_menus][type] = module projects[bookdev_menus][download][type] = git projects[bookdev_menus][download][url] = git://github.com/bookdev/bookdev_menus.git

Voilà la manière manuelle et la plus générique possible de créer ces fichiers make. Nous allons présenter deux autres méthodes. La première est une méthode graphique avec un service en ligne : drushmake.me. Ce site permet de sélectionner des modules, des bibliothèques et des thèmes, puis de générer notre fichier make. http://drushmake.me/

Figure 12–11 La page d’accueil et de sélection de drushmake.me


Une fois le bouton Generate cliqué, drushmake.me nous fournit le fichier make.

Figure 12–12 Le fichier généré par drushmake.me

Ce fichier contient donc la version de Drupal utilisée, ainsi que les modules que nous avons sélectionnés lors de la configuration. Toutefois, cette façon de faire présente un inconvénient : les versions de Drupal et de ses modules sont inscrites en dur dans le fichier et cela nous obligera donc à recréer ce dernier à chaque nouvelle version. Une autre façon de générer un fichier make est de partir d’un site Drupal existant. Nous nous positionnons dans le répertoire de ce site, puis nous lançons la commande suivante : drush generate-makefile /bookdev-auto.make

Nous récupérons alors un fichier make avec les mêmes problématiques que celui généré par drushmake.me. L’utilisation d’un fichier make facilite grandement le déploiement des sites Drupal et des modules que nous utilisons régulièrement. À nous de combiner toutes ces commandes Drush et ces scripts pour les adapter à notre propre architecture. Le fichier make gagnera à être versionné avec le code de nos sites ; il évoluera ainsi en fonction de nos besoins.


Index

.htaccess 13 .info 41, 44, 101, 119, 121, 143, 162-167, 170, 190 .install 64, 89, 92, 122, 141, 143 .module 41-42, 44, 65-66, 68, 72, 101, 106, 119, 143, 145, 189-190, 193-194, 196 .pages.inc. 69 .rules.inc 122 .rules_defaults.inc 119 .test.php 210-211, 219 A action 43, 47-49, 112-113, 117-118, 121, 125, 127, 131 alias 299-300 aliases.drushrc.php 299-300 AMP 7, 12 animation 282, 290 Apache 6, 11, 13-15 API 30, 41-42, 64, 101, 106, 109, 115, 131, 140 Apparence 167 assertEquals 212 Atoum 209 audio 264 automatisation 209 B base de donnÊes 296-297, 300 bibliothèque 40, 277, 279, 300, 302 bloc 164-165, 167, 170, 173-174, 178, 197, 200, 224, 228, 235, 246-248, 256-259, 286, 291 body 279 bookdev.make 301-302 bootstrap 208, 211-212, 219 bundle 65-66, 69, 75, 90, 143, 155 C cache 106, 120, 282, 297 Captcha 56 champ 34, 36, 54, 58-59, 61, 63-64, 68, 71, 75, 80, 87-91, 99, 103, 109, 131, 134-135, 142-143, 147, 149, 155, 182, 224, 235, 260, 267-269, 271-272, 284, 286-287 CKEditor 276-277, 301 commentaire 36, 56, 224


condition 121, 124-125, 127 configuration 5, 16, 22, 28-29, 40, 45, 61, 75, 77, 83 connexion 295 content 275-276 contenu 44, 47, 197, 285 contexte 49 CRUD 189-190 CSS 158, 163 CTOOLS 198 Current Search Blocks 245 D débogage 30 déclencheur 43, 45, 47-48, 112-113, 117, 123, 131 dépendance 101 déploiement 294, 296, 299, 303 Devel 29, 182 DevelThemer 31 Diff 83 DocumentRoot 15 droit 55, 129, 131, 139, 144, 146, 225, 235, 251 drupal_render 175 Drush 20, 26-29, 31, 57, 76, 94, 115, 129, 131, 145, 184, 198, 230-231, 237, 245, 250, 252, 254, 257, 260, 265, 276, 282, 299, 302 Drush make 300 drushmake.me 302 E Eclipse PDT 22 endpoint 185, 187, 196 entité 35-36, 47, 64-65, 68-70, 72-73, 75, 89-90, 99, 106, 109, 119, 131-134, 142-143, 145, 189, 200, 229-230, 234-235, 237 entity 35 Entity API 229 état 132-133 événement 121-122, 124 extension 43, 265 F Facet API 240, 245 facette 245-248 feature 302 Features 75-76, 82-83 fichier joint 271 field 36, 64 field_create_field 91


field_create_instance 91 FileZilla 294, 298 filtre contextuel 98, 104 FTP 294 G gabarit 31 galerie 264, 269 gestionnaire de versions 25 GIT 25-26 git 83 group manager 148 groupe d'utilisateurs 145, 147 H handler 109 header 171 Honeypot 57 hook 37, 42, 212 _menu 37 _menus_ ressource_access() 196 ressource_create() 193 ressource_delete() 195 ressource_index() 195 ressource_retrieve() 195 ressource_update() 194 bookdev_preprocess_user_login_block() 175 bookdev_theme() 175 default_rules_ configuration() 119 hook_action_info 45 hook_basic_action 47 hook_block_info 43 hook_help 43, 45 hook_menu 46 hook_node_sticky_action 48 hook_page_alter 42 hook_unblock_user_action 47 menu_for_all__help() 212 menus.install() 141 menus_delete_menu() 190 menus_get_menu() 189 menus_permission() 145 menus_ressource_


services_ressources() 190 menus_ressource_perm() 193 menus_utilisateurs_install() 143 menus_views_api() 101, 107 menus_views_data() 107 menus_write_menu() 189 repas_views_default_views() 102 restaurant_rules_ rules_action_info() 125 rules_condition_info() 124 rules_data_info() 123 rules_event_info() 123 schema() 122 update_table() 126 view_list() 125 views_condition() 125 views_pre_render() 124 hook menus menus_addmenu() 70 menus_addmenu_submit() 71 menus_admin() 70 menus_display_one() 73 menus_edit() 73 menus_edit_delete() 75 menus_edit_submit() 74 menus_edit_validate() 74 menus_entity_info() 65-66 menus_install() 89-91 menus_load() 73 menus_menu() 68-69, 72 menus_schema() 64 menus_title() 73 menus_type_load() 69 menus_type_title() 69 menus_uninstall() 92 menus_uri() 68 menus_validate() 71 hosts 15 HTML 5 158, 187 html.tpl.php 165, 171 I IDE 21-23 image 264, 272, 274, 279, 282, 284, 286-288 Imagecache 282


index 230, 234, 237, 240, 251, 258, 260 indexation 227, 235, 260 install.php 302 installation 15-16, 20, 24-26, 28-29, 31, 57, 79, 89, 94, 115, 129, 131, 145, 184, 198, 229-231, 237, 245, 250, 252-254, 257, 260, 264-265, 276-277, 282 instance 91 J JavaScript 31, 164 jQuery 31, 188 L layout 200-201, 203-205 lien 286-288 log 228, 295 logo 170 logo.png 170 M make 302 Media 264-265, 267-268, 272, 279 media queries 162 menu 37, 46, 57, 68-69, 170, 224 mise à jour 298 modération 56 module 28, 31, 35, 37, 40, 43, 48, 57, 64, 75, 79, 82-83, 89-92, 94, 98, 101, 105-106, 112, 115, 119-121, 128-129, 131, 144-145, 166, 184, 190, 197-198, 211, 218, 224, 226, 229-231, 237, 245, 247, 250, 252-254, 257, 260, 264-265, 276-277, 282, 287, 299-302 multimédia 264, 269, 272, 275 my.cnf 13-14 MySQL 6, 11, 14 N Netbeans 23 node 34, 178-179, 284 node.tpl.php 178-180, 182 nœud 34, 36, 44, 49, 146, 167, 179, 186-187, 189, 198, 213, 224, 228, 230, 235, 240, 264, 273-274 O Organic Groups 145 Override node options 128-129 P page 197-198, 200-201, 204, 213 page.tpl.php 171, 178, 180 page_bottom 165


page_top 165 Panelizer 197-198, 200 Panels 166, 197-198, 200, 204 PATH 211, 219 permission 128-129, 138, 141, 144-146, 148, 150, 152-155, 193, 196, 251 PHP 6, 13, 22-23, 27, 30 php.ini 13 PhpMyAdmin 297 phpMyAdmin 15, 294 PHPUnit 209-210, 212, 218 preproccess 167 processus 132 profil 142 publication 44 R recherche 224-226, 228-230, 237, 245, 247-248, 251, 253-260, 262 recherche avancée 226 région 164-165, 170-171, 173, 197, 224, 291 règle 115-119, 127, 130-131 relation 99 Responsive Design 158-159, 168 ressource 186-187, 189-190, 193, 196-197 rôle 130, 133, 135, 138-141, 144, 148, 152-153, 155 Rules 115, 117-118, 121, 123, 128, 131 rules_invoke_event_by_args() 124 S scénario 215 screenshot.png 170 Search 224 Search API Solr 231 Search Facets 245 Search API 229-231, 234, 237, 250, 260 Search API Attachments 260 Search API Autocomplete 250 Search API Multi-index Searches 257 Search API Page 237 Search API Saved Searches 253-254 Search API Spellcheck 252 sécuriser 234 Select 200 Selenium HQ 214, 218 serveur 230, 232-235, 237, 260, 296, 299, 302 Services 184, 186, 189


settings.php 296 SimpleTest 209-210, 218 Solr 229-230, 232, 234-235, 250 sous-thème 163, 165 SQL 297 SSH 299 starterkit 162, 167 structure 286 style.css 168, 181 synchro.sh 300 synchronisation 299 T tâche cron 227-228, 235-236 taxonomie 44, 63, 84-86, 89, 91, 224, 235, 237, 260 Taxonomy 90 template 167, 170-171, 175, 177, 183, 200-201, 204 template.php 167, 170, 174 terme 85-86, 89-91, 224, 235, 237, 260 test fonctionnel 214, 218-219, 222 test unitaire 209-211, 214, 218, 222 thème 31, 40-41, 56, 159-160, 162-167, 291, 302 theme-settings.php 167 Tika 260 token 266 transfert de fichier 294, 297 transition 133, 290 Trigger 112 trigger 43 type de contenu 34, 52-54, 56, 58, 64, 76-77, 79-80, 87, 129, 147, 149, 153, 199, 264, 267, 272, 283 ajouter 52 U URI 299 user_role_load_by_name() 141 user-login.tpl.php 175, 178 utilisateur 36, 44, 47-49, 52-53, 128-129, 138, 140-142, 144-148, 150, 152, 158, 186, 195, 214, 224, 226, 228, 235, 237, 251, 253-256, 260 V validateur 44 vidéo 264, 272 Views 94, 98, 101, 106, 109, 121, 123, 132, 146, 240, 259, 287 Views Slideshow 282 views_handler_filter_equality 110


Vimeo 265 VirtualHost 14 vocabulaire 84-90, 92 vue 95, 98-99, 101-102, 105-106, 121, 124, 127, 251-252, 258, 286, 291 W webservice 184-187, 189, 197 Workflow 131, 134-135 workflow 128-129, 131-134, 136 WYSIWYG 40, 82 Wysiwyg 267, 276-279 X Xampp 7, 10-11, 13 XML 187 Z Zen 159-160, 162-163, 165-167, 183


Pour suivre toutes les nouveautés numériques du Groupe Eyrolles, retrouvez-nous sur Twitter et Facebook @ebookEyrolles EbooksEyrolles

Et retrouvez toutes les nouveautés papier sur @Eyrolles Eyrolles


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.