Can't add MENU_LOCAL_TASK to specific node-types
ryan_courtnage - September 12, 2008 - 14:31
| Project: | Drupal |
| Version: | 6.8 |
| Component: | menu system |
| Category: | support request |
| Priority: | minor |
| Assigned: | Unassigned |
| Status: | closed |
Jump to:
Description
This issue was previously discussed in the forums. With Drupal 6's new menu system, there appears to be no way for a module to define a MENU_LOCAL_TASK (a tab) that only applies to certain node types.
For example, to add a new tab for ALL node types, do:
<?php
$items['node/%node/new_tab'] = array(
'title' => 'New Tab',
'page callback' => 'mycallback',
'page arguments' => array(1),
'access callback' => TRUE,
'type' => MENU_LOCAL_TASK
)
?>In D5, we could use hook_menu !$may_cache to conditionally create the tab based on the node type. This is not available in D6.
One possible workaround is to use the 'access callback' key to check for the node type and return false when needed:
<?php
$items['node/%node/new_tab'] = array(
'title' => 'New Tab',
'page callback' => 'mycallback',
'page arguments' => array(1),
'access callback' => check_type(arg(1)),
'type' => MENU_LOCAL_TASK
)
function check_type($node)
{
if($node->type == 'story')
return TRUE;
}
return FALSE;
}
?>This will work for non-admin users. However when you are admin (user 1), the 'access callback' check is skipped. This results in node pages with irrelevant tabs on them.

#1
Turns out the workaround using 'access callback' does work, even for user 1.
#2
The best way remains to define your own loader. Using access callback for this is simply ugly.
#3
Can you please elaborate? Do you mean do something like:
<?php
$items['node/%my_node_type/new_tab'] = array(
'title' => 'New Tab',
'page callback' => 'mycallback',
'page arguments' => array(1),
'access callback' => TRUE,
'type' => MENU_LOCAL_TASK
)
...
function my_node_type_load($arg) {
$node = node_load($arg);
if($node->type == 'my_type')
return $node;
return FALSE;
}
?>
?
Dang, i never considered that before. I'll have to try!
#4
I meant exactly that.
#5
If you have 5 tabs definied, does that mean that the node gets loaded 5 times ? Or is there a workaound ?
$items['node/%my_node_type/new_tab']= array(...
$items['node/%my_node_type/new_tab1']= array(...
$items['node/%my_node_type/new_tab2']= array(...
$items['node/%my_node_type/new_tab3']= array(...
$items['node/%my_node_type/new_tab4']= array(...
...
function my_node_type_load($arg) {
$node = node_load($arg);
if($node->type == 'my_type')
return $node;
return FALSE;
}
#6
Hi, did you solve this problem?
Can you give me the whole code to implement a tab? I can't figure it out.
Cheers
#7
I am having real problems just getting the tabs to appear on all nodes. Does the code above need to be placed in a hook_menu or just as php inside my module? can someone post the full code for a module including a sample page callback as this is possible where my error lies. I am just returning a string from my callback for testing purposes.
Thanks.
#8
As Apfel007 mentioned, could someone post a complete working code for us noobs to learn from? :)
#9
It goes into hook_menu in a custom module named my_module (or whatever you want to call it). Here is some working code:
/**
* Implementation of hook_menu().
*/
function my_module_menu() {
$items['node/%/new_tab'] = array(
'title' => 'Pay Here',
'page callback' => 'mycallback',
'page arguments' => array(1),
'access callback' => 'custom_loader',
'access arguments' => array(1),
'type' => MENU_LOCAL_TASK,
);
return $items;
}
function custom_loader($param) {
$node = node_load($param , $revision = NULL, $reset = NULL);
if($node->type == 'my_node_type')
return TRUE;
return FALSE;
}
/**
* Menu callback; do whatever you want the tab to do here.
*/
function mycallback($param) {
$node = node_load($param , $revision = NULL, $reset = NULL);
// Do cool stuff here
return ;
}
#10
Beautiful! Thank you!
#11
Automatically closed -- issue fixed for 2 weeks with no activity.
#12
Don't forget to clear your menu caches when testing!