Voilà, voilà... Fin de l'aventure...

 

Fermeture de kolossaldrupal.org dans...


Bonjour tout le monde,

Drupal évolue, les versions changent et Kolossaldrupal.org était essentiellement consacré à la version 6 de Drupal.

Autant dire que les infos présentées ici commencent à dater...

Faute de temps, je ne peux plus garder le site Kolossaldrupal à jour...

Je vous aurais bien proposé de reprendre le flambeau mais... c'est tellement simple de nos jours de se faire son propre site à soi...Pourquoi s'embêter alors ? :-)

Ce site restera donc en l'état, tel qu'il était en 2011...

Ah la la ! Cela ne nous rajeunit pas !

Manuel Vila - Avril 2016

Écrire des actions

Référence en anglais sur drupal.org : 5 Janvier 2010 - 16h09
http://drupal.org/node/172152


Les actions Drupal seront mieux comprises avec une bonne définition.

Pour les administrateurs de sites Drupal : les actions sont des choses individuelles que Drupal peut réaliser. Des exemples d'actions : envoyer un e-mail, publier un node, bannir un utilisateur ou promouvoir un node en page d'accueil d'un site. Vous rencontrerez habituellement les actions dans les écrans de paramétrage de Drupal.

Pour les programmeurs: une action est une fonction qui agit comme une procédure stockée. Les paramètres de la fonction, s'il y en a, sont enregistrés dans la base de données et la fonction est exécutée en récupérant ces paramètres et en appelant la fonction.

Pouvez-vous donner un exemple pour lequel une action est utile ?

Les actions sont généralement utilisées pour configurer les réponses de Drupal aux événements. Supposons qu'un administrateur de site veuille être averti par e-mail chaque fois qu'un utilisateur s'inscrit au site. Il configurera une action « Envoyer un e-mail » et utilisera le module trigger pour faire exécuter cette action quand un nouvel utilisateur s'inscrira au site (techniquement, cela devra se faire quand l'op 'insert' du hook utilisateur sera exécutée).

Où se trouve le code-source des actions ?

Le moteur des actions, qui exécute les actions, se trouve dans includes/actions.inc. Le répartiteur (dispatcher) des actions se trouve dans modules/trigger.module.

Les écrans de configuration pour ajouter, enlever et paramétrer les actions individuelles font partie de system.module.

L'interface pour associer les actions aux événements (hooks) est fournie par modules/trigger.module.

Le hook qui décrit les actions (hook_actions_info()) et les actions elles-mêmes se trouvent dans les modules. Les actions ayant des incidences sur les nodes, comme l'action « Publier un node » se trouvent dans node.module.

Comment créer une nouvelle action ?

En deux étapes. La première consiste à décrire l'action à Drupal via la fonction hook_action_info(). Puis on écrit le code-source de l'action qui sera exécuté.

Décrire l'action avec hook_info_action()

Regardons l'implémentation de hook_action_info() dans le module utilisateur :

<?php

/**
* Implementation of hook_action_info().
*/
function user_action_info() {
  return array(
    
'user_block_user_action' => array(
      
'description' => t('Block current user'),
      
'type' => 'user',
      
'configurable' => FALSE,
      
'hooks' => array(
        
'nodeapi' => array('presave''delete''insert''update''view'),
        
'comment' => array('view''insert''update''delete'),
        
'user' => array('logout'),
        ),
      ),
    
'user_block_ip_action' => array(
      
'description' => t('Ban IP address of current user'),
      
'type' => 'user',
      
'configurable' => FALSE,
      
'hooks' => array(
        
'nodeapi' => array('presave''delete''insert''update''view'),
        
'comment' => array('view''insert''update''delete'),
        
'user' => array('logout'),
      )
    ),
  );
}
?>

hook_action_info() doit retourner un tableau dont les clés sont les noms des fonctions des actions décrites. Dans le module utilisateur, user_action_info() nous décrivons deux actions. Concentrons-nous sur la première. La clé du tableau pour la première action décrite est user_block_user_action. C'est le nom de la fonction qui sera exécutée quand l'action aura lieu. Le nom de la fonction est construit selon la convention suivante :

nomdumodule + description de ce que fait la fonction + _action

Dans notre cas :

user + block user + action

Ce qui nous donne user_block_user_action.

Nous devons ensuite apporter quelques informations au tableau via les clés suivantes :

description : une description compréhensible de ce que fait l'action

type : le type est déterminé par l'objet sur lequel l'action agit. Des choix possibles peuvent être node, user, comment et system. Ou bien votre propres types personnalisés.

configurable : TRUE ou FALSE. De cette valeur dépendra l'interface qu'utilisera Drupal pour la configuration des actions. Si c'est FALSE c'est le cas le plus simple : il n'y a pas d'interface pour la configuration de l'action.

Dans notre exemple, l'action « Block current user » n'a pas besoin d'infos supplémentaires puisque Drupal peut facilement identifier l'utilisateur en cours pendant l'exécution. Pour une action plus complexe, comme envoyer un e-mail, il faudra connaître le destinataire de l'e-mail, son objet, son contenu, etc...

hooks : tableau contenant les opérations pour lesquelles l'action est appropriée, saisies par leur nom de hook. Dans l'interface qui associe les actions aux événements, le module actions utilise ce tableau pour ne pas y faire figurer les opérations inappropriées. Par exemple, l'action « Block current user » définit l'opération logout du hook utilisateur mais pas l'opération login. Parce qu'il serait idiot de bannir un utilisateur juste après sa connexion. Il est à noter qu'il s'agit là d'un simple problème d'interface; Drupal n'a pas de restrictions quant à l'exécution des actions.

Remarque : si vous écrivez des actions dans vos propres modules et voulez déclarer le support de tous les hooks possibles, vous pouvez paramétrer 'hooks' => array('any' => TRUE).

Écrire une action

Une fois l'action décrite à Drupal, vous devez écrire le code-source de l'action. Voici le code pour l'action « Bannir l'utilisateur en cours » :

<?php
/**
* Implementation of a Drupal action.
* Blocks the current user.
*/
function user_block_user_action(&$object$context = array()) {
  
// get the uid from the object
  
if (isset($object->uid)) {
    
$uid $object->uid;
  }
  elseif (isset(
$context['uid'])) {
    
$uid $context['uid'];
  }
  else {
    global 
$user;
    
$uid $user->uid;
  }
  
// make sure we have a user record
  
if ($uid) {
    
$user user_load($uid);
    
// block the user
    
db_query("UPDATE {users} SET status = 0 WHERE uid = %d"$uid);
    
// log out the user
    
sess_destroy_uid($uid);
    
// record a message noting the action taken
    
watchdog('action''Blocked user %name / uid=%uid.', array('%name' => check_plain($user->name), '%uid' => $uid));
  }
}
?>

Veuillez noter que ce code n'est plus synchronisé avec celui du core Drupal (http://api.drupal.org/api/function/user_block_user_action) d'où il a été tiré. Voir la discussion #497358: user_block_user_action() may log incomplete watchdog message

Voyons d'abord la fonction de l'action. Deux paramètres sont passés, un objet et un tableau.

$object : c'est l'objet sur lequel l'action doit agir. Il correspond au type déclaré pour cette action dans hool_action_info(). Par exemple, si un type utilisateur avait été déclaré, l'action passerait un objet utilisateur.

$context : un tableau contenant des informations supplémentaire qui pourront aider l'action à déterminer le contexte dans lequel elle s'exécute. Par exemple, les modules actions paramètrent les clés hook et op du tableau context (hook peut être nodeapi et op peut être insert), l'action peut ainsi les examiner et prendre diverses décisions si nécessaires.

Regardons maintenant l'action elle-même. Elle se décompose en deux parties. D'abord on détermine l'utilisateur à bannir en regardant l'objet utilisateur passé en paramètre. S'il n'y en a pas, on cherche l'uid dans le tableau $context. Si on ne le trouve pas, on regarde dans la variable globale $user pour déterminer l'uid à bannir. Vous trouverez peut-être étranges ces différentes étapes. Pourquoi ne pas passer d'entrée le bon paramètre ? La réponse est double. D'abord, avec les actions, nous voulons un passage de paramètres universel pour que la couche action sous-jacente ait moins de travail à réaliser, ce qui donnera de meilleures performances. Ensuite, supposons que vous vouliez bannir 50 utilisateurs. Faire un user_load() complet sur chacun d'eux juste pour avoir un objet que vous passerez à l'action n'est pas performant alors que vous pouvez placer l'uid dans le tableau context.

La seconde partie de l'action bannit effectivement l'utilisateur et une entrée watchdog est enregistrée.

Vous savez maintenant comment créer une action non paramétrable. Si une action doit être paramétrée, vous devez réaliser le formulaire de saisie dans lequel l'administrateur indiquera ses paramètres. Dans comment.module, regardez l'action « Unpublish comment containing keyword(s) » pour plus d'infos, et plus particulièrement les fonctions comment_unpublish_by_keyword_action_form(), comment_unpublish_by_keyword_action_submit() et comment_unpublish_by_keyword_action().

J'ai écrit un module qui fournit les hooks. Comment assigner les actions à exécuter lorsque ces hooks sont sont exécutés ?

Utilisez les instructions indiquées dans la page Écrire des triggers. D'autres informations sont également disponibles dans les fonctions node_hook_info(), comment_hook_info() ou user_hook_info().

Je veux exécuter des actions mais je ne veux pas utiliser actions.module

Vous pouvez exécuter n'importe quelle action directement dans votre code-source en appelant la fonction actions_do(), qui se trouve dans includes/actions.inc.

Je veux exécuter une action mais seulement lorsque certaines conditions sont réunies

Jetez un œil au module Rules et à sa documentation, il a été spécialement conçu pour vous permettre de déclarer des actions s'exécutant de façon conditionnelle, telles que « envoyer un e-mail quand un contenu est publié mais seulement s'il s'agit d'un node »

J'ai actualisé la déclaration de mon action dans hook_action_info() mais l'action n'a pas été mise à jour. A l'aide !

Lorsque vous visitez la page de configuration des actions (Administrer » Configuration du site » Actions), Drupal détectera (via actions_synchronize()) que l'action a été actualisée mais n'utilisera pas automatiquement les nouvelles infos.

Allez dans Administrer » Rapports » Entrées récentes de journal et vous devriez voir une entrée sur les actions orphelines. Cliquez sur le message pour en voir le détail puis cliquez sur le lien « Remove orphans actions ». Cela enlèvera aussi tout trigger associé à cette action.

Votre nouvelle déclaration d'action sera désormais utilisée. N'oubliez pas de visiter la page des déclencheurs pour réassigner vos actions.

Notez que tous les changements dans le code-source de l'implémentation de votre action prendront effet immédiatement, c'est juste la déclaration de l'info dans hook_action_info() qui est difficile à effacer !