Jak dodać warunek dostępu do elementu menu?

17

Jak dodać nowe warunki do istniejących, które określają, czy element menu jest widoczny? Warunki te nie powinny ograniczać się do ustawień uprawnień.

Jako przykładowy przypadek użycia (niekoniecznie powód tego pytania): Załóżmy, że mam typ zawartości, w którym użytkownicy mogą tworzyć tylko jeden węzeł. Mam element menu służący do dodawania tego typu treści. Ale jeśli użytkownik utworzył już węzeł tego typu zawartości, chcę ukryć element menu. Moją pierwszą myślą jest uruchomienie zapytania w celu sprawdzenia istnienia węzła utworzonego przez bieżącego użytkownika, który ma określony typ zawartości. Jeśli taki istnieje, ukryj element menu.

Myślę, że ten rodzaj funkcjonalności powinien wejść hook_menu_alter()i dodać tam wymaganą logikę. Ale nie jestem pewien, jak to zrobić, nie omijając istniejących kontroli, takich jak sprawdzenie, czy użytkownik ma uprawnienia do tworzenia tego typu treści. Czy musiałbym uwzględnić tę logikę w swoim własnym stanie? Czy mogę dodać do istniejącej logiki dostępu bez nadpisywania jej?


Edycja: niektóre osoby wydają się skoncentrowane na odpowiedzi „jak ograniczyć użytkownika do utworzenia jednego węzła typu zawartości”. To nie jest pytanie tutaj. Pytanie brzmi: jak dodać niestandardowe warunki dostępu do elementu menu.

Chaulky
źródło

Odpowiedzi:

11

To, co musisz zrobić, to dodać swoje wywołanie zwrotne za pomocą hook_menu_alter (), a następnie w swoim wywołaniu zwrotnym po prostu wykonaj logikę, a następnie zwróć dane za pomocą oryginalnego wywołania zwrotnego.

Aby mieć pewność, że nie zastąpisz żadnych innych zmian hook_menu_alter (), powinieneś przekazać poprzednie wywołanie zwrotne do swojego wywołania zwrotnego za pomocą argumentu dostępu.

To wszystko jest teoretyczne, ale kod powinien wyglądać mniej więcej tak:

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);
}
Odszyfrować
źródło
więc jeśli przypisam nową funkcję oddzwaniania, czy to zdecydowanie zastąpi pierwotne oddzwonienie?
Chaulky
Tak, możesz mieć tylko jedno oddzwonienie dostępu do pozycji menu, dlatego upewnij się, że powrócisz do pierwotnego oddzwaniania. Widziałem moduł, który robi coś takiego, jeden z modułów ciężkich uprawnień, nie pamiętam który.
Odszyfruj
co robi shift_shift na $ args?
Chaulky
Wyciąga pierwszy argument z „argumentów dostępu”, które zrobiliśmy w starym „wywołaniu zwrotnym dostępu”. Więc jeśli starym wywołaniem zwrotnym było „MYMODULE2_access_callback”, właśnie to zwraca przesunięcie tablicy. Usuwa go również z tablicy, dzięki czemu przekazujemy tylko argumenty, których oczekuje wywołanie zwrotne.
Odszyfruj
1

W odpowiedzi na powyższe komentarze rozwiązaniem w D7 byłoby użycie:

/**
 * 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
źródło
1
Wydaje się, że nie ma to nic wspólnego z elementami menu. Nie znam jeszcze zbyt dobrze D7, ale wygląda na to, że jest to specyficzne dla tworzenia węzłów. Pytanie dotyczy ogólnie pozycji menu.
Chaulky,
Och, rozumiem ... to odpowiedź na mój komentarz z prośbą o więcej szczegółów na temat rozwiązania D7 zasugerowanego w odpowiedzi, która wskazuje na moduł Node Limit. Wciąż trochę nie na temat, ale doceniony.
Chaulky,
Ponieważ widoczność linków tworzenia typu mynodetype jest kontrolowana przez funkcję node_access (), która wywołałaby ten hak w Drupal 7.
Dave Reid
-1

Jedną z opcji byłoby utworzenie nowej roli, która ma uprawnienia do tworzenia zawartości dla danego typu zawartości. Gdy użytkownik utworzy węzeł tego typu, usuń tę rolę, a nie będzie mógł już więcej tworzyć.

cjworden
źródło
-1

Być może powinieneś wypróbować moduł Limit węzłów .

Ze strony projektu:

Moduł Limit węzłów pozwala administratorom ograniczyć liczbę węzłów określonego typu, które mogą tworzyć role lub użytkownicy. Na przykład jeśli witryna ma rolę „Reklamodawca”, która może tworzyć węzły „reklamowe”, to administrator limitu węzłów może ograniczyć wszystkich użytkowników w tej roli do określonej liczby węzłów. Może również ograniczać użytkowników dla poszczególnych użytkowników.

Dave Reid
źródło
Ograniczenie do jednego węzła jest tylko przykładem użycia dodania niestandardowej metody wywołania zwrotnego. Ponadto Limit węzłów nie usuwa pozycji menu, po prostu uniemożliwia użytkownikowi dodanie innego węzła tego typu treści.
Chaulky,
To prawda teraz, kiedy ponownie przeglądam opis modułu. Gdyby tak było na Drupal 7, byłoby to naprawdę łatwe, ponieważ można użyć hook_node_access ($ node, 'create', $ account), co wpłynęłoby na widoczność samego linku tworzenia typu węzła.
Dave Reid
To interesujące. Planuję wkrótce przejść na D7. czy mógłbyś napisać to bardziej szczegółowo i opublikować odpowiedź?
Chaulky,
Wersja D7 opublikowanej odpowiedzi.
Dave Reid