Свой модуль profile_taxonomy_on_node_addition Отображает на странице создания ноды термины таксономии, выбранные в поле профиля пользователя

Drupal: 

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

Задача: многопользовательский сайт, профиль пользователя имеет поле Компании (в которых работает пользователь) типа ссылка на термин с множественным выбором. При создании материала нужно отображать только те компании, в которых работает пользователь. Для роли администратор или редактор не ограничивать термины.

Реализация: пишем hook_node_form() в собственном модуле, в котором нужно ограничить термины таксономии поля Копания (о которой материал) только терминами из профиля пользователя.

Алгоритм программы: выбираем из таблицы field_data_field_companies все фирмы юзера, в которых entity_id совпадает с $user->uid то есть ид текущего юзера. И потом просматриваем массив поля $form['field_company'] - это массив терминов таксономии - и скрываем те, которых нет в выбранном массиве из бд.

 

profile_taxonomy_on_node_addition.module
  1. /*displays only user checked companies in node addition form in field_company*/
  2. /* field_companies - user profile field */
  3. /* field_company - node field */
  4.  
  5. function profile_taxonomy_on_node_addition_form_node_form_alter(&$form, &$form_state, $form_id) {
  6.  
  7. global $user;
  8. //if current user has roles administrator or editor return
  9. foreach ($user->roles as $role) {
  10. if (($role == 'administrator') || ($role == 'redaktor')) return;
  11. }
  12. if (isset($form['field_company'])) {
  13. //get user checked terms companies
  14. $terms = db_select('field_data_field_companies', 'c')
  15. ->fields('c', array('field_companies_tid'))
  16. ->condition('c.entity_id', $user->uid)
  17. ->execute()
  18. ->fetchCol();
  19. if ($terms) {
  20. //forming array of firms using $terms array
  21. $count=count($terms);
  22. foreach ($form['field_company']['und']['#options'] as $key=>$value) {
  23. if ($key == '_none') continue;
  24. $delete=true;
  25. for ($i=0;$i<$count;$i++) {
  26. if ($key == $terms[$i]) $delete = FALSE;
  27. }
  28. if ($delete) $form['field_company']['und'][$key]= array('#access' => FALSE);
  29. }
  30. }else {
  31. //hide field firm if user has no access to any term
  32. $form['field_company']['#access'] = FALSE;
  33. }
  34. }
  35. }

Так как это первый модуль, который я публикую на сайте, приведу еще и листинг файла profile_taxonomy_on_node_addition.info

name = Profile Taxonomy on Node Addition
description = If user checked field Companies it displays only user checked taxonomy terms in node addition page
core = 7.x
version = "7.x-1.0"
files[]= profile_taxonomy_on_node_addition.module

dependencies[] = taxonomy
package = MyModuls

 

Анализ кода модуля

Как скрыть термин таксономии из формы создания ноды?

Для этого есть опция #access у этого термина в переменной $form['field_company']['und']['id_термина']= array('#access' => FALSE); в данном примере имя поля field_company, вы можете заменить своим. Также отметим, что если обратиться к полю $form['field_company']['und']['id_термина']['#access'] = FALSE: то это не даёт эффекта (не могу пояснить почему). Так что в модуле мы заново определяем переменную $form['field_company']['und']['id_термина'] и сохраняем в ней массив, а не сразу обращаемся к переменной $form['field_company']['und']['id_термина']['#access']

Как скрыть выбор термина совсем (не показывать это поле для роли)?

$form['field_company']['#access'] = FALSE;

Как выбрать поля таблицы из базы данных?

Нежелательно использовать db_query(). В данном коде мы используем функцию db_select() так как она более друпал-вэй и может быть более динамичной (учитывать изменения в базе данных). Функция fetchCol(); выдаёт индексированный массив элементов. В то время как например функция fetchAll() выдавала бы массив объектов, что тоже можно было использовать, но объекты это требуют больше памяти и тормозят исполнение модуля (хотя в данном случае очень незначительно).