web-dev-qa-db-fra.com

Comment ajouter une condition d'accès à un élément de menu?

Comment puis-je ajouter de nouvelles conditions en plus des conditions existantes qui déterminent si un élément de menu est visible? Ces conditions ne doivent pas être limitées aux paramètres d'autorisations.

Comme exemple d'utilisation (pas nécessairement la raison de cette question): Supposons que j'ai un type de contenu dont les utilisateurs ne sont autorisés à créer qu'un seul nœud. J'ai un élément de menu pour ajouter ce type de contenu. Mais si l'utilisateur a déjà créé un nœud de ce type de contenu, je souhaite masquer l'élément de menu. Ma première pensée est d'exécuter une requête pour vérifier l'existence d'un nœud créé par l'utilisateur actuel qui est du type de contenu spécifique. S'il en existe un, masquez l'élément de menu.

Je pense que ce type de fonctionnalité devrait aller dans hook_menu_alter() et y ajouter la logique requise. Mais je ne sais pas comment faire cela sans contourner les vérifications existantes, comme vérifier si l'utilisateur a les autorisations pour créer ce type de contenu. Dois-je inclure cette logique dans ma propre condition? Ou puis-je ajouter à la logique d'accès existante sans l'écraser?


Modifier: Certaines personnes semblent se concentrer sur la réponse "comment puis-je limiter un utilisateur à créer un nœud d'un type de contenu". Ce n'est pas la question ici. La question est de savoir comment ajouter des conditions d'accès personnalisées à un élément de menu.

16
Chaulky

Ce que vous devez faire est d'ajouter votre rappel via hook_menu_alter (), puis à l'intérieur de votre rappel, vous faites simplement votre logique puis renvoyez les données via le rappel d'origine.

Pour être certain de ne pas écraser les autres modifications de hook_menu_alter (), vous devez transmettre le rappel précédent à votre rappel via l'argument d'accès.

Tout cela est théorique, mais le code devrait ressembler à ceci:

MYMODULE_menu_alter(&$items) {
  $items['menu']['access arguments'] = array_merge(array($items['menu']['access callback']), $item['menu']['access arguments']);
  $items['menu']['access callback'] = 'MYMODULE_access_callback';
}

MYMODULE_access_callback() {
  $args = func_get_args();

  // Do Stuff.
  if ($something == FALSE) {
    return FALSE;
  }

  $function = array_shift($args);
  return call_user_func_array($function, $args);
}
11
Decipher

Vous recherchez le module Chain Access Access API .

L'API d'accès au menu en chaîne permet à votre module de chaîner ses propres fonctions de rappel d'accès au menu dans les entrées du routeur de menu des autres modules.

Il y a au moins n exemple on Drupal Stack Exchange de la façon de l'utiliser).

1
crantok

En réponse aux commentaires ci-dessus, la solution dans D7 serait d'utiliser:

/**
 * Implements hook_node_access().
 */
function mymodule_node_access($node, $op, $account) {
  $type = is_string($node) ? $node : $node->type;

  if ($op == 'create' && $type == 'mynodetype' && db_query("SELECT 1 FROM {node} WHERE type = :type AND uid = :uid", array(':type' => $type, ':uid' => $account->uid))->fetchField()) {
    // If the user has already created a node of a specific type, they cannot
    // create any more.
    return NODE_ACCESS_DENY;
  }

  // Otherwise do not affect any node access.
  return NODE_ACCESS_IGNORE;
}
1
Dave Reid