0

I have a views page with a menu tab in user profile, I want to hide it for some user roles.
I tried with hook_menu_alter

function hide_tabs_menu_alter(&$items) {
    global $user;
    if (in_array('gerant', array_values($user->roles))) {
        $items['user/%user/infos']['type'] = MENU_CALLBACK;
    }
}
  1. This doesn't hide the tab, but it works for other tabs -created by other modules- like user/%user/contact.
  2. I wanted this user still be able to see this tab in other users profile.

To add more information

There are two roles (gerant and etudiant). The permission should be View own info page which should be assigned to etudiant. gerant should not have it, but it should still be allowed to see user/%user/infos in etudiant's profiles.

7
  • Can you clarify what you want? It sounds like this is a tab on a user profile that you want shown conditionally not based on the role of the user viewing the profile, but rather on the roles possessed by the user that the profile itself is associated with, is that right?
    – Aaron
    Commented Sep 9, 2015 at 15:04
  • this is a tab that I want moderator see it in user profile,and hide it form in his user profile.
    – learner123
    Commented Sep 9, 2015 at 15:09
  • I would rather use permissions, which can be set for a view. It would also require less code, which means at least two hooks less.
    – avpaderno
    Commented Sep 9, 2015 at 20:27
  • @kiamlaluno using permissions on views allows users that doesn't have to moderator role to see the tab, but it will not allow moderator to see it in users profle.
    – learner123
    Commented Sep 10, 2015 at 8:27
  • If you create a new permission you just assign to a single role, and you use that permission to filter who can see a page/view, users with other roles would not see that page/view. And if you don't have a role that applies to those users who need to see that page/view, you create a new one. That is the correct Drupal way.
    – avpaderno
    Commented Sep 10, 2015 at 8:32

5 Answers 5

1

Finally it worked for me using hook_menu_local_tasks_alter(), thanks to drupal developers community.

function hide_tabs_menu_local_tasks_alter(&$data) {
  if (arg(0) == 'user' && is_numeric(arg(1))) {
    $uid = arg(1);
    $account = user_load($uid);
    if (in_array('gerant', array_values($account->roles))) {
      foreach ($data['tabs'][0]['output'] as $key => $value) {
        if ($value['#link']['path'] == "user/%/infos") {
          unset($data['tabs'][0]['output'][$key]);
        }
      }

    }
  }
}
0

You can give a try to this module tabtamer

Tab Tamer is an administration utility that provides easy re-ordering, hiding, and deactivation of tabs and subtabs. You can also rename tab labels.

Tab Tamer makes use of Drupal's drag ordering, but degrades gracefully when javascript is disabled.

0

How about creating 2 views. One with a tab and the other one without the tab.

View #1 has access role of anonymous, view #2 has access role of authenticated.

PS: By default views has access of permission, so click on access and change that to role.

0

You can't check anything about the user in hook_menu or hook_menu_alter. Whether or not a user has access to a given path is not determined at the time those hooks are run; instead, those hooks give you a chance to tell the system what functions should be called to determine access when the path is eventually accessed. That's the purpose of the access callback and access arguments options.

First, you need to determine the actual path that is registered. Since it's Views, the path is user/%views_arg/infos if you have validation turned on for the contextual filter, and user/%/infos if you don't have any validation for the contextual filter.

So try something like this:

function hide_tabs_menu_alter(&$items) {
  $items['user/%views_arg/infos']['access callback'] = 'hide_tabs_user_info_access_callback';
  $items['user/%views_arg/infos']['access arguments'] = array(1);
}

function hide_tabs_user_info_access_callback($uid) {
  if (($account = user_load($uid)) && ($role = user_role_load_by_name('moderator'))) {
    return !user_has_role($role->rid, $account);
  }
  return FALSE;
}

Also, since Views actually adds these paths in hook_menu_alter itself, you need to ensure your module runs after Views. So your module needs to either have a higher weight than Views, or implement hook_module_implements_alter. So add this to your module as well:

function hide_tabs_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'menu_alter') {
    $implementation = $implementations['hide_tabs'];
    unset($implementations['hide_tabs']);
    $implementations['hide_tabs'] = $implementation;
  }
}
10
  • this is not hiding the tab, you can check my code codeshare.io/Yx7Vk
    – learner123
    Commented Sep 9, 2015 at 15:52
  • @learner123 What is the name of the role for which you don't want the tabs to appear? Is the role name gerant, as your snippet implies? Or is that the name of a user?
    – Aaron
    Commented Sep 9, 2015 at 15:55
  • Yes, the role name is gerant, moderators are users have role gerant, it's not a name of user.
    – learner123
    Commented Sep 9, 2015 at 16:03
  • @learner123 Sorry, I forgot that Views adds its menu callbacks via hook_menu_alter so your module needs to run after Views' implementation of that hook. I've edited my answer.
    – Aaron
    Commented Sep 9, 2015 at 16:04
  • it's not working :( codeshare.io/ibAzP
    – learner123
    Commented Sep 9, 2015 at 16:39
0

The Views module uses hook_menu_alter() to add its pages. That is why hide_tabs_menu_alter() doesn't work: views_menu_alter() is invoked after hide_tabs_menu_alter(), and the changes made from your module are overridden from the Views module.
You need to change the order hooks are executed, implementing hook_module_implements_alter() or changing module weight.

function hide_tabs_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'menu') {
    $group = $implementations['hide_tabs'];
    unset($implementations['hide_tabs']);
    $implementations['hide_tabs'] = $group;
  }
}

As side note, rather than checking for a role, you should:

  • Create a user permission you assign to a specific role you use for those users who should see that page/view
  • Through the user interface, create a new role you assign just to those users who should see that page/view

To create a new user permission, your module needs to implement hook_permission() (Drupal 7.x) or hook_perm() (Drupal 6.x or previous). In your specific case, the permission would be two:

  • View own info page
  • View any info page

This is similar to what the Node module does, which defines the following permissions for each content type: edit own $type content and edit any $type content.

In your case, you cannot use user_access() as access callback, since that function can just check a single permission, which is then applied to every user. The code you would use should be similar to the following one.

function hide_tabs_user_info_access($account) {
  global $user;

  if ($account->uid == $user->uid) {
    // The logged-in user is viewing the page for their own account.
    return user_access('view own info page', $account);
  }
  else {
   // The logged-in user is viewing somebody else's page.
     return user_access('view any info page', $account);
  }

  // The previous lines can be simplified to the following one.
  // $permission = ($account->uid == $user->uid ? 'view own info page' : 'view any info page');
  // return user_access($permission, $account);
}

This is the code I would write.

function hide_tabs_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'menu') {
    $group = $implementations['hide_tabs'];
    unset($implementations['hide_tabs']);
    $implementations['hide_tabs'] = $group;
  }
}

function hide_tabs_menu_alter(&$items) {
  if (isset($items['user/%user/infos'])) {
    $items['user/%user/infos']['access callback'] = '';
    $items['user/%user/infos']['access arguments'] = array(1);
  }
}

function hide_tabs_user_info_access($account) {
  global $user;
  $permission = ($account->uid == $user->uid ? 'view own info page' : 'view any info page');

  return user_access($permission, $account);
}

(I will leave as exercise the implementation of hook_permission().)

Another error in your code is checking in hook_menu_alter() if the currently logged-in user has a role. That doesn't work because hook_menu_alter() is not always invoked; it is invoked when the information returned from hook_menu() needs to be re-build. You are not checking the role the logged-in user has, but the role of the user who is logged-in when Drupal re-builds the hook_menu() information.

1
  • checking if hook=menu give me an error ( hide_tabs in hide_tabs_module_implements_alter() ), I replaced it with hook=menu_alter, but it's not hiding the tab at all. I set the persmissons for the right roles. plz check if something is missing in my code codeshare.io/dwZei
    – learner123
    Commented Sep 11, 2015 at 16:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.