Come faccio ad aggiungere una condizione di accesso a una voce di menu?


17

Come posso aggiungere nuove condizioni oltre alle condizioni esistenti che determinano se una voce di menu è visibile? Queste condizioni non dovrebbero essere limitate alle impostazioni delle autorizzazioni.

Ad esempio un caso d'uso (non necessariamente il motivo di questa domanda): supponiamo che io abbia un tipo di contenuto di cui gli utenti sono autorizzati a creare solo un nodo. Ho una voce di menu per l'aggiunta di quel tipo di contenuto. Ma se l'utente ha già creato un nodo di quel tipo di contenuto, voglio nascondere la voce di menu. Il mio primo pensiero è di eseguire una query per verificare l'esistenza di un nodo creato dall'utente corrente che è del tipo di contenuto specifico. Se ne esiste uno, nasconde la voce di menu.

Penso che questo tipo di funzionalità dovrebbe entrare hook_menu_alter()e aggiungere lì la logica richiesta. Ma non sono sicuro di come farlo senza ignorare i controlli esistenti, come verificare se l'utente dispone delle autorizzazioni per creare quel tipo di contenuto. Dovrei includere quella logica nelle mie condizioni? Oppure posso aggiungere alla logica di accesso esistente senza sovrascriverla?


Modifica: alcune persone sembrano concentrate sulla risposta "come posso limitare un utente alla creazione di un nodo di un tipo di contenuto". Questa non è la domanda qui. La domanda è come aggiungere condizioni di accesso personalizzate a una voce di menu.

Risposte:


11

Quello che devi fare è aggiungere il tuo callback tramite hook_menu_alter (), e poi all'interno del tuo callback fai semplicemente la tua logica e poi restituisci i dati tramite il callback originale.

Per essere certi di non sovrascrivere altre modifiche hook_menu_alter (), è necessario passare il callback precedente al callback tramite l'argomento access.

Questo è tutto teorico, ma il codice dovrebbe andare in questo modo:

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);
}

quindi se assegno una nuova funzione di callback di accesso, questo sovrascrive definitivamente il callback originale?
Chaulky

Sì, è possibile avere un solo callback di accesso per voce di menu, quindi accertarsi di tornare al callback originale. Ho visto un modulo che fa qualcosa del genere, uno dei moduli pesanti permessi, ma non ricordo quale però.
Decifrare il

cosa sta facendo array_shift su $ args?
Chaulky

Estrae il primo argomento dagli "argomenti di accesso", che abbiamo creato il vecchio "callback di accesso". Quindi, se il vecchio callback era "MYMODULE2_access_callback", ecco cosa restituisce array_shift. Lo rimuove anche dall'array in modo che passiamo solo gli argomenti previsti dal callback.
Decifrare il

1

In risposta ai commenti sopra, la soluzione in D7 sarebbe quella di utilizzare:

/**
 * 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
Questo non sembra avere nulla a che fare con le voci di menu. Non ho ancora familiarità con D7, ma sembra che questo sia specifico per la creazione del nodo. La domanda è focalizzata sulle voci di menu in generale.
Chaulky

Oh capisco ... questo è in risposta al mio commento che richiede maggiori dettagli sulla tua soluzione D7 suggerita nella tua risposta che punta al modulo Node Limit. Ancora un po 'fuori tema, ma apprezzato.
Chaulky

Perché la visibilità dei collegamenti create mynodetype è controllata dalla funzione node_access (), che invocherebbe questo hook in Drupal 7.
Dave Reid

1

Stai cercando il modulo API di accesso al menu Chain .

L'API di accesso ai menu a catena consente al modulo di concatenare le proprie funzioni di richiamata di accesso ai menu nelle voci del router dei menu di altri moduli.

Esiste almeno un esempio su Drupal Stack Exchange su come usarlo.


-1

Un'opzione sarebbe quella di creare un nuovo ruolo che ha creato l'autorizzazione del contenuto per il tuo tipo di contenuto. Dopo che un utente ha creato un nodo di quel tipo, togli quel ruolo e non sarà più in grado di crearlo.


-1

Forse dovresti provare il modulo Node Limit .

Dalla pagina del progetto:

Il modulo Limite nodo consente agli amministratori di limitare il numero di nodi di un tipo specifico che possono essere creati da ruoli o utenti. Ad esempio, se un sito ha un ruolo "Inserzionista" in grado di creare nodi "pubblicitari", l'amministratore del limite nodo può limitare tutti gli utenti in quel ruolo a un numero specifico di nodi. Può anche limitare gli utenti per utente.


Limitare a un nodo è solo un esempio di caso d'uso per l'aggiunta di un metodo di callback di accesso personalizzato. Inoltre, Node Limit non rimuove la voce di menu, ma impedisce all'utente di aggiungere un altro nodo di quel tipo di contenuto.
Chaulky

È vero ora che guardo di nuovo la descrizione del modulo. Se questo fosse su Drupal 7, in realtà sarebbe facile poiché puoi usare hook_node_access ($ node, 'create', $ account) che influirebbe sulla visibilità del link stesso tipo di nodo di creazione.
Dave Reid,

Interessante. Ho intenzione di passare presto alla D7. ti dispiacerebbe scriverlo in modo più dettagliato e pubblicare una risposta?
Chaulky

Versione D7 della risposta pubblicata.
Dave Reid,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.