2

What would it take to style tabs (of the MENU_LOCAL_TASK variety) differently for tabs that anonymous can't see. I have various admin-only tabs that I'd like to automatically call out as admin-only tabs (so that my admins/mods can keep track of what normal visitors can and can't see).

Maybe something like a call to user_access() within the hook_menu's title_callback attribute and stuffing a css class in the menu title if anon fails? This would mean adding this to every MENU_LOCAL_TASK though. I was hoping for something a little more global/automated.

What about taking it one step further and having a css class on all links that would be hidden if anon were viewing the page?

Drupal 6.


My solution

Riffing on Andy's answer.

/*
 * Add css class to menu items that anonymous users don't have access to.
 */
function [themename]_menu_item_link($link)
{
    global $user;

    // Not necessary to do this for Anon
    if ($user->uid != 0) {
        // Temporarily impersonate Anon
        $original_user = $user;
        $old_state = session_save_session();
        session_save_session(false);
        $user = drupal_anonymous_user();

        // See if Anon has access to this menu item
        $map = explode('/', $link['href']);
        _menu_check_access($link, $map);

        if (! $link['access']) {
            $newStyle = array('attributes' => array('class' => 'non-admin'));
            $link['localized_options'] = array_merge($link['localized_options'],
                                                     $newStyle);
        }

        // Restore user
        $user = $original_user;
        session_save_session($old_state);
    }

    // Resume rendering of this link
    return theme_menu_item_link($link);
}
  • Are you using one user permission for all of these links, eg, user_access('admin links') or are they all over the map. Obviously, node edit/track/publish permissions and so forth would be but just wondering if there was some commonality we could key in on re: your custom tabs. – Jimajamma Aug 10 '12 at 14:54
  • I can't +1 again, but +1 for using _menu_check_access()! – Andy Aug 14 '12 at 7:54
  • Just a quick note on performance: it might be worth checking the link type to avoid the overhead for non-local task links. (I'd expect on most sites that typically the majority of links aren't local tasks). Unless you also want the class added to normal links... – Andy Aug 14 '12 at 8:07
1

menu_local_tasks() is a good place to start looking. This calls theme_menu_item_link() which is the pertinent theme function to look at. It makes sense to do any access checks in the preprocess and you'll also need a custom theme function to handle the variables you set. You mention user_access() in the Q, but it's important to remember that the access callback could by any function. For that reason it's necessary to impersonate the anonymous user (note the link isn't specifically for anon users, but the fundamentals are the same). You can get the menu item type, access callback, and access arguments from $link. The bit of code to do the actual checks would look something like:

if ($menu_item_type & MENU_LOCAL_TASK) {
  global $user;
  $original_user = $user;
  $old_state = session_save_session();
  session_save_session(FALSE);
  $user = drupal_anonymous_user();

  if (!call_user_func_array($access_callback, $access_arguments)) {
    // Anon's don't have access to this local task
  }

  $user = $original_user;
  session_save_session($old_state);
}

A note regarding performance: none of the calls access the database, except possibly the access callback (which could do anything). user_access() caches a role's permissions, so that would only access the DB the first time. Other access callback's might not do this. It wouldn't be particularly difficult to cache the results of the access callback yourself (keyed by access callback and serialised arguments).

  • Thanks Andy, great answer! I worked out some details and posted my solution above. – ack Aug 14 '12 at 5:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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