使用建议的hook_nodeapi() 仍然为时已晚。
如果您使用$op = load,您可能会耗尽您的内存,因为 Drupal 已经提交了它在加载节点时所做的所有正常事情(包括多次加载)。
如果您使用$op = view,则可以通过以下操作“伪造”它:
function mymodule_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
switch ($op) {
case 'view':
drupal_access_denied();
exit();
break;
}
}
但这不是真正的 403:除了在 Watchdog 中,它不会被报告,所有正常的东西仍然会加载和渲染,就好像节点在那里一样。
为了简单的破解,你可以使用hook_init():
function mymodule_init() {
$nodes_403 = array(42, 69, 187);
if (arg(0) == 'node' && in_array(arg(1), $nodes_403))
drupal_access_denied();
exit();
}
}
但这会不必要地绕过 Drupal 的内置权限系统。相反,您想利用 Drupal 的 node access rights 系统来拒绝对节点的访问。
如果您在模块中定义了自己的内容类型,则可以使用hook_access():
function mymodule_access($op, $node, $account) {
$nodes_403 = array(42, 69, 187);
if (in_array($node->nid, $nodes_403)) {
return FALSE;
}
}
但如果您不定义自己的自定义内容类型,则永远不会调用hook_access()。因此,您需要用自己的方式覆盖节点路径的 access callback:
function mymodule_menu_alter(&$items) {
$items['node/%node']['access callback'] = 'mymodule_access';
}
function mymodule_access($op, $node, $account = NULL) {
$nodes_403 = array(42, 69, 187);
if ($op == 'view' && in_array($node->nid, $nodes_403)) {
return FALSE;
}
return node_access($op, $node, $account);
}
由于hook_menu_alter() 的实现,请确保在实现上述操作后重建您的菜单系统。