如何以编程方式将访问分配给块?


10

我已经以编程方式创建了一个块,但是我不知道如何以编程方式分配对该块的访问。我该如何实现?


您能否扩展问题并显示代码?
Triskelion

在块代码本身中,您可以查找用户(全局$ user)并使用链接中的方法检查其角色。bywombats.com/blog/ryan/10-25-2007/...
user6614

面板模块具有一些使用区域而非块的出色访问控制。
路易(Louis)

Answers:


10

在从返回的数组中设置“角色”数组hook_block_info()不起作用,因为:

  • 从用户块中的block_admin_configure_submit()中保存了允许查看块以及在用户界面中设置的角色。

    $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函数检查从返回的数据中的role属性,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',
   )

这似乎是使用编程方法来实现此目的的最佳方法,因为您可以定义哪些角色可以访问,然后让Drupal确定用户是否可以访问它。我是否错过了这种方法的任何缺点?
user5013 2013年

如果必须以编程方式执行此操作,则可以。没有缺点。但是,我认为必须有一个很好的用例,以防止仅转到/ admin / structure / block并将角色分配给该块。
Triskelion 2013年

用例将自动为用户设置,因此他们不必这样做。严格来说是一个方便问题。设置好之后,如果不符合他们的特定需求,他们便可以将其更改为所需的形状。
user5013 2013年

1
这行不通;看到我的答案为什么没有。
kiamlaluno

0

假设您是使用hook_block_info()自己制作块,则可以在hook_block_view()函数中执行user_access()。查看api文档,因为他们有此示例。


是的,我应该考虑过使用user_access。完全让我忘了-D'oh。我考虑使用角色访问,但也许许可访问可能是更好的方法。
user5013 2013年

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

使用此代码,经过身份验证的用户(而非访客)将对已身份验证的用户可见块。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.