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

17

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.

À titre d'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 y entrer 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 à la création d'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.

Chaulky
la source

Réponses:

11

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 que vous n'écrasez aucune autre modification hook_menu_alter (), vous devez passer 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);
}
Déchiffrer
la source
donc si j'attribue une nouvelle fonction de rappel d'accès, cela écrase-t-il définitivement le rappel d'origine?
Chaulky
Oui, vous ne pouvez avoir qu'un seul rappel d'accès par élément de menu, assurez-vous donc que vous revenez au rappel d'origine. J'ai vu un module qui fait quelque chose comme ça, l'un des modules lourds d'autorisations, mais je ne me souviens pas lequel.
Déchiffrez
que fait array_shift sur $ args?
Chaulky
Il extrait le premier argument des «arguments d'accès», dont nous avons fait l'ancien «rappel d'accès». Donc, si l'ancien rappel était 'MYMODULE2_access_callback', c'est ce que array_shift renvoie. Il le supprime également du tableau afin que nous ne transmettions que les arguments attendus par le rappel.
Déchiffrez
1

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;
}
Dave Reid
la source
1
Cela ne semble avoir rien à voir avec les éléments de menu. Je ne connais pas encore bien D7, mais il semble que cela soit spécifique à la création de nœuds. La question est centrée sur les éléments de menu en général.
Chaulky
Oh je vois ... c'est en réponse à mon commentaire demandant plus de détails sur votre solution D7 suggérée dans votre réponse qui pointe vers le module Node Limit. Encore un peu hors sujet, mais apprécié.
Chaulky
Parce que la visibilité des liens create mynodetype est contrôlée par la fonction node_access (), qui invoquerait ce hook dans Drupal 7.
Dave Reid
1

Vous recherchez le module API Chain Menu Access .

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 un exemple sur Drupal Stack Exchange sur la façon de l'utiliser.

crantok
la source
-1

Une option serait de créer un nouveau rôle disposant de l'autorisation de création de contenu pour votre type de contenu. Une fois qu'un utilisateur a créé un nœud de ce type, supprimez ce rôle et il ne pourra plus en créer.

cjworden
la source
-1

Vous devriez peut-être essayer le module Node Limit .

Depuis la page du projet:

Le module Node Limit permet aux administrateurs de limiter le nombre de nœuds d'un type spécifique que les rôles ou les utilisateurs peuvent créer. Par exemple, si un site a un rôle "Annonceur" qui peut créer des nœuds "publicité", l'administrateur de limite de nœuds peut restreindre tous les utilisateurs de ce rôle à un nombre spécifique de nœuds. Il peut également restreindre les utilisateurs par utilisateur.

Dave Reid
la source
La limitation à un nœud n'est qu'un exemple d'utilisation pour ajouter une méthode de rappel d'accès personnalisé. De plus, Node Limit ne supprime pas l'élément de menu, il empêche simplement l'utilisateur d'ajouter un autre nœud de ce type de contenu.
Chaulky
C'est vrai maintenant que je regarde à nouveau la description du module. Si c'était sur Drupal 7, ce serait en fait facile car vous pouvez utiliser hook_node_access ($ node, 'create', $ account) qui affecterait la visibilité du lien de création de type de nœud lui-même.
Dave Reid
C'est intéressant. Je prévois de passer bientôt au D7. Pourriez-vous l'écrire plus en détail et poster une réponse?
Chaulky
Version D7 de la réponse publiée.
Dave Reid