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.

  1. Use an access control module to restrict access to a node. I used tac_lite to demo.
  2. Add a node and a menu link to it on the main menu. Tag it with the tag configured in tac_lite that denies anonymous users viewing the node.
  3. See the link to the node in the main menu.
  4. Log out. Now you can't see the menu link.

This issue is about letting the menu link be visible despite access to the node being restricted.

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.


/**
 * 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;
  }
}
codevoice’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.

jmcerda’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?

jmcerda’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
nevosa’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');
}
catch’s picture

RunePhilosof’s picture

Status: Closed (duplicate) » Active

Reopening this since I can't see how #2463753 would fix this issue.
#2463753 is about being able to hide menu items from UID1 and users with role 'Link to any page'.
This issue is about showing menu items to users who lack the appropriate permission.

catch’s picture

Status: Active » Closed (duplicate)
cilefen’s picture

Issue summary: View changes
Status: Closed (duplicate) » Active

In Drupal 8 as in Drupal 7:

  1. Use an access control module to restrict access to a node. I used tac_lite to demo.
  2. Add a node and a menu link to it on the main menu. Tag it with the tag you configured in tac_lite that denies anonymous users viewing the node.
  3. See the link to the node in the main menu.
  4. Log out. Now you can't see the menu link.

#460408: Cannot administer menu item/link if it points to an unpublished node ensures that roles with appropriate permissions can see all links, but, that isn't the subject of this issue. This is about letting roles that definitely do not have access to the content, see a link to the content on a menu.

jmuzz’s picture

+1 I am dealing with the same issue using the module content_access in Drupal 8.

Thanks to @DuaelFr I was able to accomplish this using hooks in a custom module.

https://www.drupal.org/project/always_visible/issues/2535162

dkre’s picture

This isn't a duplicate of the above mentioned issues.

Here's a simple use case which will reproduce the problem.

I have a site which has an events calendar. The events are primarily created public submission which requires users to create an account to allow users to edit, amend and maintain their event listings.

To encourage usage and ease of use I would like to have a menu link 'List your event' which links to /node/add/event.

I use a 403 redirect to login because users who already have an account will expect to be asked to login if they aren't and new users will be directed immediately to where they need to be (login or sign-up) and this again is an expected behaviour.

This also centralises our messaging to encourage sign-up to the login page.

-

To get around this on our previous Drupal site we created hard coded links within menu template files. This is a pretty ugly solution.

You could add authenticated/unauthenticated link sets but this is bugged: #2267603: "Login" link shows up for logged-in users as well and it's also a little difficult to maintain because the you will end up with two links of the same name in the same menu which I discovered while find the above mentioned bug.

bkosborne’s picture

Version: 9.x-dev » 8.7.x-dev

Drupal 8 point releases can introduce new features, so no need to push such a feature to D9.

This would also be useful to sites I managed.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

malcolm_p’s picture

I also had this need and solved it by using a custom menu link manipulator when rendering my menu. I did this by adding a field to the menu_link_content entity and altering the form with a checkbox to ignore access on that specific link.

Unfortunately core doesn't expose an alter / event for this so it's kind of a custom process. I'm linking this to #2854013 as a result because I think that would help this issue a lot.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

michal.k’s picture

Hi Drupal Team,

It's easy. Just use `Menu Item Role Access` contributed module and check `Anonymous user` and `Authenticated user` roles for a particular menu item to make it visible for ALL! IMPORTANT: to make it working enable `Overwrite internal link target access check` in module config page (admin/config/menu-item-role-access).

Hope that this helps a lot of people!
Good luck!
Michal.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.