The arg passed to the Drupal user_access function from hook_menu looks like this: Array('some permission')

Can someone please tell me...
1. how to pass multiple args to a custom access control function.

2. how to pass a single array of args

I couldn't get anything to work.

Comments

mechler’s picture

I've handled this sort of issue by providing my own callback function. I used hook_menu_alter() to change the 'access callback' property of the item I needed to modify access to. For example, the edit user item looks like this by default:

$items['user/%user_category/edit'] = array(
    'title' => 'Edit',
    'page callback' => 'user_edit',
    'page arguments' => array(1),
    'access callback' => 'user_edit_access',
    'access arguments' => array(1),
    'type' => MENU_LOCAL_TASK,
    'load arguments' => array('%map', '%index'),
    'file' => 'user.pages.inc',
  );

I change it with my hook_menu_alter implementation:

function module_menu_alter(&$items) {
  $items['user/%user_category/edit']['access callback'] = 'module_user_edit_access';
} // function module_menu_alter

Then I use my own custom callback function to call the original as well as my own new access parameters.

function module_user_edit_access($account) {
  // If the user has edit access through the normal callback or the module would grant access, return TRUE
  return (user_edit_access($account) || module_other_access($a, $b))
} // function module_user_edit_access

Web Developer, Iowa State University College of Veterinary Medicine

rnealxp’s picture

Thanks for taking the time to share this.

Can you not just skip usage of hook_menu_alter to tweak 'access callback' and just specify the desired method string for 'access callback' within hook_menu (that is, set it to 'module_user_edit_access' in the first place)? (Is hook_menu_alter required?)

What does 'array(1)' do for you in 'access arguments'? (Asking because I don't understand it's purpose.)

If this function had 3 args like so:

function module_user_edit_access($account, $a, $b) {
  // If the user has edit access through the normal callback or the module would grant access, return TRUE
  return (user_edit_access($account) || module_other_access($a, $b))
} // function module_user_edit_access

Is there not a way to set 'access arguments' so that the 3 args could be successfully passed? (Or can only one scalar variable be passed?)

Thanks a million. I won't drain your energy further if you risk a reply.

mechler’s picture

No worries. I'll try to explain as best I can. I'm newish to Drupal development myself. :)

The hook_menu() called by the user module already sets up this menu item. I suppose I didn't specify that. This particular menu item that I'm using as an example is the EDIT tab (MENU_LOCAL_TASK) that you see when viewing a user (if you have appropriate permissions set up, of course). We only want to modify the access to this menu item if that module is enabled (core, in this case) and so we need to use hook_menu_alter() to make alterations to an item that is already in place.

The use of array(N) passes the N-th parameter of the URI (starting with 0). It's basically just exploding the URI with regards to '/' and returning the resulting array's [N] value. If the menu item looks like this $items['user/%user_category/edit'], then array(1) will pass the value where %user_category is. You could just use a "%" instead of using the label, too, but using the label fires the hook label_load($a) where $a is equal to the value in the place that the wildcard was. In this case, it will call user_category_load($uid) where $uid is equal to the number in that position. Navigating to index.php?q=user/rnealxp/edit for example would try to run user_category_load('rnealxp') which in this case would fail because it's expecting an int representing a uid. I'm just providing this example in the hopes that it will further explain and cement your understanding of how this works.

If you wanted to pass three different args to the function defined in the 'access callback', you'd pass them as an array of values. $items['user/%user_category/edit']['access arguments'] = array(foo, bar, qin) would pass multiple values to the access callback function.

I hope this helps.

Web Developer, Iowa State University College of Veterinary Medicine

rnealxp’s picture

Thanks for the good explanation. I wish Drupal could be configured to notify us by email when replies are made. Many good discussion forums have such a feature and it helps to keep the momentum going on discussions. Again, thanks!