Как программно назначить доступ к блоку?

10

Я создал блок программно, но я не знаю, как я могу программно назначить доступ к нему. Как мне этого добиться?

user5013
источник
Не могли бы вы расширить свой вопрос и показать свой код?
Трискелион,
В самом коде блока вы можете найти пользователя (global $ user) и проверить его роль, используя метод в ссылке. bywombats.com/blog/ryan/10-25-2007/...
user6614
Модуль Panels имеет несколько отличных элементов управления доступом, использующих регионы, а не блоки.
Луи

Ответы:

10

Установка массива "role" в массиве, возвращаемом из hook_block_info(), не работает, потому что:

  • Роли, которым разрешено видеть блок и которые установлены в пользовательском интерфейсе, сохраняются из block_admin_configure_submit () в таблице "block_role"

    $query = db_insert('block_role')->fields(array('rid', 'module', 'delta'));
    foreach (array_filter($form_state['values']['roles']) as $rid) {
      $query->values(array(
        'rid' => $rid,
        'module' => $form_state['values']['module'],
        'delta' => $form_state['values']['delta'],
      ));
    }
    $query->execute();
    
  • Код, который решает, какие блоки следует показать текущему вошедшему в систему пользователю, содержится в block_block_list_alter () , который является реализацией hook_block_list_alter () , и использует только содержимое этой таблицы.

    $result = db_query('SELECT module, delta, rid FROM {block_role}');
    foreach ($result as $record) {
      $block_roles[$record->module][$record->delta][] = $record->rid;
    }
    
    foreach ($blocks as $key => $block) {
      if (!isset($block->theme) || !isset($block->status) || $block->theme != $theme_key || $block->status != 1) {
        // This block was added by a contrib module, leave it in the list.
        continue;
      }
    
      // If a block has no roles associated, it is displayed for every role.
      // For blocks with roles associated, if none of the user's roles matches
      // the settings from this block, remove it from the block list.
      if (isset($block_roles[$block->module][$block->delta]) && !array_intersect($block_roles[$block->module][$block->delta], array_keys($user->roles))) {
        // No match.
        unset($blocks[$key]);
        continue;
      }
    
      // …
    
    }
    
  • Существует не другой Drupal функция , которая проверяет роли собственности в данных , возвращаемых hook_block_info(), ни содержание «block_role» таблицы объединены с тем, что возвращаемые из hook_block_info()реализаций.

Вы можете убедиться, что у пользователя есть требуемая роль, чтобы видеть блок hook_block_view(), но в этот момент Drupal уже рендерит блок; это означает, что пользователь все равно будет видеть заголовок блока, если он уже был установлен.

Что вы можете сделать, так это реализовать hook_block_list_alter()удаление информации об этом блоке, когда у пользователя нет требуемой роли.
Чтобы избежать путаницы с пользователями, которые управляют блоками, я также изменил бы форму, используемую для редактирования блока, и отключил бы поле формы, используемое для определения того, какие роли могут видеть этот блок, поскольку модуль, реализующий его, будет использовать свой собственный список. ролей; минимальный код должен по крайней мере показывать сообщение о том, что параметры роли не имеют никакого эффекта, но я бы также отключил элементы формы для параметров роли.

Поскольку модуль «Блок» уже отображает поля формы для выбора ролей, которые видят блок, вы также можете просто установить значение по умолчанию для своего блока и позволить администраторам изменять его при необходимости.

Скриншот

В соответствии с проверкой ролей пользователя по сравнению с проверкой полномочий пользователя, последняя является предпочтительной, особенно когда альтернативой будет жесткое кодирование списка ролей в модуле.
Как показано в модуле «Блок», использование разрешения - не единственная альтернатива: модуль может иметь настройку для решения, каким ролям разрешено что-либо видеть.
Понятно, что не всегда стоит иметь настройки, для которых ролям разрешено что-то делать. Я также представляю, что для пользователей с администратором означало бы, если бы у 10 модулей были свои собственные настройки, для которых ролям разрешено что-то делать, вместо того, чтобы использовать разрешения и разрешать пользователям-администраторам использовать одну страницу для их установки.

киамлалуно
источник
Что ж, мне, очевидно, придется согласиться с этим как с наиболее подходящим ответом. Спасибо за подробное объяснение, поскольку оно действительно помогает понять, как блоки Drupal работают за кулисами.
user5013
1

В вашем hook_block_info вы можете попробовать что-то вроде:

$blocks['myblock'] = array(
   ...
   'roles' => array(
      'administrator' => '3',
      'authenticated user' => '2',
   )
Triskelion
источник
Кажется, это лучший способ реализовать это, используя программный подход, так как вы определяете, какие роли имеют доступ, а затем позволяете Drupal определить, может ли пользователь получить к нему доступ или нет. Я пропустил какие-либо недостатки этого подхода?
user5013
Если вы должны сделать это программно, да. Нет недостатков. Однако я бы предположил, что должен быть очень хороший вариант использования против простого перехода в / admin / structure / block и назначения ролей в блок.
Трискелион,
Вариант использования будет автоматически выполнять настройку для пользователя, чтобы им не пришлось это делать. Собственно вопрос удобства. После установки они могут изменить его на то, что им нужно, если это не соответствует их конкретным потребностям.
user5013
1
Это не работает; см. мой ответ, почему это не так.
kiamlaluno
0

Предполагая, что вы делаете блоки самостоятельно с помощью hook_block_info (), вы можете просто выполнить user_access () в своей функции hook_block_view (). Проверьте API документы, так как у них есть пример этого.

jdwfly
источник
Да, я должен был подумать об использовании user_access. Полностью проскользнуло у меня в голове - Д'Ох. Я думаю об использовании доступа по ролям, но, возможно, доступ с разрешениями может быть лучшим способом.
user5013
0

Это невозможно в hook_block_info (), но вы можете использовать этот запрос для достижения этой цели. Измените MODULE_NAME, BLOCK_DELTA и RID соответственно

$query = db_insert('block_role')
  ->fields(array(
    'module' => 'MODULE_NAME', 
    'delta' => 'BLOCK_DELTA', 
    'rid' => 2, // Authenticated User
  ))
  ->execute();
Пол Бениш
источник
0

В hook_block_view вы можете использовать, global $userчтобы получить информацию о пользователе, затем, в зависимости от роли пользователя, вы можете назначить другой block['subject']и block['content']даже не назначать какой-либо предмет и контент для блокировки, если он будет невидимым для этой роли. вот пример:

function ModuleNAME_block_view($delta = '') {
  switch ($delta) {
    case 'Your_BLOCK' :
      Global $user;
      if($user->uid != '0') {
        $block['subject'] = 'SUBJECT';
        $block['content'] = 'SOME CONTENT OR A FUNCTION FOR BLOCK';
      }
      break;
  }
  return $block;
}

при использовании этого кода аутентифицированные пользователи (не гости) получат блокировку для аутентифицированных пользователей.

Алиреза Табатабаян
источник