00:00:00

Formation Développement Drupal

Notes

Qui suis-je ?

Pierre RINEAU

@pounard sur le web

Développeur Drupal depuis 2008

Notes

Objectifs de la formation

  • Appréhender l'environnement de développement Drupal
  • Comprendre les concepts et l'API Drupal
  • Créer un module
  • Modifier le comportement d'un module existant
  • Créer un profil d'installation

Prérequis

  • Connaitre PHP et avoir développé quelques scripts
  • Avoir construit un site avec Drupal
  • Notions de HTML, CSS, JavaScript et requêtes SQL

Notes

Planning

Notes

1er jour

  • Environnement de développement
  • Quelques outils utiles (Drush, Git, Devel)
  • Bonnes pratiques, standards de code, documentation
  • Architecture de Drupal
  • Les concepts de base
  • Création du squelette d'un module
  • Les premiers hooks

2ème jour

  • Les différentes API
  • Les nœuds, le contenu et les droits d'accès
  • L'alteration des modules

Notes

3ème jour

  • La form API
  • Les mails
  • Créer un thème basique
  • Les profils d'installation




Slides disponibles en ligne

http://git.io/LrEKVg

Notes

Environnement de développement

Notes

Le serveur Web

  • xAMP

    • Apache - Souvent remplacé par Nginx + PHP-FPM
    • MySQL - Drupal est optimisé pour
    • PHP - version de 5.3 à 5.6 (nous utiliserons 5.5)
  • D'autres possibilités de base de données : Oracle, IIS, PostgreSQL

  • Languages que nous utiliserons :

    • PHP
    • SQL
    • HTML, CSS, JavaScript

On utilisera dans cette formation UwAmp ou n'importe quel autre déjà installé sur votre machine.

faire un tour de table des compétences et de l'expérience PHP

prévenir que le formateur ne peut pas intervenir en cas de problème sur autre chose que uwamp

Notes

Les outils nécessaires

  • Un bon terminal
    sous Windows cmder basé sur ConEmu est très bien : http://cmder.net/

  • GIT
    sous Windows, il est inclus dans cmder

  • Drush
    que nous verrons comment installer plus tard

  • Un bon IDE sera utile surtout s'il a un débugguer intégré
    nous verrons cela aussi plus tard

Notes

TP: Les outils nécessaires

  • Installez un xAMP si vous n'en avez pas
    Si vous en avez déjà un, sans XDebug, téléchargez UwAmp http://www.uwamp.com/fr/

  • Installez GIT

  • Optionnellement (mais recommandé) installez un terminal alternatif à cmd ou utilisez PowerShell

Notes

TP: Installer Drupal 7

  • Aller télécharger Drupal sur http://www.drupal.org/project/drupal
  • Installer le profil d'installation Standard
  • Paramètres
    • Nom du site : Formation
    • Adresse de courriel : formation@example.org
    • Utilisateur : admin
    • Mot de passe : admin
  • Désactiver les modules
    • update
    • overlay
    • shortcut
    • color
    • dashboard

Notes

L'éditeur de code

  • Le meilleur est celui que vous maitrisez
  • Différence IDE/Editeur simple :
    • Autocomplétion
    • XDebug
    • Refactoring
    • Erreurs de syntaxe
  • Possibilité de télécharger des configurations
  • Exemples
    • Eclipse
    • Netbeans
    • PHPStorm
    • SublimeText
    • Vim

Notes

Les standards de codage*

  • Indentation, espaces : lisibilité du code
  • Nommage, toujours commencer par le nom système : éviter les conflits
    • fonctions
    • constantes
    • variables persistantes
    • classes
    • fichiers
  • Tags <?php non fermés : éviter l'envoi du buffer

A connaître pour comprendre et être compris

https://drupal.org/coding-standards

* basés sur le standard PEAR

Notes

TP: Utilisation d'Eclipse

  • Créer un projet: File > New > PHP Project
  • Choisir le répertoire de Drupal
  • Choisir la bonne version de PHP

Avantages :

  • navigation et autocompletion
  • support de toutes les versions possibles PHP
  • installation d'XDebug facile

Notes

TP: Installation d'XDebug

  • dans php.ini décommenter la ligne commençant par zend_extension=xdebug.dll
  • Rajouter en fin de php.ini
    
        [xdebug]
        xdebug.remote_enable=1
        xdebug.remote_host=127.0.0.1
        xdebug.remote_port=9000
        xdebug.profiler_enable_trigger=1
    
    L'option profiler_enable_trigger est en bonus si nous avons le temps
  • Redemarrer le HTTPd
  • Installer l'extension navigateur (easy XDebug pour Firefox, par exemple)
  • Ajouter un breakpoint dans le fichier index.php
  • Activer l'extension dans le navigateur
  • Recharger la page

Notes

TP: Configuration d'XDebug

  • Window > Preferences
  • Chercher "XDebug"

Options :

  • Debug Port : 9000
  • Accept remote session (JIT) : any
  • [X] Use multisession
  • [X] Show super globals
  • Max array depth : 8
  • Max children : 32
  • Max data : 2048
  • Capture stdout : off
  • Capture stderr : off

Notes

Les modules Drupal pour les intégrateurs

  • Features: transférer la configuration dans le code
  • Drush / Drush Make : administration (DRUpal SHell)

Autres bons à connaître

  • Examples for developpers : démonstrations de l'utilisation de l'API
  • Coder : revue de code

Ceux qui vous feront perdre du temps

  • Devel : debug et informations sur les données
  • Admin Menu : flusher les caches rapidement
  • Masquerade : changer d'utilisateur sans se déconnecter

Notes

Les modules Drupal pour les développeurs

La pluspart des modules pour développeur ne vous aideront pas ils vous feront perdre du temps

C'est pour cette raison que nous allons dès maintenant :

  • Ne pas les télécharger
  • Apprendre à utiliser XDebug

Notes

TP: Installer Drush

Un binaire pour Windows existe :

https://github.com/drush-ops/drush/releases/tag/7.0.0

  • Télécharger l'archive .zip
  • La décompresser - elle contient toutes ses dépendences
  • Lancer setenv.bat pour enregistrer Drush dans le PATH Windows
  • Ouvrir un invite de commande, et taper drush pour tester

Pour Linux, MacOS, etc... se reporter à la configuration en ligne.

Notes

TP: Drush

  • Lancer Drush
  • Regarder la liste des commandes
  • Installer un module (features)
  • Regarder à nouveau la liste des commandes
  • Installer des modules, par exemple entity, ckeditor, jquery_update
  • Desactiver le module toolbar

Notes

Git et la gestion de versions

  • Utilisé par beaucoup de développeurs dans le milieu du web

  • Très utile pour patcher des modules car utilisé pas la communauté Drupal et sur drupal.org

  • Une connaissance basique de quelques commandes suffit

    • git clone
    • git add
    • git commit
    • git reset
    • git diff
  • Possibilité d'avoir une interface graphique : SourceTree, GitX, GitEye, Github

Notes

L'architecture de Drupal

Notes

Présentation de l'arborescence

-
-
Modules intégrés au coeur de Drupal
Profils d'installations
-
-
-
Thèmes de tous les sites
Modules de tous les sites
Répertoire spécifique au site
Répertoire d'upload par défaut
Fichiers de configuration
-
Thèmes intégrés au cœur de Drupal


Où travailler ? Dans un profil d'installation custom ou dans un sous-repertoire custom

/!\ Le hack du core et l'avenir des chatons

Notes

Notes

Les modules du core

  • System, User -> prérequis
  • Node, Field, Comment, File, Image -> création de contenu
  • Text, List, Options, Number -> types de champs
  • Menu, Block, Taxonomie -> structuration
  • Toolbar, Shortcut, Dashboard, Color, Overlay, Contextual -> interface
  • Book, Blog, Forum, Poll -> structuration avancée
  • Contact, Aggregator, Tracker, Update, OpenID -> fonctions spécifiques
  • Path, RDF -> SEO
  • Locale, Content Translation -> traduction

Drupal sans ses modules contrib ne permet que de faire des sites simples.

Notes

Les librairies JS

  • jQuery 1.4.4
  • jQuery UI 1.8.7
  • jQuery once (callback evenement unique)
  • jQuery form (envoi de form en ajax)
  • jQuery BBQ (hashchange)
  • jQuery Cookie (cookie JS)
  • Farbtastic (colorpicker)

Pour une version plus récente, utiliser le module jQuery Update

Notes

TP: Jetons un œil à la base de données

  • se familiariser avec PhpMyAdmin

  • identifier les tables des modules actuellement activés

  • identifier les autres : cache, variable, registry

  • identifier la table system et son utilité

Notes

Qu'est ce qu'un module ?

Notes

Fil rouge : le module gold, une fonctionnalité Premium

  • Créer deux permissions pour les rôles, une pouvant affecter le status gold aux contenus et l'autre le voir
  • Créer un bloc affichant si l'utilisateur a la permission de voir les contenus gold
  • Administrer les types de contenus concernés par le statut gold
  • Altérer le formulaire d'édition de nœud pour ajouter le statut gold
  • Envoyer un mail aux utilisateurs ayant la permission de voir les contenus gold lorsque qu'un nouveau contenu gold apparait sur le site
  • Lister les contenus avec le statut gold
  • Créer un style d'image pour illustrer les contenus gold
  • Créer une fonction de theme pour afficher le statut gold d'un nœud
  • Créer des tests pour vérifier le bon fonctionnement du module

Créer ce module : il doit apparaître dans la liste des modules.

Notes

La création d'un module

Notes

Avant de commencer

Votre bible : api.drupal.org

Recense toutes les fonctions de Drupal, et leur documentation. Un IDE aura cette même documentation dans le code.

Aborde certains topics en profondeur : form API, schema API, hooks, etc


Votre guide : modules examples

Pour chaque concept de Drupal, des exemples concrets d'utilisation (ajax, form, blocks, cache, render, cron, dbtng, email, menu, node_access, theming, ...).

Ils sont fonctionnels : on peut les activer et voir leur impact en terme d'interface.

Très bien documentés, ne pas hésiter à lire, comprendre et reprendre le code de ces modules.

Notes

Les hooks

  • Implémenter hook_form_alter() donnera mon_module_form_alter()

  • Poids des modules et altération

  • Répondent à des déclencheurs
  • Des hooks peuvent être déclarés par des modules contrib
  • Rappel: on ne « hack » JAMAIS le code (sauf en cas de module buggué)
  • 3 types de hooks : déclaratif, évenementiel, d'altération
  • Les implémentations sont mise en cache
  • Les hooks déclaratifs sont généralement mis en cache

Liste des hooks https://api.drupal.org/api/drupal/includes%21module.inc/group/hooks/7

Plus de 350 hooks disponibles dans le cœur de Drupal

Notes

Les hooks : mode barbu engaged

php -a
# Optionnel, mais évite des warnings PHP
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';

# Bootstrappe Drupal, cf. index.php
define('DRUPAL_ROOT', getcwd());
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

print_r(module_implements('menu'));

Encore plus barbu

# Force le cache à se charger
module_implements();
# Récupère le cache statique (en mémoire)
$impl = drupal_static('module_implements');

print_r(array_keys($impl));

Notes

Les hooks : autre alternative avec drush php-eval

drush php-eval "print_r(module_implements('menu'));"

Autre méthode : utiliser XDebug

  • Mettre un point d'arrêt dans la méthode module_implements()
  • Lancer un debug, regarder les variables
  • De loin la meilleure méthode !

Notes

TP: Notre premier hook

  • Implémenter le hook_permission()

  • Créer les deux permissions

  • Vider le cache

  • Créer un role contributeur pouvant affecter le statut gold

  • Créer un role premium pouvant voir le statut gold

  • Créer un utilisateur pour chaque rôle

Notes

Les blocs

// Déclaration -> apparait dans la liste des blocks
function hook_block_info() {
  $blocks['syndicate'] = array(
    'info' => t('Syndicate'),
    'cache' => DRUPAL_NO_CACHE,
  );
  return $blocks;
}

// Visualisation
function hook_block_view($delta = '') {
  if ($delta == 'syndicate') {
    return array(
      'subject' => '',
      'content' => '', // (Render array ou HTML) 
    );
  }
}

// Altération
function hook_block_view_alter(&$data, $block) {}
function hook_block_view_MODULE_DELTA_alter(&$data, $block) {}

Notes

TP: Notre premier bloc

Créer un bloc :

  • dont le titre côté administration est "Statut premium de l'utilisateur"
  • dont le delta (nom machine) est gold-status
  • qui affiche "Vous êtes un utilisateur premium" ou "Vous n'êtes pas un utilisateur premium" entouré d'un <h3>

Rappel: user_access() pour vérifier les permissions

Attention au cache d'implementations :

drush php-eval "cache_clear_all('cache_bootstrap');"

Notes

Render Arrays

Les render arrays sont les blocs constituant une page Drupal. Ce sont des arrays PHP qui définissent des données (c-a-d la structure) ; par souci de modularité, on essaiera toujours de produire des render arrays. Ceci afin qu'ils soient puissent être modifiés via les hooks d'altérations ou par la couche de theming.

Les propriétés sont toujours préfixées par un # et la propriété par défaut est #markup, elle permet d'indiquer du balisage simple. Un render array est converti en HTML avec la fonction render();

// Un render array simple
'ma_cle1' => array(
  '#markup' => "<h2>Du texte basique</h2>",
),

// Des propriétés utiles
'ma_cle2' => array(
  '#markup' => "Du texte basique",
  '#prefix' => '<h2>',
  '#suffix' => '</h2>',
),

Notes

Paramètres du render array et propriétés

Une fonction de #theme peut être renseignée ainsi que ses paramètres.

// Un render array qui produit un tableau HTML
'ma_cle1' => array(
  '#theme' => 'table',
  '#header' => $header,
  '#rows' => $rows,
  '#empty' => "Aucune donnée pour ce tableau",
),

Des propriétés utiles :

  • #cache: mise en cache du render array
  • #pre_render: agit sur l'array avant le rendering
  • #post_render: agit sur le markup après le rendering
  • #weight: donne un poids à l'élément
  • #attached: lier à un ou des CSS/JS
  • #access: desactive l'élément si == FALSE

Notes

Fonctions de theme

Exemples de fonctions de theme() :

  • table
  • item_list
  • pager
  • links
  • image

Liste complete des implementation de theme du cœur

$table_element = array(
    '#theme'  => 'image',
    '#path' => drupal_get_path('module', 'monmodule') . '/monimage.png',
);
print drupal_render($table_element); // Quasi-automatiquement appelé
                                     // par les hooks

Documentation http://drupal.org/node/930760 et le module render_example

Notes

TP: Privilégier les render arrays

  • Convertir le contenu du bloc render array
  • Altérer le bloc dans un hook_block_view_alter() afin de changer le <h3> en <h4>

Ne pas hésiter à rendre le code lisible en utilisant des constantes pour les permissions

Notes

Système de menus

Quelques définitions :

  • routage : faire pointer une route (node/%) à une action (afficher un noeud)
  • chemin (ou path) : route dont les arguments sont définis (ex: node/123 est un chemin, pointant vers la route node/% où l'argument est 123)
  • lien de menu : Texte (ou titre) pointant vers un chemin
  • alias : associe un chemin système (node/123) vers un chemin arbitraire renseigné par le contributeur (mon-noeud)

Les propriétés d'une route

  • Permissions -> 'access callback', 'access arguments'
  • Arguments peuvent être bruts '%' ou nommés '%node' pour être chargés à la volée avec *_load() -> node_load()

Notes

  • Type d'élément de menu
    • MENU_NORMAL_ITEM -> lien de menu dans l'arborescence
    • MENU_LOCAL_TASK -> onglet
    • MENU_CALLBACK -> url simple
  • Possibilité de placer la page callback dans un fichier .inc (file path + file)
  • La route abc/def est enfant de la route abc si celle-ci est définie
  • /!\ Il y a toujours un s à arguments : utiliser un array()
  • /!\ Il y n'a pas d'underscore dans le nom des propriétés : page_callback
Propriété Valeur par défaut
page callback celle du parent
access callback user_access ou celle du parent
file path le chemin du module
menu_name navigation
type MENU_NORMAL_ITEM

Notes

Exemple

function mymodule_menu() {
  $items['abc/def'] = array(
    'title' => "My ABC page",
    'page callback' => 'mymodule_abc_view',
    'page arguments' => array(1),
    'access callback' => 'mymodule_verify_access',
    'access arguments' => array('une chaine'),
    'file' => 'mymodule.pages.inc',
  );
  return $items;
}

function mymodule_abc_view($def) {
  return "Mon contenu";
}

function mymodule_verify_access($string) {
  return $string == 'une chaine';
}

Notes

TP: Création de page

Créer une page Suis-je Premium ? reproduisant le comportement du bloc

  • url : suis-je-gold

Créer une page Est-il Premium ? affichant la même chose, mais avec en argument l'uid de l'utilisateur

  • url d'exemple : est-il-gold/2

Créer une page Page Premium avec du contenu "Lorem Ipsum" et ne s'affichant que si l'utilisateur courant à la permission de voir le contenu premium

  • url : page-gold

S'inspirer de la docummentation du hook_menu()

Placer toutes les callback dans un autre fichier que le .module

Attention au cache de menu

Notes

Gestion des nodes et des users

Quelques globales et fonctions de l'API à connaitre :

  • global $user : utilisateur actuellement connecté (modifier avec prudence !)
  • node_load() et node_load_multiple() pour charger des nœuds
  • node_save() pour enregistrer un nœud
  • user_load() et user_load_multiple() pour charger des utilisateurs
  • user_save() pour enregistrer un utilisateur
  • REQUEST_TIME : timestamp à l'appel de la page

Notes

Gestion de la base de données

SQL statique

La fonction db_query() permet d'exécuter du SQL directement mais utiliser des accolades autour des noms de table {table_name} (permet la gestion de prefixe) et les placeholders pour passer des arguments (pour les failles de sécurité). Utiliser ensuite foreach() pour parcourir les résultats.

$result = db_query("SELECT some_col FROM {my_table}
  WHERE some_col IN (:my_ids)", array(':my_ids' => $my_ids));
foreach ($result as $record) {
  print_r($record);
}

DBTNG

Permet de faire des requêtes dynamiques grâce à une API en POO, donc sans manipuler de chaînes.

Documentation complète, voir également les commentaires sur chaque fonction sur https://api.drupal.org

Notes

DBTNG

$results = db_select('contact', 'c')
              ->fields('c')
              ->condition('created', REQUEST_TIME)
              ->execute()
              ->fetchAllAssoc('cid');
foreach ($results as $result) {
  // faire qqch
}

Voir aussi db_insert(), db_delete(), db_update() et db_merge()

Récupération de résultats :

  • fetchField() : la première colonne du premier résultat
  • fetchCol() : la première colonne sous forme d'array
  • fetchAssoc() : le premier résultat sous forme d'objet
  • fetchAllAssoc() : tous les résultats sous forme d'objet
  • fetchAllKeyed() : tous les résultats sous forme de tableau indexé par la 1ere colonne avec pour valeur la 2e

Notes

Gestion des URLs et des paths

Quelques globales et fonctions de l'API à connaitre :

  • url() -> '' ou 'node/1'
  • l() -> lien avec texte (<a href=''>)
  • drupal_goto() -> redirection
  • global $base_url -> http://monsite.com
  • base_path() -> / ou /mon-dossier-drupal
  • drupal_get_path() (module, theme) -> chemin vers un module ou un thème drupal_get_path('module', 'devel') donne sites/all/modules/devel

Notes

TP: Création de page

Créer une page Utilisateurs premium listant les utilisateurs du site ayant un accès premium.

  • Créer une page

  • Récupérer les rôles ayant la permission de voir le contenu gold (dans la table role_permission)

  • Récupérer les utilisateurs ayant ces rôles (dans la table users_roles)

  • Les afficher d'abord dans une liste

  • Modifier pour les afficher dans un tableau avec Identifiant, Nom, Lien vers son profil

Les callback doivent être situées dans un autre fichier que le .module

Attention au cache

Notes

La Form API

Notes

Un formulaire est une structure déclarative composée d'éléments de la form API. La majeure partie des traitements est effectuée par celle-ci, rendant la création ou la modification de formulaire rapide et sécurisée.

Référentiel des composants disponibles sur api.drupal.org

$form = drupal_get_form('my_module_example_form'); // Appel

// Déclaration
function my_module_example_form($form, &$form_state) {
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
  );
  return $form;
}
function my_module_example_form_validate($form, &$form_state) {
  // Logique de validation.
}
function my_module_example_form_submit($form, &$form_state) {
  // Traitement des données soumises.
}

Notes

Traitement des données

Les données soumises et validées sont contenues dans $form_state['values'].

Après exécution du _submit(), l'utilisateur est redirigé vers le formulaire vidé de ses valeurs, ou bien vers une page définie par $form_state['redirect']

Chaque formulaire a un identifiant unique qui permet de l'altérer facilement par les autres modules.

  • Possibilité de créer des formulaires multi-étapes.
  • Validation par élément
  • Possibilité de créer de nouveaux type d'éléments
  • #ajax (http://drupal.org/node/752056) permet de faire de l'Ajax sans ecrire de JS
  • #autocomplete_path 

Schéma de workflow complet : https://drupal.org/files/fapi_workflow_7.x_v1.1.png

Notes

Gestion de variables persistantes

  • variable_set('name', value) pour définir
  • variable_get('name', default_value) pour récupérer
  • variable_del('name') pour supprimer

Notes

TP : Form API

But: définir pour quels types de contenu la fonctionnalité premium est activée. C'est-à-dire, sur quels types on affichera l'option "Contenu premium" dans les formulaires de création ou de modification de nœud.

  • Créer un formulaire listant les types de contenu avec pour chaque une checkbox


Article
Page de base

  • Valider le fait qu'on ne peut pas choisir le type de contenu Page de base

  • A la soumission enregistrer les valeurs dans une variable persistante 'gold_types'

  • Cocher les checkbox par défaut lorsque le type de contenu est activé

Notes

Manipuler les fichiers et les images

Notes

La File API

Un fichier n'est pas une entité ! (malheureusement)

Différence entre fichiers gérés et non gérés

Différence entre fichiers privés et fichiers publics

API complète https://api.drupal.org/api/drupal/includes%21file.inc/group/file/7

Les streams wrappers

Un stream est un chemin, une URI, vers un fichier interne ou externe :

  • public://
  • private://

Notes

Fournir un effet sur les images

function hook_image_effect_info() {
  $effects['mymodule_resize'] = array(
    'label' => t('Resize'),
    'help' => t('Resize an image to an exact set of dimensions.'),
    'effect callback' => 'mymodule_resize_effect',
    'dimensions callback' => 'mymodule_resize_dimensions',
    'form callback' => 'mymodule_resize_form',
    'summary theme' => 'mymodule_resize_summary',
  );

  return $effects;
}

Notes

Fournir un style par défaut

function hook_image_default_styles() {
  $styles['mymodule_preview'] = array(
    'label' => 'My module preview',
    'effects' => array(
      array(
        'name' => 'image_scale',
        'data' => array(
          'width' => 400,
          'height' => 400,
          'upscale' => 1,
        ),
        'weight' => 0,
      ),
    ),
  );

  return $styles;
}

Notes

TP: Créer un style d'image pour nos contenus gold

Celui-ci nous servira pour les images qui seront sur les articles gold

Notes

Schema API

  • Gère la base de données
  • Se situe dans le fichier .install
  • hook_schema() -> crée une ou plusieurs tables
  • hook_schema_alter() déclare une modification (mais ne la réalise pas)
  • API de la structure https://drupal.org/node/146866
  • Fonctions de l'API https://drupal.org/node/150223
  • Les hook_update_N() servent à réaliser des actions sur la structure ou les données
  • Très utile pour les mises à jour en production, et le test de celles-ci

Notes

TP: Enregistrer les statuts

Déclarer une table gold

Via l'API, déclarer une table avec deux colonnes, nid etstatus. Installer cette table via un hook_update_N() ou réinstaller le module.

Altérer le formulaire de noeuds

  • Ajouter la checkbox au dessus du titre

  • Enregistrer la valeur dans notre table à l'enregistrement

  • La mettre à sa valeur par défaut à l'affichage du formulaire

Rappels 

  • hook_form_alter(&$form, $form_state, $form_id)
  • hook_node_update() et hook_node_insert()
  • Debug : drupal_set_message('<pre>'.print_r($var, 1).'</pre>')

Notes

TP : Contrôler l'accès aux nœuds

Utiliser l'API Node Access (documentation)

Déclarer notre hook_node_access()` et ne retourner NODE_ACCESS_DENY que si les 4 conditions sont réunies :

  1. je suis en train de voir le nœud
  2. son type a la foncitonnalité premium activé
  3. c'est un contenu premium
  4. je n'ai pas la permission de voir les contenu premium

Attention: ne fonctionnera pas pour les listes (dont la page d'accueil) pour des raisons de performances, il faudrait declarer hook_node_grants(). Rester simple et ne controler l'accès qu'à un nœud complet.

De même hook_node_access() n'est pas appelé pour le superadmin.

Notes

Envoi de mails

// Déclaration du contenu du mail avec hook_mail().
function monmodule_mail($key, &$message, $params) {
  $account = $params['account'];
  $node = $params['node'];
  $message['subject'] = "Bonjour " . format_username($account);
  $message['body'][] = "Le noeud {$node->title} a été créé";
  $message['body'][] = "A bientot";
}

// Envoi du mail.
drupal_mail('monmodule', 'maclé', 'toto@example.com', 'fr-FR', array(
  'node' => node_load(123),
  'user' => user_load_by_name('toto'),
);

On peut utiliser la notion de tokens (jetons) ou la fonction strtr(). 'body' est un tableau de lignes.

Envoi du mail avec drupal_mail($module, $key, $to, $language, $params = array());

La clé permet à un module de gérer plusieurs types de mail.

Notes

TP

Notification par mail

Envoyer un mail à tous les utilisateurs premium :

Sujet: Nouveau contenu premium

Bonjour _Nom d'utilisateur_,
Un nouveau _Type de contenu_ premium a été créé, il s'intitule _Titre_
Vous pouvez le consulter ici : _URL_
Cordialement,
L'équipe du site _Nom du site_

Affichage du statut premium sur le nœud

  • Trouver un hook qui permettrait d'ajouter un message <strong>Contenu premium/strong> sur chaque contenu premium
  • L'implementer avec #markup

Notes

Le partie thème d'un module

Le module fournit toujours le markup par défaut.

Le hook_theme() définit des hooks/clés qui pourront ensuite être utilisés via la propriété #theme des render arrays. Ces theme hooks généreront ensuite le markup HTML soit via une fonction, soit via un template.

On peut fournir des variables à ces theme hooks. Des fonctions preprocess et process peuvent ajouter ou modifier des variables, et également ajouter des suggestions de templates.

https://www.drupal.org/files/theme_flow_6_1.pdf (pour Drupal 6)

Notes

Déclaration et appel

function forum_theme() {
    return array(
        'forums' => array(
            'template' => 'forums',
            'variables' => array(
                'forums' => NULL,
                'topics' => NULL,
            ),
        ),
    );
}

$html_output = theme('forums', array(
  'forums' => $forums,
  'topics' => $topics,
));

// Mais toujours privilégier les render arrays, car altérables
$build['forums'] = array(
  '#theme' => 'forums',
  '#forums' => $forums,
  '#topics' => $topics,
);

Notes

TP: Créer un template pour gold

Convertir le render array utilisé dans hook_node_view() pour utiliser un theme hook qui se base sur un template.

Passer en paramètre le nœud et transformer "Contenu premium" en "Titre du nœud est un contenu premium".

Ajouter une image de médaille dans ce template.

Créer un preprocess pour transformer cette image en variable.

Dans le preprocess, transformer l'image en render array, et utiliser la fonciton render() dans le template.

Ajouter des suggestions pour ce template.

Notes

Ajout de JS / CSS

  • 3 techniques d'ajout
    • dans le .info -> global
    • drupal_add_* -> au moment de l'appel
    • #attached[] -> au moment du rendering
  • hook_(js/css)_alter() 
  • drupal_add_library() également pour jQuery UI et autres
  • Notion de groupes 
    • JS (JS_LIBRARY, JS_DEFAULT, JS_THEME)
    • CSS (CSS_SYSTEM, CSS_DEFAULT, CSS_THEME)

Notes

TP: Faire flotter l'image à droite

Ajouter une classe à l'image et créer un fichier CSS:

img.gold-icon {
  float: right;
}

L'ajouter lorsqu'un noœud gold est affiché.

Notes

Le javascript

  • Bonnes pratiques 
  • Jquery (inclus dans Drupal) 
  • Le « Drupal way » 

Bonnes pratiques JS

  • « Unobtrusive javascript » 
    • Surcouche 
    • Comportements dégradés 
    • Accessibilité 

Voir les modules example

Notes

Les profils d'installation

Quelques exemples

Une bonne pratique de développement

TP: créer un profil avec notre module gold

Notes

Aller plus loin

Drush make

Les performances

Features

Notes

Merci

Notes