All the pieces of the original user menu items are defined in modules/user/user.module
via the User Module's hook_menu()
. The key ones here are (IMHO) user/%user
for viewing the user page, and user/%user/edit
for editing it, eg pages like user/1
to look at uid 1's user page, and user/1/edit
to edit that same page.
So, from a logic standpoint, I am going to assume you want this:
If a user wants to look at or edit his or her own page, allow them to
do so. Furthermore, if another user has appropriate permissions,
allow them to look at and/or edit these pages as well. But no one else
should be able to look at any other user's pages (let alone edit
them).
Ok, so how can we do this. Let's first look at the original view the user page menu item:
$items['user/%user'] = array(
'title' => 'My account',
'title callback' => 'user_page_title',
'title arguments' => array(1),
'page callback' => 'user_view_page',
'page arguments' => array(1),
'access callback' => 'user_view_access',
'access arguments' => array(1),
// By assigning a different menu name, this item (and all registered child
// paths) are no longer considered as children of 'user'. When accessing the
// user account pages, the preferred menu link that is used to build the
// active trail (breadcrumb) will be found in this menu (unless there is
// more specific link), so the link to 'user' will not be in the breadcrumb.
'menu_name' => 'navigation',
);
Here we would want to change the 'access callback'
to include further logic, so the menu alter would only have to change that, nothing else, eg, something along the lines of this:
function YOURMODULE_menu_alter(&$items) {
$items['user/%user']['access callback']='YOURMODULE_user_access';
}
and then you could write something like this:
function YOURMODULE_user_access($account) {
if ($account->uid) { // so we don't try to look at an anonymous user
$account = user_load($account->uid); // load the full user object (ADDITION: was user_load($uid) in original post, oops)
if ($GLOBALS['user']->uid == 1) { // admin super user
return TRUE;
}
if ($GLOBALS['user']->uid == $account->uid) {
return TRUE; // same user so allow (we will assume blocked users aren't logged in)
}
if ( /* whatever logic you need to allow coordinators to access the user is TRUE */ ) {
return TRUE; // or return $account->status; if you want to take blocked accounts into effect
}
}
return FALSE;
}
So, barring any brain freezes or typos on my part, the above should work for viewing, but I did just type it in freehand, so buyer beware. But, now, let's look at the original user edit menu item:
$items['user/%user/edit'] = array(
'title' => 'Edit',
'page callback' => 'drupal_get_form',
'page arguments' => array('user_profile_form', 1),
'access callback' => 'user_edit_access',
'access arguments' => array(1),
'type' => MENU_LOCAL_TASK,
'file' => 'user.pages.inc',
);
And once again, all you want or need to do is change the 'access callback'
, eg, your hook_menu_alter()
is now...
function YOURMODULE_menu_alter(&$items) {
$items['user/%user']['access callback']='YOURMODULE_user_access';
$items['user/%user/edit']['access callback']='YOURMODULE_user_access';
}
and yes, since the logic is the same, you can use the same function all over again.
Caveats: We are totally ignoring Drupal's built in permissions, eg, user_access('access user profiles')
and user_access('administer users')
in the above.
Also, if you find after doing this you can't load user.pages.inc
, Drupal is most probably looking for it in your module's directory instead of the user module's where it sits, so set 'file' => drupal_get_path('module', 'user') . '/user.pages.inc'
and you should be set.
Anyways hope this stream of consciousness helps out!
'access callback' => 'my_module_validate'
but the function is namedmymodule_validate
- was it just a typo while obfuscating name to paste it here? Also, please don't just say I can't make it work - it's useless. What happens? What have you expected? What's the difference? What error messages are on screen, watchdog, error.log?