Табы в Друпале

При просмотре содержимого того или иного нода в CMF Drupal можно заметить наличие вкладок «Просмотр», «Изменить» и прочих:

Выбор одной из них позволяет пользователю осуществить то или иное действие с просматриваемым нодом. Вполне естественно, что при создании новых типов нодов нам может захотеться добавить к ним новые вкладки.

Делается это через систему меню, а точнее — в hook_menu. Предположим, нам нужно добавить к нодам локал таск tab1. Ноды доступны по внутреннему пути 'node/$nid', значит таб будет доступен по адресу 'node/$nid/tab1':

  1. function mymodule_menu() {
  2.   $items = array();
  3.  
  4.   $items['node/%/tab1'] = array(
  5.     'title' => 'Tab1',
  6.     'page callback' => '_view_tab1_page',
  7.     'page arguments' => array(1),
  8.     'access callback' => '_my_localtask_access',
  9.     'access arguments' => array(1),
  10.     'type' => MENU_LOCAL_TASK,
  11.   );
  12.  
  13.   return $items;
  14. } //function mymodule_menu

где _view_tab1_page генерирует содержимое таба, а _my_localtask_access — управляет доступом к этому содержимому.

Знак % — это так называемый wildcard (он же шаблон, метасимвол, символ подстановки), использующийся для передачи элемента пути в аргумент функции. В данном случае нам нужно передать элемент пути, соответствующий arg(1), в функции генерации страницы и контроля доступа. Предполагается, что элемент пути — это ID просматриваемого нода. Например для пути 'node/64/tab1' arg(1) вернет 64. Однако поскольку путь может быть намеренно изменен пользователем в адресной строке браузера на что угодно, его следовало бы валидировать — проверить, что это число, убедиться, что нод с таким ID существует и т.д.

Для удобства разработчики Друпала предусмотрели метасимвол с загрузкой. Запись '%node' в примере ниже позволяет передать в функции вместо arg(1) сразу результат работы node_load(arg(1)). То есть и валидировать элемент пути, и сразу загрузить нужный нод. Это, кстати, избавляет нас от необходимости дважды вызывать node_load() — сначала в функции доступа, а затем в функции генерации страницы.

  1. function mymodule_menu() {
  2.   $items = array();
  3.  
  4.   $items['node/%node/tab1'] = array(
  5.     'title' => 'Tab1',
  6.     'page callback' => '_view_tab1_page',
  7.     'page arguments' => array(1),
  8.     'access callback' => '_my_localtask_access',
  9.     'access arguments' => array(1),
  10.     'type' => MENU_LOCAL_TASK,
  11.   );
  12.  
  13.   return $items;
  14. } //function mymodule_menu

Возникает вопрос: а зачем вообще нужна функция доступа? Ведь мы можем просто передать 'access content' или что-то еще в стандартный коллбэк user_access(). Функция доступа _my_localtask_access используется для того, чтобы ограничить появление вновь созданных табов за пределами нашего нового типа нода (как известно, если функция доступа возвращает FALSE, элемент меню не генерируется).
  1. function _my_localtask_access($node) {
  2.   if ($node->type != 'my_node_type') return FALSE;
  3.        
  4.   return user_access('access content');
  5. } //function _my_localtask_access

С точки зрения логики это не совсем правильно: ведь мы не хотим запрещать доступ к локал таскам для других нодов, мы хотим, чтобы для них нашего таба просто не существовало. Но других вариантов нет.

Вот таким, немного странным, но коротким и аккуратным способом можно сделать табы для нодов.

Отправить комментарий

CAPTCHA
Пройдите, пожалуйста, проверку. Она нужна, чтобы отличать людей от спам-роботов. А если не хотите проходить эту проверку регулярно — зарегистрируйтесь.
Image CAPTCHA
Введите цифры, изображенные на картинке (без пробелов).