Posted by pelsdyret on October 5, 2012 at 4:45pm
I have two weird issues with hook_node_access().
I have created to modules, say module1 and module2. They both reside under site/all/modules/custom.
In module1 I have among other stuff:
function module1_node_access($view, $node) {
// code omitted
return false;
}Note the parameters, $view and $node; I tried first with $node, $op, $account, but it dies with a "missing argument 3 for module1_node_access". Besides that, it works, and setting the return value to false produces a Drupal "not authorized" message as expected.
Now, in module2, I am able to use the hook_node_access parameters as expected according to the API:
function module2_node_access($node, $op, $account) {
// code omitted
echo "module2_node_access()";
return false;
}But the return value is completely ignored. I know the module2_node_access function is being called.
I have tried to return NODE_ACCESS_DENY instead with no change.
Any clues? Thanks.
Comments
Why are you echoing the
Why are you echoing the function name? Don't you want to call the function?
Jaypan We build websites
Just to show we're being called
Don't worry about te echo. It's just to show that we're inside the function/we're being called.
I don't think you will see
I don't think you will see the echo in a function like node_access
if you really want to see if it works, you could use
drupal_set_message('I got called in hook_node_access');if it doesn't work, you could try clearing your cache
You're right about that...
Actually I use drupal_debug(...) which produces the expected output. The echo was just for the (bad) example.
I've cleared the cache several times. It's not that.
It could be 2 things I can
It could be 2 things I can think off.
Either your module name or your hook name have a spelling error.
Or you are logged in as superadmin(user id: 1) which overrides all access control.
If you are logged in with your admin account, try using a normal created account.
No spelling errors
Thank you for your suggestions. However, there are no spelling errors and the hooks are being called but in module1's case with incorrect number of parameters.
Also, I am logged as a regular user, not as admin, which is seen by the fact that a "return false" in module1_node_access(...) correctly forces Drupal to display a "unauthorized"-page.
Can you post the exact code
Can you post the exact code you are using for hook_node_access, maybe it will help solve te problem.
The Code
I appreciate the feedback. However, the warning happens when coursepermission_node_access(...) is being called by core.
An interesting thing is that I disabled "module1" that had the problem with being called by wrong number of paramters, and now module2 (coursepermission in the following) complains about the same thing.
Instead of being called with the paramters ($node, $op, $account), I get ($view, $node).
Anyway, here is the code:
/*
* implements hook_menu_alter()
*/
function coursepermission_menu_alter(&$items) {
$items['node/%node']['access callback'] = 'coursepermission_node_access';
}
/*
* implements hook_node_access()
*/
function coursepermission_node_access($node, $op, $account) {
if(is_string($node)) return true;
// Check only for content of type course and course_session
if($node->type != 'course' && $node->type != 'course_session') return true;
// Check if user has access to this course by looking up taxonomy terms
// We may be called more than once so cache $profile
static $profile = null;
if(empty($profile)) $profile = profile2_load_by_user($account, 'student');
$fields = field_view_field('profile2', $profile, 'field_classes');
$courseList = array();
foreach($fields['#items'] as $item) {
$name = $item['taxonomy_term']->name;
$courseList[] = substr($name, 0, strrpos($name, '-'));
}
$moduleTid = $node->field_module[$node->language][0]['tid'];
$moduleName =
db_query("select name from {taxonomy_term_data} where tid=:tid",
array(':tid'=>$moduleTid))->fetchField();
$ok = in_array($moduleName, $courseList);
if(!$ok) @watchdog('coursepermission', "Access to %node denied for student %student.",
array('%node'=>$node->nid, '%student'=>$account->uid), WATCHDOG_NOTICE);
return $ok ? NODE_ACCESS_IGNORE : NODE_ACCESS_DENY;
}
This results in the following:
Warning: Missing argument 3 for coursepermission_node_access() in coursepermission_node_access() (line 12 of [omitted...]/sites/all/modules/custom/coursepermission/coursepermission.module).Being called by _menu_check_access
Just a little bonus info: My coursepermission_node_access(...) is being called by _menu_check_access(...). I stepped through the code to see this.
function _menu_check_access(&$item, $map) {// Determine access callback, which will decide whether or not the current
// user has access to this path.
$callback = empty($item['access_callback']) ? 0 : trim($item['access_callback']);
// Check for a TRUE or FALSE value.
if (is_numeric($callback)) {
$item['access'] = (bool) $callback;
}
else {
$arguments = menu_unserialize($item['access_arguments'], $map);
// As call_user_func_array is quite slow and user_access is a very common
// callback, it is worth making a special case for it.
if ($callback == 'user_access') {
$item['access'] = (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
}
elseif (function_exists($callback)) {
$item['access'] = call_user_func_array($callback, $arguments);
}
}
}
Maybe it has to do with if($callback == 'user_access') stuff, that appears to call a module hook with two parameters...?
A workaround
This workaround inserted at the beginning of the function appears to work:
function coursepermission_node_access($node, $op, $account = null) {// Workaround when called with two parameters (artisteer issue?)
if($account == null) {
$_op = $op;
$op = $node;
$node = $_op;
unset($_op);
$account = &$GLOBALS['user'];
}
I'm beginning to suspect this has to do with my theme, which is created by the Artisteer product.
Your problem is probably
Your problem is probably coming from your hook_form_alter(). Hooks are called automatically, and you have hard-coded yours in. This means it's probably not getting the parameters the function expects, since it's not being called in the place it's meant to be called.
Jaypan We build websites
No hooks are being called manually
Thanks for taking time to commenting on this.
However, I'm not calling any hooks manually. The code above is taken from core.
A suggestion
Hello,
Sorry to interrupt :) . You don't need the following:
function coursepermission_menu_alter(&$items) {$items['node/%node']['access callback'] = 'coursepermission_node_access';
}
I believe that is what Jaypan is referring too.
The main purpose of the Drupal's "menu" system is to map requests to code that services the request with a response. The "hook" system doesn't require you to map a url/path before the implemented "hook" is called.
The errors you were getting were likely due to that fact that you overrode a request path with a "named" wildcard argument.
Thinking is the best way to travel.
Thanks, goofus
Thank you, goofus, for clarifying on this. I'll will check it out. :)