3

对于所有用户,我需要有条件地阻止对“消息”类型节点的访问。用户应该能够查看这些消息节点的唯一方法是成功提交表单。

我是这样开始的:

  function mymodule_node_access($node, $op, $account) {
    if ($op == 'view' && $node->type == 'message') {
      return NODE_ACCESS_DENY;
    }
  }

但是,我希望在成功提交表单后允许查看访问这种类型的单个节点:

function form_submit($form, &$form_state) {
  // some logic here  
  $form_state['redirect'] = 'node/255';
}

所以节点 255 的类型是“消息”,我想“解除”这个特定节点和这个用户的 NODE_ACCESS_DENY(+ 在大多数情况下,这将是一个匿名用户)

关于实现这一目标的不同方法的任何建议?

4

2 回答 2

4

您可以这样做的唯一方法是在表单提交处理程序中设置一个值,然后由hook_node_access(); 您可以使用 Drupal 变量或保存在数据库表中的值。您需要存储访问表单的用户的用户 ID,以及已提交该表单的每个节点的节点 ID。

假设您使用 Drupal 变量,您可以使用类似于以下的代码:

function mymodule_form_submit($form, &$form_state) {
  global $user;
  $message_nid = 255;
  $values = variable_get('access_nid', array());

  if (isset($values[$user->uid])) {
    if (!isset($values[$user->uid][$message_nid])) {
      $values[$user->uid][$message_nid] = $message_nid;
    }
  }
  else {
    $values[$user->uid] = array($message_nid => $message_nid);
  }

  variable_set('access_nid', $values);
  $form_state['redirect'] = 'node/' . $message_nid;
}

function mymodule_node_access($node, $op, $account) {
  $result = NODE_ACCESS_IGNORE;

  if ($op == 'view' && $node->type == 'message') {
    $values = variable_get('access_nid', array());
    if (!empty($values[$account->uid]) {
      if (isset($values[$account->uid][$node->nid])) {
        unset($values[$account->uid][$node->nid]);
        $result = NODE_ACCESS_ALLOW;
      }
      else {
        $result = NODE_ACCESS_DENY;
      }
    }
    else {
      $result = NODE_ACCESS_DENY;
    }
  }
  variable_set('access_nid', $values);

  return $result;
}

注意这段代码只允许用户访问一个节点一次;如果用户第二次尝试访问同一个节点,用户将收到“拒绝访问”错误。如果不希望这样做,则应将第二个函数重写如下:

function mymodule_node_access($node, $op, $account) {
  if ($op == 'view' && $node->type == 'message') {
    $values = variable_get('access_nid', array());
    if (!empty($values[$account->uid]) {
      if (isset($values[$account->uid][$node->nid])) {
        return NODE_ACCESS_ALLOW;
      }

      return NODE_ACCESS_DENY;
      }
    }
    else {
      $result = NODE_ACCESS_DENY;
    }
  }

  return NODE_ACCESS_IGNORE;
}

我使用 Drupal 变量来编写简单的代码;在这种情况下,如果可以创建该内容类型节点的用户很少,则应该使用 Drupal 变量;如果有很多用户可以创建这些节点,那么使用数据库表会更好。
同样在使用 Drupal 变量时,Drupal 使用的是数据库表;不同之处在于该数据库表的内容始终加载到内存中。如果您需要存储大量数据,则不应使用 Drupal 变量。

于 2011-07-29T17:39:06.007 回答
2

使用 $_SESSION 的修改解决方案,因为我主要与匿名用户一起工作:

function mymodule_form_submit($form, &$form_state) {
  $message_nid = 255;
  if (!isset($_SESSION['node_access'])) {
    $_SESSION['node_access'] = array();
  }
  if (!isset($_SESSION['node_access']['nid'])) {
    $_SESSION['node_access']['nid'] = $message_nid;
  }
  $form_state['redirect'] = 'node/' . $message_nid;
}

function mymodule_node_access($node, $op, $account) {
  $node_access = NODE_ACCESS_IGNORE;
  if ($op == 'view' && $node->type == 'message') {
    if (isset($_SESSION['node_access'] && !empty($_SESSION['node_access'])) {
      if ($node->nid == $_SESSION['node_access']['nid']) {
        unset($_SESSION['node_access']['nid']);
        $node_access = NODE_ACCESS_ALLOW ;
      } else {
        unset($_SESSION['node_access']['nid']);
        $node_access = NODE_ACCESS_DENY;
      }
    } else {
      $node_access = NODE_ACCESS_DENY;
    }
  }
  return $node_access;
}
于 2011-07-31T11:43:51.260 回答