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

Remplacement dynamique d'arguments (wildcards)

Référence en anglais sur drupal.org : 1 Mars 2009 - 22h02
http://drupal.org/node/109153


Exemple

Débutons par un exemple :

<?php
  $items
['node/%node/edit'] = array(
    
'access callback' => 'node_access',
    
'access arguments' => array('update'1),
?>

node_access('update', node_load(arg(1))); sera appelé pour un contrôle de l'accès. %foo veut dire que foo_load sera appelé.

Background

Dans le passé nous avions du code qui s'exécutait à chaque requête de page :

<?php
if (arg(0) == 'node' && arg(1) && is_numeric(arg(1)) && ($node node_load(arg(1)))) {
  
$items[] = array(
    
'path' => 'node/'$node->nid,
    
'access' => node_access('view'$node),
    
'callback' => 'node_view_page',
    
'callback arguments' => array($node),
  );
}
?>

Et donc pour le module Comment :

<?php
if (arg(0) == 'comment' && arg(1) == 'reply' && arg(2) && is_numeric(arg(2)) && ($node node_load(arg(2)))) {
  
$items[] = array(
    
'path' => 'comment/reply/'$node->nid,
    
'access' => node_access('view'$node),
    
'callback' => 'comment_reply',
    
'callback arguments' => array($node),
  );
}
?>

Maintenant regardons ces deux définitions ! Si on décompose le if, la première partie s'assure que vous êtes dans un path donné (node/123, comment/reply/123) et la seconde moitié charge le node dont l'ID est 123. Le nouveau système de menu sait déjà comment interpréter les paths dynamiques (voir wildcards traduction à venir). Pour la seconde moitié, la vérification is_numeric peut être centralisé et alors tout le système de menus a besoin de savoir si nous voulons effectuer le chargement d'un objet identifié par un argument spécifique et si cet objet est un node.

Une conversion rudimentaire au nouveau système de menu serait :

<?php
  $items
['node/%'] = array(
    
'access callback' => 'node_access',
    
'access arguments' => array('view''$node'),
    
'page callback' => 'node_view_page',
    
'page arguments' => array('$node'),
    
'the argument that specifies $node' => 1,
    
'object type to load for argument 1' => 'node',
  );
?>

Nous devons mettre $node entre guillemets parce que le nouveau système de menu n'exécutera pas cette déclaration à chaque requête de page - mais, selon ce qui porécède, il peut découvrir comment agir puisque

tout le système de menus a besoin de savoir si nous voulons effectuer le chargement d'un objet identifié par un argument spécifique et si cet objet est un node.

et nous avons spécifié l'argument et le type d'objet. Nous pourrions effectivement utiliser cette écriture, mais elle est assez vilaine. Notre première constatation est que 'l'argument qui spécifie $node' => 1, peut être mis à la place de $node :

<?php
  $items
['node/%'] = array(
    
'access callback' => 'node_access',
    
'access arguments' => array('view'1),
    
'page callback' => 'node_view_page',
    
'page arguments' => array(1),
    
'object type to load for argument 1' => 'node',
  );
?>

Maintenant, pourquoi pouvons-nous charger un objet pour l'argument 1 ? Parce qu'il s'agit d'un wildcard. Maintenant, pourquoi le wildcard ne peut-il nous resneigner sur le type d'objet qu'il remplace ?

%wildcard_load()

(voir aussi Wildcard Loader Arguments)

<?php
  $items
['node/%node'] = array(
    
'access callback' => 'node_access',
    
'access arguments' => array('view'1),
    
'page callback' => 'node_view_page',
    
'page arguments' => array(1),
  );
?>

 

<?php
  $items
['comment/reply/%node'] = array(
    
'access callback' => 'node_access',
    
'access arguments' => array('view'2),
    
'page callback' => 'comment_reply',
    
'page arguments' => array(2),
  );
?>

Lors de l'appel à comment_reply, le 2 du tableau d'arguments sera remplacé par node_load(arg(2)).

Le nom de la fonction est le nom du wildcard avec _load comme suffixe, donc node_load() est utilisé pour le wildcard %node.

L'accès à node/123 est par conséquent déterminé par un appel à node_access('view', node_load(123)).

Que se passe-t-il avec l'onglet Edit ?

<?php
  $items
['node/%node/edit'] = array(
    
'access callback' => 'node_access',
    
'access arguments' => array('update'1),
    
'page callback' => 'node_edit_page',
    
'page arguments' => array(1),
    
'title' => 'edit',
    
'type' => MENU_LOCAL_TASK
  
);
?>

Si vous êtes sur le path node/123 vous vous attendez à ce que cet item créé un onglet pointant sur node/123/edit. C'est plutôt facile, nous remplaçons node/%/edit par node/123/edit où 123 est simplement l'argument adéquat. Lorsque vous cliquez sur cet onglet, vous arriverez sur node/123/edit où la substitution d'objet habituelle se produira.

Vous pouvez surcharger ce comportement pour le cas dans lequel vous voulez substituer dynamiquement une valeur dans un lien (ou un onglet) qui est affiché (voir %wildcard_to_arg() ci-dessous).

Des arguments supllémentaires pour la fonction load peuvent être spécifiés via la clé load arguments. %map et %index sont des arguments load spéciaux.

%map est un tableau contenant les différentes parties du path, pour user/1/edit/this/is/a/category, cela donnera array('user','1','edit','this','is','a','category')

%index indique à quel argument nous nous trouvons, pour le path node/%node/1 ce sera 1. Pour comment/reply/%node ce sera 2. Un exemple de leur utilisation est function user_category_load($uid, &$map, $index) qui manipule user/%user_category/edit/'. $category['name']. La partie la plus importante de la fonction est :

<?php
    
// Since the path is like user/%/edit/category_name, the category name will
    // be at a position 2 beyond the index corresponding to the % wildcard.
    
$category_index $index 2;
    
// Valid categories may contain slashes, and hence need to be imploded.
    
$category_path implode('/'array_slice($map$category_index));
?>

Au final, map sera array('user', $account, 'edit', 'this/is/a/category').

%wildcard_to_arg()

Lorsque vous voulez substituer dynamiquement une valeur dans le path d'un lien de menu (ou d'un onglet), vous pouvez déclarer une fonction avec le suffixe _to_arg.

Un bon exemple dans le core est la fonction user_uid_optional_to_arg() (avec le path de menu correspondant user/%user_uid_optional) qui est utilisé pour modifier dynamiquement le lien Mon compte afin qu'il pointe vers la page du compte de l'utilisateur en cours.

Les arguments spéciaux %map et %index (voir ci-dessus) sont automatiquements passés à la fonction _to_arg.

Une autre fonction _to_arg très utile est menu_tail_to_arg().

<?php
 $search
['search/'$name .'/%menu_tail'] = ...
?>

Elle prendra tous les arguments à partir du wildcard, et les retournera en une seule chaîne de caractères. De cette façon, si vous cherchez foo/bar, les onglets de recherche pointeront vers search/node/foo/bar et search/user/foo/bar. Sans menu_tail, il n'y aurait eu que search/user/foo.

Notez qu'à l'inverse des fonctions _load(), la valeur retour d'une fonction _to_arg() n'est pas passée aux fonctions callback quand, dans le tableau arguments, vous spécifiez le numéro arg du wildcard. La valeur passée sera simplement la valeur de arg(n). Une fonction _to_arg() n'affecte que le path d'un élément de menu.

>Combiner _load and _to_arg

Il n'y a pas de conflits entre ces deux types de fonctions. Si vous voulez que la même valeur de remplacement soit passée au path et aux arguments callback, implémentez simplement les deux fonctions _load() et _to_arg() pour le même wildcard.

par exemple, le module User définit les deux user_uid_optional_load() et user_uid_optional_to_arg() pour les substitutions %user_uid_optional.

Il n'y a pas de menu_tail_load() de déclaré, donc la fonction callback search_view() pour les éléments de menu 'search/'.$name.'/%menu_tail doit recréer la chaîne %menu_tail pour les args inchangés, en utilisant search_get_keys().

Arguments callback de type entier

Tout entier n dans un tableau arguments renvoie à la valeur de arg(n), ou sa substitution wildcard_load(). Ceci parce que la fonction menu_serialize() utilise le contrôle is_int.

Cela s'applique aux entiers litéraux, constantes et variables; donc si votre tableau d'arguments est array($count), et que $count est un entier, alors arg($count) sera la valeur passée.

Si vous voulez passer une valeur de type entier à un callback de menu, vou devrez utiliser une chaîne à la place :

  • '3'
  • (string) 3
  • (string) MY_CONSTANT
  • (string) $my_variable
  • "{$my_variable}"

Dans Drupal 5, nous avions l'habitude d'utiliser des boucles foreach() pour déclarer récursivement plusieurs MENU_ITEM ou MENU_SUGGESTED_ITEM.

Dans Drupal 6, nous n'avons besoin que d'une entrée dans hook_menu() avec le wildcard approrié. De plus, vous pouvez créer autant d'éléments de menus que souhaités (activés ou non) avec menu_link_save().

Pour plus d'informations à ce sujet, voyez cette discussion.