2011-07-29 42 views
3

對於所有用戶,我需要有條件地阻止對'message'類型節點的訪問。用戶應該能夠查看這些消息節點的唯一方法是成功提交表單。Drupal 7 hook_node_access有條件地阻止節點訪問

我開始是這樣的:

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(+在大多數情況下這將是一個匿名用戶)

關於不同的任何建議如何實現這一目標?

回答

4

你可以做到這一點的唯一方法是在表單提交處理程序中設置一個值,然後通過hook_node_access()進行檢查;你可以使用Drupal變量,或者保存在數據庫表中的值。 您需要存儲訪問該表單的用戶的用戶標識以及爲其提交此表單的每個節點的節點標識。

假如你使用一個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變量。

+0

謝謝你的指針,我第一次在Drupal使用的變量。我有一個工作解決方案(下面張貼) - 不知道這是最優雅的解決方案,但工程! – pragnatek

+0

@pragnatek我已經更新了我的答案。 – kiamlaluno

+0

感謝您的幫助 - 我第一次學習了很多嘗試爲node_access和node_access使用varaibles。我越來越近了! – pragnatek

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