对于所有用户,我需要有条件地阻止访问“消息”类型的节点。用户应该能够查看这些消息节点的唯一方法是成功提交表单。
我是这样开始的:
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的类型为“message”,我想“解除”此特定节点和该用户的NODE_ACCESS_DENY(+在大多数情况下,这将是一个匿名用户)
有关实现此目标的不同方法的任何建议吗?
答案 0 :(得分: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变量。
答案 1 :(得分: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;
}