DBUG meeting question follow-up: tabs for anon users

Events happening in the community are now at Drupal community events on www.drupal.org.
bradjones1's picture

I asked a question at last night's DBUG meeting about using local menu task-style tabs for navigation links on a subset of pages in D7. In particular, I'd found a way to get new tabs appearing for logged-in users, but they were nowhere to be found for anonymous visitors:

<?php
function nga_helpers_menu_local_tasks_alter(&$data, $router_item, $root_path) {
 
$path = explode('/',drupal_get_path_alias());
  if(
$path[0] == 'public') {
   
$data['tabs'][0]['output'][] = array(
     
'#theme' => 'menu_local_task',
     
'#link' => array(
 
'title' => t('Example tab'),
  
'href' => 'public/careers',
      ),    );  } }
?>

I did some debugging after the meeting and found that the #link entries in the $tabs variable passed into the page template contained 'access_callback' keys, but trying to replicate them with something like 'access_callback' => TRUE in the above array didn't do anything. It's not documented anywhere I could find.

So I took a different approach and just put this into the theme template.php file, though it obviously needs more work to make it dynamic.

<?php
function nga_preprocess_page(&$variables, $hook) {
   
$path = explode('/',drupal_get_path_alias());
    if(
$path[0] == 'public' && $path[1] == 'careers')
   
$variables['tabs']['#primary'][] = array(
       
'#theme' => 'menu_local_task',
       
'#link' => array(
           
'href' => 'testing',
           
'title' => 'Preprocessed',
        ), ); }
?>

Does anyone have a simpler approach to this? Or is preprocess the best place to put it in the first place? I think hook_menu_local_tasks_alter is neat, but it's limited in utility if it only works to add logged-in tabs.

Comments

It would be better to keep it

coltrane's picture

It would be better to keep it out of preprocess if possible. I missed your question, what are you trying to do? Also, why doesn't a custom menu definition as local tasks work?

I have a set of public-facing

bradjones1's picture

I have a set of public-facing pages for a corporate site in a structure like this: careers, careers/benefits, careers/apply, etc. They drop-down out of the main nav window from the menu system.

What I'd like to do is use tabs for sub-navigation inside that section, so where admin users see view/edit, etc., I'd like Careers, Benefits, Apply. Make sense?

Someone last night suggested a menu block, but I want it inline with the node like the tabs now.

What do you mean by "custom menu definition as local tasks"?

Custom menu items

coltrane's picture

From http://api.drupal.org/api/drupal/modules--system--system.api.php/functio...

You can also make groups of menu items to be rendered (by default) as tabs on a page. To do that, first create one menu item of type MENU_NORMAL_ITEM, with your chosen path, such as 'foo'. Then duplicate that menu item, using a subdirectory path, such as 'foo/tab1', and changing the type to MENU_DEFAULT_LOCAL_TASK to make it the default tab for the group. Then add the additional tab items, with paths such as "foo/tab2" etc., with type MENU_LOCAL_TASK. Example:

so you could perhaps define

$items['careers'] = array(
  'title' => 'Careers',
  'type' => MENU_NORMAL_ITEM,
  // rest of the menu properties
);
$items['careers/careers'] = array(
  'title' => 'Careers',
  'type' => MENU_DEFAULT_LOCAL_TASK,
  // rest of the menu properties
};
$items['careers/benefits'] = array(
  'title' => 'Benefits',
  'type' => MENU_LOCAL_TASK,
  // rest of the menu properties
);

hook_menu() vs. hook_menu_local_tasks_alter()

sreynen's picture

I normally do this kind of thing with hook_menu() and wasn't aware of hook_menu_local_tasks_alter() until last night. The problem with hook_menu() is it only runs when menus are updated, not at page load, so it doesn't work great with more dynamic criteria. hook_menu_local_tasks_alter() solves that problem, running on each individual page. But the problem with hook_menu_local_tasks_alter() is, apparently, it automatically applies an access check for authenticated users. There's no mention of this access check in the documentation, so I wonder if that's a bug.

Having tinkered with this

bradjones1's picture

Having tinkered with this most of the day, I do think this is buggy behaviour on the part of the menu module. Filed: http://drupal.org/node/1140550

Thanks for everyone's help.

Access callback

jyee's picture

You may want to try changing the access callback to: array('access content')

I encountered an issue a while back where 'access callback' => TRUE in hook_menu didn't work(still unsure of the reason). Changing it to look for an actual permission resolved the problem in my case.

I've tried the following, and

bradjones1's picture

I've tried the following, and after clearing the menu cache (and, well, all caches) still nada.

<?php
function nga_helpers_goto($path = '') {
 
drupal_goto($path);
}

/* Use tabs for navigation on public/careers */

function nga_helpers_menu() {
 
$items['public/careers'] = array(
   
'title' => 'Careers',
   
'type' => MENU_NORMAL_ITEM,
   
'access callback' => TRUE,
   
'page callback' => 'nga_helpers_goto',
  );
 
$items['public/careers/apply'] = array(
   
'title' => 'Apply',
   
'type' => MENU_DEFAULT_LOCAL_TASK,
   
'access callback' => TRUE,
   
'page callback' => 'nga_helpers_goto',
  );
 
$items['public/careers/volunteering'] = array(
   
'title' => 'Volunteering',
   
'type' => MENU_LOCAL_TASK,
   
'access callback' => TRUE,
   
'page callback' => 'nga_helpers_goto',
  );
 
  return
$items;
}
?>

I'm wondering, though, if this isn't because the items I'm linking to are in fact nodes already defined to the paths listed there. As I understand it, hook_menu() is used primarily to define paths for content that is then themed by a function callback, not to point to content already assigned a path in the menu system?

I'm beginning to think sreynen's comment here is the root of the issue, given the _alter call works mostly, just not for anon users, and that there's some access issue either not documented or not supported by that method.

It sounds to me like your

apmsooner's picture

It sounds to me like your issue with not just setting up menus as blocks is that you want it to appear within the node like tabs do. If thats the case, why not just create a region in your page.tpl.php file where tabs are currently at and style it just like tabs so it appears as a second row of tabs? That way you can drop your menu block into that region and control access for the various roles pretty easily. Seems like that would make the most sense because you can then assign whatever nodes to that specific menu. Am i missing some needed functionality you're after here? Sounds like it's just a presentation issue to your client so attacking the issue at the theme template might be easier?

That is probably what I will

bradjones1's picture

That is probably what I will end up doing here, in that I can still dynamically create an array to pass to theme('menu_local_task'). I still think there's buggy behaviour in the hook, but that starts to be out of scope here. Thanks for the help.

Brad, i don't know if you

apmsooner's picture

Brad, i don't know if you know panels or not but you can do what you're trying to do with panels using context to set the tabs. Its kind of a similar way you'd create tabs using the views modules and specifing paths like careers, careers/benefits, etc... but with panels you can actually go a little deeper and specify certain node/add/edit forms, specific nodes, etc... to build your tabs.
The context module may do something similar but i'm not as experienced with that one. Otherwise, perhaps you're looking for a way to just code it yourself.

Drupal Colorado

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: