Wie füge ich einer Menüoption eine Zugriffsbedingung hinzu?


17

Wie kann ich neue Bedingungen zu vorhandenen Bedingungen hinzufügen, die bestimmen, ob ein Menüelement sichtbar ist? Diese Bedingungen sollten nicht auf Berechtigungseinstellungen beschränkt sein.

Beispiel für einen Anwendungsfall (nicht unbedingt der Grund für diese Frage): Angenommen, ich habe einen Inhaltstyp, für den Benutzer nur einen Knoten erstellen dürfen. Ich habe einen Menüpunkt zum Hinzufügen dieser Art von Inhalten. Wenn der Benutzer jedoch bereits einen Knoten dieses Inhaltstyps erstellt hat, möchte ich den Menüeintrag ausblenden. Mein erster Gedanke ist, eine Abfrage auszuführen, um die Existenz eines Knotens zu überprüfen, der vom aktuellen Benutzer erstellt wurde und der einen bestimmten Inhaltstyp aufweist. Falls vorhanden, verbergen Sie den Menüpunkt.

Ich würde denken, diese Art von Funktionalität sollte dort eingehen hook_menu_alter()und die erforderliche Logik hinzufügen. Ich bin mir jedoch nicht sicher, wie ich das tun soll, ohne die vorhandenen Prüfungen zu umgehen, z. B. zu prüfen, ob der Benutzer Berechtigungen zum Erstellen dieser Art von Inhalten hat. Müsste ich diese Logik in meinen eigenen Zustand einbeziehen? Oder kann ich die vorhandene Zugriffslogik erweitern, ohne sie zu überschreiben?


Bearbeiten: Einige Leute scheinen sich darauf zu konzentrieren, zu antworten, "Wie beschränke ich einen Benutzer auf das Erstellen eines Knotens eines Inhaltstyps". Das ist hier nicht die Frage. Die Frage ist, wie ich einem Menüelement benutzerdefinierte Zugriffsbedingungen hinzufüge.

Antworten:


11

Sie müssen lediglich Ihren Rückruf über hook_menu_alter () hinzufügen und dann in Ihrem Rückruf einfach Ihre Logik ausführen und dann die Daten über den ursprünglichen Rückruf zurückgeben.

Um sicherzugehen, dass Sie keine anderen hook_menu_alter () -Änderungen überschreiben, sollten Sie den vorherigen Rückruf über das Zugriffsargument an Ihren Rückruf übergeben.

Das ist alles theoretisch, aber der Code sollte ungefähr so ​​lauten:

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

Wenn ich also eine neue Access-Callback-Funktion vergebe, überschreibt dies definitiv den ursprünglichen Callback?
Chaulky

Ja, Sie können nur einen Zugriffsrückruf pro Menüelement durchführen. Stellen Sie daher sicher, dass Sie zum ursprünglichen Rückruf zurückkehren. Ich habe ein Modul gesehen, das so etwas macht, eines der berechtigungsintensiven Module, kann sich aber nicht erinnern, welches.
entziffern

Was macht array_shift auf $ args?
Chaulky

Es zieht das erste Argument aus den 'Zugriffsargumenten' heraus, die wir als alten 'Zugriffsrückruf' bezeichnet haben. Wenn der alte Rückruf also "MYMODULE2_access_callback" war, gibt array_shift dies zurück. Es wird auch aus dem Array entfernt, sodass nur die vom Rückruf erwarteten Argumente übergeben werden.
entziffern

1

In Reaktion auf die obigen Kommentare würde die Lösung in D7 lauten:

/**
 * 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
Dies scheint nichts mit Menüpunkten zu tun zu haben. Ich bin noch nicht so vertraut mit D7, aber es sieht so aus, als ob dies spezifisch für die Erstellung von Knoten ist. Die Frage konzentriert sich auf Menüpunkte im Allgemeinen.
Chaulky

Oh, ich verstehe ... dies ist eine Antwort auf meinen Kommentar, in dem ich Sie nach weiteren Details zu Ihrer in Ihrer Antwort vorgeschlagenen D7-Lösung frage, die auf das Node-Limit-Modul verweist. Noch ein bisschen abseits des Themas, aber sehr geschätzt.
Chaulky

Da die Sichtbarkeit der Links zum Erstellen von Mynodetypen durch die node_access () -Funktion gesteuert wird, wird dieser Hook in Drupal 7 aufgerufen.
Dave Reid

1

Sie suchen nach dem Chain Menu Access API- Modul.

Mit der Chain Menu Access API kann Ihr Modul seine eigenen Menüzugriffs-Rückruffunktionen in die Menürouter-Einträge anderer Module einbinden.

Es gibt mindestens ein Beispiel für die Verwendung von Drupal Stack Exchange.


-1

Eine Möglichkeit wäre, eine neue Rolle zu erstellen, die über die Berechtigung zum Erstellen von Inhalten für Ihren Inhaltstyp verfügt. Nachdem ein Benutzer einen Knoten dieses Typs erstellt hat, entfernen Sie diese Rolle und er kann keine weiteren erstellen.


-1

Vielleicht sollten Sie das Node Limit- Modul ausprobieren .

Von der Projektseite:

Mit dem Modul "Knotenbegrenzung" können Administratoren die Anzahl der Knoten eines bestimmten Typs einschränken, die Rollen oder Benutzer erstellen können. Wenn eine Site beispielsweise die Rolle "Werbetreibender" hat, mit der "Werbeknoten" erstellt werden können, kann der Administrator für Knotenbegrenzungen alle Benutzer in dieser Rolle auf eine bestimmte Anzahl von Knoten beschränken. Er kann Benutzer auch auf Benutzerbasis einschränken.


Die Beschränkung auf einen Knoten ist nur ein Beispiel für das Hinzufügen einer benutzerdefinierten Zugriffsrückrufmethode. Außerdem entfernt die Knotenbegrenzung das Menüelement nicht, sondern verhindert lediglich, dass der Benutzer einen weiteren Knoten dieses Inhaltstyps hinzufügt.
Chaulky

Das stimmt jetzt, wo ich die Modulbeschreibung nochmal durchschaue. Wenn dies auf Drupal 7 der Fall wäre, wäre es tatsächlich einfach, da Sie hook_node_access ($ node, 'create', $ account) verwenden können, was sich auf die Sichtbarkeit der Verknüpfung vom Typ create node auswirkt.
Dave Reid

Das ist interessant. Ich habe vor, bald zu D7 zu wechseln. Würde es Ihnen etwas ausmachen, es genauer zu schreiben und eine Antwort zu schreiben?
Chaulky

D7-Version der Antwort gepostet.
Dave Reid
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.