Drupal 6 removed the ability to display menu items the user doesn't have access to. However, in some cases it is desirable to show a menu item even though the user doesn't have access to the menu item. For example, if you use an authentication mechanism that tries to acquire authentication when a 403 would be displayed, you still want to display the menu item so that users get a chance to provide credentials to log in.

Comments

marcoBauli’s picture

+1 for this. Often is useful to show menu items to inform anonyms about members-only sections, features, etc.

sun’s picture

Category:feature» bug

I agree, and this is a bug.

Jaypan’s picture

I don't know that it's a bug, but it's a missing feature that should be available. I have this issue right now.

venkatd’s picture

I needed this feature. Here's a small module I wrote that allows me to accomplish this. It's somewhat of a hack, but Drupal's design takes the blame. I'm using Drupal 6.x so it's only been tested for Drupal 6.

<?php
/**
 * Implementation of hook_form_alter()
 **/
function menu_visibility_form_alter(&$form, &$form_state, $form_id) {
  if (
$form_id == 'menu_edit_item') {
   
$form['menu']['always_show'] = array(
     
'#title' => t('Always show'),
     
'#type' => 'checkbox',
     
'#description' => t('If select, this menu item will be shown even if the user does not have permission. (Access will still be denied.)'),
     
'#default_value' => $form['menu']['options']['#value']['always_show'],
    );
   
array_unshift($form['#submit'], 'menu_visibility_menu_edit_form_submit');
  }
}

function
menu_visibility_menu_edit_form_submit($form, &$form_state) {
 
$menu =& $form_state['values']['menu'];
  if (
$menu['always_show']) {
   
$menu['options']['always_show'] = 1;
   
$menu['options']['alter'] = 1;
  }
  else {
   
$menu['options']['always_show'] = 0;
   
$menu['options']['alter'] = 0;
  }
}

/**
 * Implementation of hook_translated_menu_link_alter().
 */
function menu_visibility_translated_menu_link_alter(&$item, $map) {
  if (
$item['options']['always_show'] == TRUE) {
   
$item['access'] = TRUE;
  }
}
?>
thehandyman’s picture

+1 for the option to turn off this "feature" in D6... we need to let users see that additional content is available. If they can't see the buttons, they don't know it's there. The big problem with this new behavior is that, good or bad, it is unexpected and as such generates a lot of frustration.

freighthouse’s picture

I used #4's solution and I can only get block titles but still not the menu items. I have been disabling any and all other modules that have anything to do with taxonomy access and menu access with no luck.

venkatd’s picture

Hi freighthouse, can you determine whether menu_visibility_translated_menu_link_alter is fired?

freighthouse’s picture

ummm, would you mind guiding me on that?

xurizaemon’s picture

@venkatd: For me, yes menu_visibility_translated_menu_link_alter() is fired on each display of the menu for anonymous user. The menu entry is included, but the text of the menu entry is '', so your posted code *almost* works for me, but doesn't quite.

A couple of alternative workarounds for D6 are -

1. Path Access module which provides a means of restricting access without affecting menu visibility (according to the project page).
2. Creating absolute URLs as menu entries. ie, instead of node/123, set the menu entry to http://example.com/node/123. One customer reported that Drupal automatically "corrected" this (haven't tested/reproduced myself); if so then this may be circumventable by assigning meaningless parameters to the absolute URL (http://example.com/node/123?abc=def).

Algae_94’s picture

#4's module code worked like a charm on my 6.x install. I added the additional check to put a different css class on the links for anon users:

function menu_visibility_translated_menu_link_alter(&$item, $map) {
     if ($item['options']['always_show'] == TRUE) {
         $item['access'] = TRUE;
         if (user_is_anonymous()){
              $item['localized_options']['attributes']['class'] .= 'anonymouscssclass';
         }
     }
}
Damien Tournoud’s picture

Version:7.x-dev» 8.x-dev
Category:bug» feature

This is very much not a bug.

mattyoung’s picture

It may not be a bug. But it is a very needed feature. +1 for this.

mthomas’s picture

valderama’s picture

for the statistics: i am currently building a site, where I would need that feature.

valderama’s picture

to make the suggestion from #4 in D7 i had to modify minor stuff (this solution is based on the stuff by mthomas in #13)

<?php
//largely based on http://drupal.org/node/300607#comment-2805992

/**
* Implementation of hook_form_alter()
**/
function always_visible_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'menu_edit_item') {
   
    $form['always_visible'] = array(
      '#title' => t('Always show this menu item.'),
      '#description' => t('Disables the check if the user has access to this path.'),
      '#type' => 'checkbox',
      '#weight' => '0',
      '#default_value' => isset($form['options']['#value']['always_visible'])?$form['options']['#value']['always_visible']:FALSE,
    );
  array_unshift($form['#submit'], 'always_visible_menu_edit_form_submit');
  }
}

function always_visible_menu_edit_form_submit($form, &$form_state) {  
  $menu =& $form_state['values'];
  if ($menu['always_visible']) {
    $menu['options']['always_visible'] = 1;
    $menu['options']['alter'] = 1;
  }
  else {
    $menu['options']['always_visible'] = 0;
    $menu['options']['alter'] = 0;
  }
}

/**
* Implementation of hook_translated_menu_link_alter().
*/
function always_visible_translated_menu_link_alter(&$item, $map) {
  if ( isset($item['options']['always_visible']) && $item['options']['always_visible'] == TRUE) {
    $item['access'] = TRUE;
    $item['title'] = $item['link_title'];
  }
}

mrfelton’s picture

There is a D6 module that does this here: http://drupal.org/sandbox/mthomas/1119418. D7 patch is in its issue queue.

droplet’s picture

Priority:Normal» Major

+1 for this.

nandotinoco’s picture

Just used #15 on D7 and it worked like a charm. Thanks valderama. I agree this should be addressed. Bug or not a bug, it is unexpected

klonos’s picture

Version:6.x-dev» 8.x-dev
Priority:Normal» Major
nevos’s picture

code from #15 works on D7 cut and paste.
Thanks you.

dawehner’s picture

Version:8.0.x-dev» 9.x-dev
Priority:Major» Normal
Issue summary:View changes

I really think this is a normal feature request ... so 9.x is kinda of a good place to go

fischeme’s picture

Solution in #15 worked for me but 4 instances of "always_visible" should be replaced by your custom module name if you embed the code in a custom module, of course. Also, I modified the form alter function to alter just the menu item edit form, eliminating the need to test the form_id. The function becomes:

function always_visible_form_menu_edit_item_alter(&$form, $form_state) {
  $form['always_visible'] = array(
    '#title' => t('Always show this menu item.'),
    '#description' => t('Disables the check if the user has access to this path.'),
    '#type' => 'checkbox',
    '#weight' => '0',
    '#default_value' => isset($form['options']['#value']['always_visible']) ? $form['options']['#value']['always_visible'] : FALSE,
  );
  array_unshift($form['#submit'], 'always_visible_menu_edit_form_submit');
}