This, or similar, has been asked before but I have yet to find an answer. Can this be done?
Please note that I do not want to do this for entire blocks, just single menu items. I have attempted to install Simple Access but I get too many errors so have abandoned this. I'm not even sure that this does what I want.
It seems I have control over the visibility of blocks and pages but not an individual menu item!
Any help would be greatly appreciated.

Comments

stanbroughl’s picture

***i'm curious about this too - bookmarking for later***

rivena’s picture

I don't know if this helps, but when a menu item is made by a module, the module can apply access control to it, so that only people with appropriate permissions can see 'create a forum post' for example.

I eventually just separated it out into blocks, so I have an Admin block (me), a Members Block (users), and a Main Menu block (anyone), but I am not so fond of all of this.

You may be able to do this with PHP. The Contributor Links menu block on Drupal is PHP.

Anisa.

-----------------------------------------------------------
Kindness builds stronger bonds than necessity.

www.animecards.org - 18,000 card scans and counting!
-----------------------------------------------------------

anner’s picture

This is definitely something that should be added into the next version of drupal. I've seem plenty of requests for it (and would like it myself), but currently I don't think there is a way that doesn't involve going into the menu code. In my experience, whether or not an individual/role has access to the item or not does not make it not appear in the menu, so simple access and taxonomy access don't help at all.

Raymondo’s picture

Ah well, it seems like it's not possible. I will have to resort to multiple blocks but this is such an ugly solution.
It seems like such a simple thing, but if it ain't there, it ain't there!

JonathanDStopchick’s picture

There has to be a way
to do it! C'mon folks, someone out there must know how to port it from a previous version or have somethign to add it in!!!

.o.oOo.o.

Me I'm dishonest, and a dishonest man you can always trust to be dishonest. Honestly it's the honest ones you have to watch out for, you never can predict if they're going to do something incredibly stupid. -Jack Sparrow

jeff h’s picture

Hey all... stumbled upon this thread and thought I'd throw in one option for you...

You're right, Drupal 4.7's menu system doesn't allow per-menu-link control of display based on the viewer's role.

However, if you're willing to build the menu yourself, and sprinkle it with PHP, you can achieve the result you're after.

The following is untested, but should work (based on code at http://drupal.org/node/64135):

<ul>
  <li><a href="linkurl">link one, for all to see</a></li>
  <li><?php
global $user;
if (in_array('Approved Role',$user->roles)) {
  print "<a href=\"linkforapprovedroleonly\">for approved role only</a>;
} else {
  print "<a href=BACKSLASH"linkforothers\">for those not of approved role</a>;
}
?>
  <li><a href="anotherlinkurl">for all to see</a></li>
</ul>

Please note: where it says BACKSLASH in the code above, you should replace that word with \ which I tried to do but the codefilter module running on drupal.org must have a bug as it spat out an error :(

ninetwenty’s picture

Add the code between begin and end hack to the appropriate place in menu.inc, this works alongside any of the access control modules to hide nodes on menus that the user's role has no access to.

/**
 * Determine whether the given menu item is accessible to the current user.
 *
 * Use this instead of just checking the "access" property of a menu item
 * to properly handle items with fall-through semantics.
 */
function _menu_item_is_accessible($mid) {
  $menu = menu_get_menu();

  // Follow the path up to find the first "access" attribute.
  $path = isset($menu['items'][$mid]['path']) ? $menu['items'][$mid]['path'] : NULL;
  // ** Begin hack **
  if (substr($path, 0, 5) == 'node/') {
    $nid = substr($path, 5);
    if (is_numeric($nid)) {
      $node = node_load($nid);
      return node_access('view', $node);
    }
  }
  // ** End hack **
  while ($path && (!isset($menu['path index'][$path]) || !isset($menu['items'][$menu['path index'][$path]]['access']))) {
    $path = substr($path, 0, strrpos($path, '/'));
  }
  if (empty($path)) {
    // Items without any access attribute up the chain are denied, unless they
    // were created by the admin. They most likely point to non-Drupal directories
    // or to an external URL and should be allowed.
    return $menu['items'][$mid]['type'] & MENU_CREATED_BY_ADMIN;
  }
  return $menu['items'][$menu['path index'][$path]]['access'];
}
tekoa’s picture

When I first tried this with pacs, none of the normal menu items were visible to annonymous users. After adjusting some pacs permissions, it is now working.

1st-angel’s picture

Is this going to be in HEAD?
Or is this not wanted?

angel

MrTaco’s picture

very nice

works like a charm

thanks a lot :)

skelly’s picture

Thanks for saving me the trouble of finding the right place to hack patch core!

I have to agree that, while I understand node access and menu permissions are separate beasts in Drupal, there really needs to be some way for this functionality to live happily in core - hack or no hack. I need this all the time.

Can verify that it seems to do what I want even when individual, admin-created menu items are created as children of taxonomy_menu parents alongside taxonomy_menu children for nodes restricted by tac_lite! Sweet!

JonathanDStopchick’s picture

http://drupal.org/node/16542
This works well for me

.o.oOo.o.

Me I'm dishonest, and a dishonest man you can always trust to be dishonest. Honestly it's the honest ones you have to watch out for, you never can predict if they're going to do something incredibly stupid. -Jack Sparrow

chrisschaub’s picture

I think another way to do this is to setup your roles. Then add menu items with a "path" that points to an item that can only be accessed by that role. So, you could have a parent menu item called "my special area" that links to a view that can only be accessed by a certain role. Then just add child items to the parent. Then it's cool since the parent is protected and so are the children since they also can be restricted by role. Easy with view links, haven't tried with other content types. Works great with cck nodes since they have built in access control. To restrict certain pages or stories you'd have to used something link simple access module though I haven't tested if it will work the same way with menu items.

I thought of this since I could get cck child menu items to hide based on access control. But the parent "stub" menu item always appeared. But if the parent's path points to some access controlled area than it will be hidden as well. It's a hack but works for me.

dfletcher’s picture

Note that this works for a block containing a menu, not individual items. But it is a solution for hiding menus based on role. See below for a potential future solution that can handle individual items.

It is trivial to achieve this using the user_access() function in the right spot.

Go to your blocks configuration and find the block that is home to your menu (for example LeftNav). In that block configuration, choose "Show if the following PHP code returns TRUE (PHP-mode, experts only)." Put the following PHP code into the box:

return user_access('administer nodes');

Now, only roles with 'administer nodes' permission (under admin > access control) will see this menu.

FWIW I have also created a "Context Menus" module that can control individual items in exactly this same manner on the admin > menus configuration page, but haven't had the time to release it... send me an email if you're interested in it.

Anonymous’s picture

Thanks dfletcher for your post on using user_access. It is exactly what I needed. What other possible values, or where should I look for them are their for user_access()?

Earnie Boyd
http://For-My-Kids.Com
http://Give-Me-An-Offer.com
http://AffiliationMaster.com

dfletcher’s picture

I've elaborated a bit more here:

http://drupal.org/node/64135#comment-176458

Essentially, the argument of user_access() is anything down the left hand side of the access control page. Alternatively, if you're pretty comfortable with PHP code you can make your own permission setting for it. See the linked comment for details.

dvessel’s picture

I wouldn't know how to actually code it but something to this effect? Override the theme function to detect a string from the description field. So, if you type 'administer nodes' into the description the function would see it and act accordingly. I know, it's ugly but just thought I'd throw this out here.

theme_menu_item
theme_menu_item_link

function phptemplate_menu_item($mid, $children = '', $leaf = TRUE) { 

  global $user;
  $user_role = $user->roles; //array

  if (<some find function>($user_role, $mid[]['description']) {
    return '<li class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) .'">'. menu_item_link($mid) . $children ."</li>\n"; 
  } else {
    return false;
  }
} 

FAKE CODE!! DON'T USE

Or even better, couldn't you adapt that hack to this theme override.

joon

intu.cz’s picture

Hello, I needed something similar, and discovered that by using Taxonomy Access Module (in case your nodes can have taxonomy terms assigned to them) works like magic. No menu items show up to unauthorized people... who do not belong to the right role.

Roman

PS: Haven't read what was written above, so I apologise for possible repetitions

cboshuizen’s picture

I am using taxonomy access module and I find that menus DO show up if the user does not have access to them. Correctly the user cannot access the page, but I just cannot manage to get the menus to be suppressed. Any tips?

Chris

discursives’s picture

Best to look in the handbook for block visibility phpsnippets by role. There are several which will handle most situations.

cboshuizen’s picture

That won't help, because I am not trying to suppress the block, just one menu item within a particular menu.

I'll try the new module below and get back to you all.

andreavr’s picture

http://drupal.org/project/menu_per_role

we are just testing it in combination with taxonomy access and it is working so far.

Andrea

brianpeat’s picture

I have a test site running menu_per_role and Taxonomy Access (Drupal 5.1) and it's working.

My only issue is that the Taxonomy terms show up in some places, even though the TAC module is set to NOT show them. Not sure if it's a bug or what. The other problem is all the terms are choosable in anything a normal user is allowed to post (in my case, the forums). It's messy enough I had to turn off any kind of limitations to the forums. I'm going to try another module for that.

jeremynyc’s picture

Excellent. Thanks much. Works like a charm.

eggsurplus’s picture

I wanted to do something similar; show Navigation menu for admin only and show a site menu for anon users only. This way the admin menu wouldn't be cluttered with the site menu. To do that I had to create an addition menu grouping in MySQL:

insert into menu(mid,pid,path,title,description,weight,type)
values((select id+1 from sequences where name = 'menu_mid')
,0,'','Main links','',1,115)

#update sequence table with new menu id
update sequences
set id = 89 #new menu id
where name = 'menu_mid'

#move old menu items from navigation to main. In this case those with a weighting of less than 0
update menu
set pid = 89 #new menu id
where pid = 1 and weight < 0

Then I went to Administrator->Site Building->Blocks and set the Main menu to be on the left sidebar, saved, then clicked on the configure link and set Show block for specific roles: to anonymous users only.

Raymondo’s picture

I've just moved to v5.1 and notice that there's still no menu item level visibility control. Shame it wasn't considered a useful addition to functionality.

inforeto’s picture

"menu per role" module does this in 5.x, see the link above.

Zarniwoop’s picture

correct, the menu-per-role module controls menu item visibility based on role access, but what about menu visibility by user? Is there anything?

Nodeaccess and TAC lite etc control access (throwing up an "access denied" message) but still leave the menu item there for all to see... :(

transformative’s picture

You could try this in combination with the Remove Non-Viewable Menu Items module. I haven't tried this particular scenario though...

piztol’s picture

This module works !! very easy, no need to patch, thank you.

I'm using 5.7

kenorb’s picture

Some solutions for Drupal 6?

kenorb’s picture

Jkingzz’s picture

Use http://drupal.org/project/menu_per_role. Having installed it just go into the the menu item(s) u wish to be hidden to users based on their roles and make the restrictions on the roles, it's shown by checkboxes.

drudeep’s picture

Perfect solution.

mamta sahu’s picture

Hi...I faced same problem i have two types of user 'user' and 'emp' and i wann show some menu items according to defined roles....please comments...