Both Drupal core as well as various modules add tabs to pages that are not needed for general users, or not needed at all. You may wish to link to the page in a different way, as some users don't understand that they can click on the tab above a node.

Method for Drupal 4.7.x and Drupal 5

In versions of Drupal prior to 6, there was not a way to alter the hook_menu() generated tabs from code, so the function illustrated on this page will find and strip out a tab based on its name. As of Drupal 6, there is now the hook_menu_alter() function, which allows you to alter various properties of menu items that are set by core or other modules. If you are using Drupal 6, you should consider using hook_menu_alter instead, which is more exact, and is simpler/more efficient. One thing that hook_menu_alter cannot do that this page's method can is remove the "View" tab (if you have reason to remove the View tab, you can do so with this technique, and use hook_menu_alter for the rest of your tab removals).

Step 1 of 2

Locate your theme's template.php file. If one doesn't exist, create an empty one. This is where you can place customization PHP code.

Step 2 of 2

Custom functions placed in the themes template.php file should begin with the theme name. In the code snippet below replace "yourthemename" with the actual name of your theme, such as "garland".

You may already have a '_phptemplate_variables' function defined depending on what theme you are using, if so do not include the function again from the snippet below.

function _phptemplate_variables($hook, $vars = array()) {

  if ($hook == 'page') {
    yourthemename_removetab('address book', $vars);
    // add additional lines here to remove other tabs.
  }

  return $vars;
}

function yourthemename_removetab($label, &$vars) {
  $tabs = explode("\n", $vars['tabs']);
  $vars['tabs'] = '';

  foreach ($tabs as $tab) {
    if (strpos($tab, '>' . $label . '<') === FALSE) {
      $vars['tabs'] .= $tab . "\n";
    }
  }
}

The tab removal work is done in the yourthemename_removetab() function, pass in a plain text tab label, along with the PHPTemplate variables, and the function will remove the tab.

In the above example snippet the 'address book' tab added by the eCommerce package is removed from the user's profile page.

Notes

  • Call yourthemename_removetab('tab name', $vars); for each tab you wish to remove.
  • No other modules need to be installed to use this.
  • If you need more exact control of which page on the site to affect (since different tabs might share the same name), you can wrap the removetab function with conditions that check the URL path arguments.

Method for Drupal 6

As mentioned in the introduction, generally you should consider using Drupal 6's hook_menu_alter to remove tabs instead. However if you need to use this page's tab removal method, the below code is adapted for use in Drupal 6. The notes and info in the above steps still apply in the same way.

First either add the first code snippet as shown, or else merge it with your current preprocess_page() function in template.php (you cannot have two of the same function, so look for preprocess_page). In both code snippets, change all instances of "yourthemename" to the name of your current theme, and do not include the opening and closing PHP tags.

function yourthemename_preprocess_page(&$vars) {
  // Remove undesired local task tabs.
  // This first example removes the Users tab from the Search page.
  yourthemename_removetab('Users', $vars);
}

Then add this function "outside" of the yourthemename_preprocess_page() function:

// Remove undesired local task tabs.
// Related to yourthemename_removetab() in yourthemename_preprocess_page().
function yourthemename_removetab($label, &$vars) {
  $tabs = explode("\n", $vars['tabs']);
  $vars['tabs'] = '';

  foreach ($tabs as $tab) {
    if (strpos($tab, '>' . $label . '<') === FALSE) {
      $vars['tabs'] .= $tab . "\n";
    }
  }
}

After saving template.php, you may need to rebuild the theme registry before your changes will take effect. This can be done by clearing the cache at Administer > Site configuration > Performance, or through helper modules you likely have such as Admin Menu (top left icon) or Devel (in the Devel block).

Comments

alex.k@drupal.org’s picture

This method works for me and is cleaner (IMO) and more performant than the regexp method:
Tabs are the default way of rendering menu items of type MENU_LOCAL_TASK or MENU_DEFAULT_LOCAL_TASK. So, there is a theming function theme_menu_local_task() in menu.inc that renders them. If you override it in your theme, you can skip certain tabs by simply returning the empty string as their rendered html:
This function would go into template.php in your theme.

function phptemplate_menu_local_task($mid, $active, $primary) {
  //Check which tab is being rendered
  $item = menu_get_item($mid);
  //Remove core search tab
  if ($item['path'] == 'search/node') {
    return '';
  }
  //The rest is copied from theme_menu_local_task()
  if ($active) {
    return '<li class="active">'. menu_item_link($mid) ."</li>\n";
  }
  else {
    return '<li>'. menu_item_link($mid) ."</li>\n";
  }
}

This example removes the core search tab.

stevekerouac’s picture

For example,

if ($item['path'] == 'user') {
    return '';
  }

does not remove the Log In tab.

alex.k@drupal.org’s picture

The path to the login tab is 'user/login' for me (4.7). If you use that it should work. It's the menu item's path, not the path of the request that should be checked.

stevekerouac’s picture

That did it in 5.7 too.

eXce’s picture

Customized it to avoid the Tabs on search-subsites (if you search for "dog" the tab path is "/search/node/dog" and it doesn't work.
I avoided regexp and used str_replace due perfomance reasons.

function phptemplate_menu_local_task($mid, $active, $primary) {
  //Array with Tabs to be removed
  $disabled_tabs = array('search/user' , 'search/node');


  //Check which tab is being rendered
  $item = menu_get_item($mid);
    
  foreach ($disabled_tabs as $tab) {
  	if (substr($item['path'],0,strlen($tab))==$tab) {
  		return '';
  	}
  }
  
  //The rest is copied from theme_menu_local_task()
  if ($active) {
    return '<li class="active">'. menu_item_link($mid) ."</li>\n";
  }
  else {
    return '<li>'. menu_item_link($mid) ."</li>\n";
  }
}
urix’s picture

My task was to combine profilesearch module with default search module.
Here is the code. I keep tab title, but redirect user to another url (profilesearch/search_string).
Drupal 5.10.

function phptemplate_menu_local_task($mid, $active, $primary) {
  //Check which tab is being rendered
  $item = menu_get_item($mid);
  //Remove core search tab
  if (stristr ($item['path'], 'search/user')) {
    $search_string=substr($item['path'], strpos($item['path'],'search/user/')+12 );
    return '<li><a href="/profilesearch/'.$search_string.'">'.$item['title']."</a></li>\n";
  }
  //The rest is copied from theme_menu_local_task()
  if ($active) {
    return '<li class="active">'. menu_item_link($mid) ."</li>\n";
  }
  else {
    return '<li>'. menu_item_link($mid) ."</li>\n";
  }
}
madsph’s picture

I had a similar problem with drupal 6, and I couldn't get your fix to work.

What I did in stead was to add a new submit function to the search forms which makes a redirect to my custom search module (called 'userfinder') - heavily inspired by how the search module redirects to search/node.

This way the results of my own search module is presented first to the user. At first I wanted to remove the 'Content' and 'User' search tabs as well, and followed vijaythummar suggestion which worked perfectly. I ended up deciding to keep them as 'back-up' facilities though.

So in my userfinder.module I have:

 /**
  * Implementation of hook_form_alter().
  */
   function userfinder_form_alter(&$form, &$form_state, $form_id) {
     //This code gets called for every form Drupal build; so be sure to bail out quick
     // if the desired form is not present
     if ($form_id == 'search_block_form' || $form_id == 'search_form') {
       //Redirect to our own usersearch
       $form['#submit'][] = 'userfinder_search_submit';
     }
   }

   function userfinder_search_submit($form, &$form_state) {
     $form_id = $form['form_id']['#value'];
     $args = trim($form_state['values'][$form_id]);
     if ($args && $args != '') {
       $form_state['redirect'] = 'search/userfinder/'. $args;
     }
   }
Anonymous’s picture

Remove tabs in Drupal 7, I did this in template.php:

function yourthemename_preprocess_page(&$vars, $hook) {
  // Removes a tab called 'Reviews, change with your own tab title
  yourthemename_removetab('Reviews', $vars);
}

// Remove undesired local task tabs.
// Related to yourthemename_removetab() in yourthemename_preprocess_page().
function yourthemename_removetab($label, &$vars) {

  // Remove from primary tabs
  $i = 0;
  if (is_array($vars['tabs']['#primary'])) {
    foreach ($vars['tabs']['#primary'] as $primary_tab) {
      if ($primary_tab['#link']['title'] == $label) {
        unset($vars['tabs']['#primary'][$i]);
      }
      ++$i;
    }
  }

  // Remove from secundary tabs
  $i = 0;
  if (is_array($vars['tabs']['#secundary'])) {
    foreach ($vars['tabs']['#secundary'] as $secundary_tab) {
      if ($secundary_tab['#link']['title'] == $label) {
        unset($vars['tabs']['#secundary'][$i]);
      }
      ++$i;
    }
  }
}
pschmitz’s picture

thanks! this solution works fine for D7

RobW’s picture

There's another easy to use code snippet for D7 at http://drupal.org/node/1007226#comment-4472056.

wOOge’s picture

Small Typo — here is the fixed version for Drupal 7:

<?php
function yourthemename_preprocess_page(&$vars, $hook) {
  // Removes a tab called 'Reviews, change with your own tab title
  yourthemename_removetab('Reviews', $vars);
}

// Remove undesired local task tabs.
// Related to yourthemename_removetab() in yourthemename_preprocess_page().
function yourthemename_removetab($label, &$vars) {

  // Remove from primary tabs
  $i = 0;
  if (is_array($vars['tabs']['#primary'])) {
    foreach ($vars['tabs']['#primary'] as $primary_tab) {
      if ($primary_tab['#link']['title'] == $label) {
        unset($vars['tabs']['#primary'][$i]);
      }
      ++$i;
    }
  }

  // Remove from secondary tabs
  $i = 0;
  if (is_array($vars['tabs']['#secondary'])) {
    foreach ($vars['tabs']['#secondary'] as $secondary_tab) {
      if ($secondary_tab['#link']['title'] == $label) {
        unset($vars['tabs']['#secondary'][$i]);
      }
      ++$i;
    }
  }
}
?>

--
wOOge | adrianjean.ca

angel.angelio’s picture

Similar to this code but for several tabs in the Login FORM(D7).

if (is_array($vars['tabs']['#primary'])) {
    foreach ($vars['tabs']['#primary'] as $index => $tab) {
      if ($tab['#link']['title'] == 'Log in' || $tab['#link']['title'] == 'Request new password' ||  $tab['#link']['title'] == 'Create new account') {
        unset($vars['tabs']['#primary'][$index]);
      }
    }
  }

Add it to the hook_precoces_page function in your theme or module

Alex01’s picture

hey thanks this is just what i needed... only prob is on when using overlay i get this error "Notice: Undefined index: #primary in seven_removetab()" and the tab isn't removed... how would i fix that problem.

gbhatnag’s picture

For some reason, if I try and remove the 'Content' tab on the Search page, the styling of the tabs gets messed up (there are no more tabs, just a real plain looking bulleted list!). I haven't investigated the code much yet, but looks like there is something special about the first tab in a series of tabs (other tabs that aren't first seem to get cut just fine).

pianory’s picture

You are correct, this method does not work any time it is the first tab, and thus this handbook method is poorly coded. What happens is the tabs get broken up by newlines, so as a basic example, tabs are the string: <ul><li>first item</li><li>second item</li></ul>

Which then gets divided into an array
1. <ul><li>first item</li>
2. <li>second item</li>
3. </ul>

So if you delete the first tab item, it also deletes the first <ul>, so the list breaks! Hope this helps others, I'm sure there are good methods somewhere in the comments, I just haven't looked through all of them :)

xurizaemon’s picture

Please note that the simple method for removing the User Search functionality is to disable the permission "access user profiles" for the role which you don't want seeing it. You may only be seeing this because you're logged in as an administrator.

greg@beargroup.com’s picture

I needed to remove tabs in search & that IMCE file management tab in user accounts. Used strpos in php5, sounds like its fastest.
This would go in template.php still.

/*
 * Remove search users tab & the file upload tab for all users.
 */
function phptemplate_menu_local_task($link, $active = FALSE) {
  if ( strpos($link,'search') ) {
    return '';
  }	else if ( strpos($link,'imce') ) {
    return '';
  } else {
  	return '<li '. ($active ? 'class="active" ' : '') .'>'. $link ."</li>\n";
  }
}
harrisben’s picture

Thanks for that!

I was trying to remove the 'Request new password' tab on the user login form and for some reason it wouldn't disappear until I realise that I needed to match the case of the text (capital R). Tada! It works!

vijaythummar’s picture

Here what I have used to remove unnecessary tabs in drupal6.

function phptemplate_preprocess(&$variables, $hook) {
  if($hook == 'page') {
    yourthemename_removetab('File browser', $variables);
  }
  return $variables;
}

function yourthemename_removetab($label, &$vars) {
  $tabs = explode("\n", $vars['tabs']);
  $vars['tabs'] = '';

  foreach($tabs as $tab) {
    if(strpos($tab, '>' . $label . '<') === FALSE) {
      $vars['tabs'] .= $tab . "\n";
    }
  }
}

Regards,
vijay thummar

Thanks,
Vijay Thummar

wxman’s picture

Thank you! I've been looking everywhere for a way to do this.

feconroses’s picture

That actually works! Was looking for ages for a solution like that. Thanks :)

Could you post some code to:

- Edit existing tabs.
- Only delete/edit tabs from certain pages and not from all pages.

I would be really grateful! Thanks in advance!

pbattino’s picture

if you want this to hide tabs only in certain pages you might want to check the URL via the arg() function. For example, to hide some tabs only in the user profile pages:

replace

if($hook == 'page')

with

if($hook == 'page' && arg(0)=='user')
agileadam’s picture

I am not sure if this is very efficient, or foolproof, but it's working for me so far:

/**
 * If the user isn't an admin, or the original administrative user,
 * remove the "edit" tab for the "note" nodes in the my_garland theme.
 */
function phptemplate_preprocess(&$variables, $hook) {
    global $user;
    if($hook == 'page' && !in_array('admin',array_values($user->roles)) && $user->uid != 1){
        $nid = str_replace('page-node-','',$variables['template_files'][1]);
        $node = node_load($nid);
        if($node->type == 'note'){
            my_garland_removetab('Edit', $variables);
        }
    }
    return $variables;
}
Ariesto’s picture

I presume we have to change 'page' to a different content type if it applies. I changed youthemename to my theme name. With those changes (and removing the php tags) I could not get the "View" tab to go away..

dnewkerk’s picture

No it has nothing to do with the Page content type. Page here refers to page.tpl.php
You can read more about it here http://drupal.org/node/223430

shriya_atreya’s picture

could not remove "Log in" tab in Drupal 6 using any method specified here

Ariesto’s picture

This forum post helped me solve my tabs problem. I think that the example above works as well, I just didn't realize that I had 2 preprocess functions!

http://drupal.org/node/379792

elallaix’s picture

I would like to remove backlinks tab but all I tried doesn't function.
Can you help me?
Is it correct "backlinks" name to remove backlinks tab?

Ariesto’s picture

Check your view. I believe it has an option to turn off the backlinks tab.

connellc’s picture

Views in D7 sure does remove that tab, and with no extra coding.

pbattino’s picture

if you want this to hide tabs only in certain pages you might want to check the URL via the arg() function. For example, to hide some tabs only in the user profile pages:

replace

if($hook == 'page')

with

if($hook == 'page' && arg(0)=='user')
sridharraov’s picture

I have different types of users. So i have different categories in profile. Now based on the user type I need to display certain tabs. Is there a easy way to do it or that i need to write a query to extract value from profile_values table and add the appropriate conditions in the proprocess funtion...

owntheweb’s picture

Based on this, and another comment, here's what's working for me to remove ALL tabs, only on user pages, placed in my template.php file:

<?php
function phptemplate_preprocess(&$variables, $hook) {
  if($hook == 'page' && arg(0)=='user') {
    $variables['tabs'] = "";
  }
  return $variables;
}
?>

I needed this because I created a custom menu for different types of users, and created additional pages that start with /user/ in the url that I wanted any (if any) tabs to match. The menu I created is serving as the tabs in my particular case and has removed any confusion.

Worlds to explore. Worlds to create.
Blog: http://www.christopherstevens.cc/blog
Twitter: http://www.twitter.com/owntheweb

pwhite’s picture

This works for removing tabs on the registration page:

<?php
function phptemplate_preprocess(&$variables) {
  if(arg(1)=='register') {
    $variables['tabs'] = "";
  }
  return $variables;
}
?>
agileadam’s picture

Sorry to post again...
I am not sure if this is very efficient, or foolproof, but it's working for me so far:

/**
 * If the user isn't an admin, or the original administrative user,
 * remove the "Edit" tab for the "note" nodes in the my_garland theme.
 */
function phptemplate_preprocess(&$variables, $hook) {
    global $user;
    if($hook == 'page' && !in_array('admin',array_values($user->roles)) && $user->uid != 1){
        $nid = str_replace('page-node-','',$variables['template_files'][1]);
        $node = node_load($nid);
        if($node->type == 'note'){
            my_garland_removetab('Edit', $variables);
        }
    }
    return $variables;
}
Netbuddy’s picture

That works fine, and so does the method for Drupal 6 using menu_alter. The problem im having is I cant disable the functionality, only the tab.

For example. I have Node Gallery installed, I created an "Upload Images" tab, but of course it appears on all standard pages using MENU_LOCAL_TASK, not just the gallery pages. I can remove it easily enough using the above method for node type blog, page, story etc...but the user can still type in the direct URL and get the functionality - http://www.mydomain.com/node/22/upload...is a book node, without blocking actual functionality a user can upload images into book nodes, rather than the gallery itself!!! eeek.

I either need a way to make sure this tab only works with certain modules - in this case the node gallery module, or i need to block direct url access to the upload page on every other part of the site apart from the gallery...

mudd’s picture

It would be nice if the "user module" permissions group had an 'edit own account' checkbox, and have any module that wants to put a tab under My Account be required to put their own checkboxes here.

To be practical (since that suggestion isn't trivial), and since my site just disallows users to change email address or password, perhaps give us a way to hide certain widgets ("Account information" in my case).

ressa’s picture

I used this to remove the 'Edit' tab for the role 'customer' and disable access to the 'Edit' page altogether with the Path Access module.

I also have two roles, 'partner' and 'customer', with different Content Profiles, so I removed the 'partner' Content Profile tab when admin or editor are viewing a 'customer' role user, and vice versa.

Under Path access for the 'customer' role I added:

Access every page except the listed pages:
user
user/*/edit

To remove the 'Edit' tab for the 'customer' role only, and hide the "wrong" Content Profile from admin and editor:

// Remove 'Edit' tab from the 'customer' role, 
function phptemplate_preprocess(&$variables, $hook) {
  global $user;
  $user_obj = user_load(arg(1));

  if($hook == 'page' && (in_array('customer', $user->roles)) && $user->uid != 1) {
    THEMENAME_removetab('Edit', $variables);
  }
  // User profile role viewed is 'customer', hide Content Profile tab('Partner') from admin and editor
  elseif($hook == 'page' && ($user_obj->roles[4])) {
    THEMENAME_removetab('Partner', $variables);
  }
  // User profile role viewed is 'partner', hide Content Profile tab('Customer unit') from admin and editor
  elseif($hook == 'page' && ($user_obj->roles[6])) {
    THEMENAME_removetab('Customer unit', $variables);
  }
  return $variables;
}

function THEMENAME_removetab($label, &$vars) {
  $tabs = explode("\n", $vars['tabs']);
  $vars['tabs'] = '';

  foreach($tabs as $tab) {
    if(strpos($tab, '>' . $label . '<') === FALSE) {
      $vars['tabs'] .= $tab . "\n";
    }
  }
}
kinshuksunil’s picture

if you wanna remove each an devery tab from everywhere in the website, for every user (which, i needed for a weird reason) do this:

function yourthemename_preprocess_page(&$vars) {
  // Remove all local task tabs, from everywhere on the site, for all users.
 $vars['tabs'] = "";
}
lexi44’s picture

Does this also work when you want to remove the reply link from comments?

UNarmed’s picture

Dose anyone know how i would go about removing tabs from certain modules? Basicaly i am trying to remove tabs in the admin section that i feel might confuse the end user.

UNarmed’s picture

Ah the post by vijaythummar got me the desired result =] muchoz thanks!

antlib’s picture

I'm getting a rogue, unwanted Attendees tab on my Ubercart product pages.

Anyone know of a clean way of removing this?

Thanks!
Stan

vijaythummar’s picture

You can use HOOK_MENU_ALTER to change the access of menu.

Thanks,
Vijay Thummar
CIGNEX Technologies Pvt Ltd

Thanks,
Vijay Thummar

nickske88’s picture

You have to create a new module but wat has to be the content in it?

And where does the code of the hook menu alter has to come in wich directory i
have to create these files?

I'm a little bit stuck with the tabs.

I can program with PHP but i just don't know where to place the costum module and other code.

Regards Nick

fehin’s picture

I have the code below to remove tab from user not in certain roles but it's not working. Is there something I'm missing?

function phptemplate_menu_local_task($link, $active = FALSE) {
if ( arg(0) == 'user' ) {
	$nid = arg(1); //node id
	$user_id = user_load(array('uid'=>$nid));
      if ( $user_id->roles[7] == buyer or $user_id->roles[9] == dealer or $user_id->uid == 1 ) { 
        return '<li '. ($active ? 'class="active" ' : '') .'>'. $link ."</li>\n";
  
      } else if ( strpos($link,'Shop') ) {
         return ''; 
      }else if ( strpos($link,'Biz') ) {
         return ''; 
         }

  }
}
nickske88’s picture

I had the same problem here,
just use the tab tamer module that you can download here on the site.

If the modules doesn't work for you,

then you have to go to the module and edit this rule in the tabtamer.module file:

Search for this rule in the module and delete it!:

if (is_array($val) && $val['type'] == MENU_DEFAULT_LOCAL_TASK) {

AND REPLACE IT BY THIS RULE:

if (is_array($val) && ($val['type'] == MENU_DEFAULT_LOCAL_TASK || empty($val['type']))) {

It can be you need to empty your cache but probably not.

Regards

sepp68’s picture

Hello nickse88

thank you very much for sharing ! I had to empty caches after patching the module !

Sepp

HJulien’s picture

I am not a php programmer and I've added this code below to remove the tabs but it's not working. I copied it to the end of the existing code. I've also tried it without both the at the beginning and the at the end. Can anyone tell me what I'm doing wrong please?

function phptemplate_preprocess(&$variables, $hook) {
  if($hook == 'page' && arg(0)=='user') {
    $variables['tabs'] = "";
  }
  return $variables;
}

Why needing to do this at all to control the menu local tasks' tabs is beyond me. They are not accessible with Tab Tamer, Local Task Blocks or anything else I've found so far. I'd love to be able to keep some of the tabs but I can't do anything with them. I'm just so frustrated with them that now I just want them gone.

Thank you for your help. It is appreciated.

Hélène

wwedding’s picture

It is also possible to do this via hook_menu_local_tasks_alter(). Actually, that would be my recommendation over a preprocess_page call. This hook specifically handles the kind of menu modifications we're trying to accomplish on this page.

geerlingguy’s picture

...and, an example; in this case, I'm removing the 'View' tab from 'note' type nodes:

/**
 * Implements hook_menu_local_tasks_alter().
 */
function fn_notes_menu_local_tasks_alter(&$data, $router_item, $root_path) {
  // For note nodes, remove the 'View' tab when viewing the node.
  foreach ($router_item['page_arguments'] as $key => $argument) {
    if (is_object($argument) && $router_item['page_arguments'][$key]->type == 'note') {
      foreach ($data['tabs'][0]['output'] as $key => $value) {
        if ($value['#link']['path'] == 'node/%/view') {
          unset($data['tabs'][0]['output'][$key]);
        }
      }
    }
  }
}

__________________
Personal site: www.jeffgeerling.com

agileadam’s picture

Thank you! This worked beautifully.
Here's my adaptation, which has an additional conditional to fix an error if there is no "type" property on a page argument.

/**
 * Implements hook_menu_local_tasks_alter().
 */
function mymodule_menu_local_tasks_alter(&$data, $router_item, $root_path) {
  // For EOFA nodes, remove the 'Manage registrations' tab
  // because we want registrations managed through Program Display nodes.
  // Because both content types have links back to a program (product with
  // a registration entity), they both have tabs to manage the associated
  // registrations (commerce_registration module is responsible for this)
  foreach ($router_item['page_arguments'] as $key => $argument) {
    if (is_object($argument) && isset($router_item['page_arguments'][$key]->type) && $router_item['page_arguments'][$key]->type == 'eofa') {
      foreach ($data['tabs'][0]['output'] as $key => $value) {
        if ($value['#link']['page_callback'] == 'commerce_registration_registration_page') {
          unset($data['tabs'][0]['output'][$key]);
        }
      }
    }
  }
}

and here's a simpler example (changing user "Edit" tab to "Edit profile")

/**
 * Implements hook_menu_local_tasks_alter().
 */
function mymodule_menu_local_tasks_alter(&$data, $router_item, $root_path) {
  if (arg(0) == 'user') {
    foreach ($data['tabs'][0]['output'] as $key => $value) {
      if ($value['#link']['path'] == 'user/%/edit') {
        $data['tabs'][0]['output'][$key]['#link']['title'] = t('Edit profile');
        break;
      }
    }
  }
}
ben.swinburne’s picture

I modified the above to allow either removal or rename of multiple tabs. Just modify the $nodes array in the function. First dimension is content type name, second is key=path, value=renamed value. Leaving value blank removes the tab.

function YOURTHEME_menu_local_tasks_alter(&$data, $router_item, $root_path) {
	$nodes = array(
		'page'	=>	array(
			'node/%/view'	=>	'Renamed View'
		)
	);

	foreach ($router_item['page_arguments'] as $key => $argument) {
		if (is_object($argument) && array_key_exists( $router_item['page_arguments'][$key]->type, $nodes )) {
			foreach( $nodes[$router_item['page_arguments'][$key]->type] as $path => $new_title ) {
				foreach ($data['tabs'][0]['output'] as $key => $value) {
					if ($value['#link']['path'] == $path) {
						if( !$new_title ) {
							unset($data['tabs'][0]['output'][$key]);
						} else {
							$data['tabs'][0]['output'][$key]['#link']['title'] = $new_title;
						}
					}
				}
			}
		}
	}
}
mattcasey’s picture

With the Fusion theme, HTML tags are added around tabs in pre-processing if $tabs is anything but empty.

My fix was to check that a tab exists:

function bali_removetab($label, &$vars) {
  $tabs = explode("\n", $vars['tabs']);
  $vars['tabs'] = '';
  if ($tabs)
  {
	  foreach ($tabs as $tab) {
		if (strpos($tab, '>' . $label . '<') === FALSE) {
		  if ($tab) $vars['tabs'] .= $tab . "\n";
		}
	  }
  }
}
kirikintha’s picture

$vars['tabs'] = preg_replace('/<li.*Personal Information<\/a><\/li>/', '', $vars['tabs']);

And this let's me get rid of what I want, without having to worry about the mark up so much. Works like a charm!

PS - you can make a little function for multiples, or make a longer regex statement. Tabs are some of the hardest darn things to get rid of!

Nothing unreal exists.

CHI.seo2design.com’s picture

http://drupal.org/project/tabtamer this best way for your wanted.
composition hidden and permission necessary given with the tabs-hidden-action.

ibakayoko’s picture

Thanks to the developer of this module.

You saved me

mcarrera’s picture

My task was to remove Invoice and other tabs for the logistic user. He takes care of shipping, and doesn't need to know anything else.

I just had an if statement as follows:

 global $user;
  if(strtolower($user->name) == "logistic"){
    mytheme_removetab('Invoice', $vars);
    mytheme_removetab('Edit', $vars);
    mytheme_removetab('Payments', $vars);
    mytheme_removetab('Log', $vars);
  }

Notice if you use the locale module, the labels (ie Invoice, Edit, and so on) have to match the translations in the user's language

hedley’s picture

To alter a local task in Drupal 7 in a module you have to first invoke hook_theme_registry_alter and implement your own version of theme_local_tasks.

Here's an example I used with the User Relationships module to alter the 'Relationships' tab title to 'Connections'

function MYMODULE_custom_theme_registry_alter(&$theme_registry) {
  if (!empty($theme_registry['form_element'])) {
    // Menu local tasks
    $theme_registry['menu_local_tasks']['function'] = MYMODULE_local_tasks';
  }
}
function MYMODULE_local_tasks(&$variables) {
  $output = '';

  if (!empty($variables['primary'])) {

    // Loop through local tasks and alter
    foreach($variables['primary'] as $key => $link) {
      if($link['#link']['path'] == 'user/%/relationships') {
        $link['#link']['title'] = 'Connections';
      }
      $variables['primary'][$key] = $link;
    }

    $variables['primary']['#prefix'] = '<h2 class="element-invisible">' . t('Primary tabs') . '</h2>';
    $variables['primary']['#prefix'] .= '<ul class="tabs primary">';
    $variables['primary']['#suffix'] = '</ul>';
    $output .= drupal_render($variables['primary']);
  }
  if (!empty($variables['secondary'])) {
    $variables['secondary']['#prefix'] = '<h2 class="element-invisible">' . t('Secondary tabs') . '</h2>';
    $variables['secondary']['#prefix'] .= '<ul class="tabs secondary">';
    $variables['secondary']['#suffix'] = '</ul>';
    $output .= drupal_render($variables['secondary']);
  }

  return $output;

}
wizonesolutions’s picture

Simply naming the function properly will get it picked up by the theme registry on cache clear. The naming format is THEMENAME_menu_local_tasks. If you want to name it something else, then that's when you would use the relevant snippet for that above.

Support my open-source work: Patreon | Ko-Fi | FillPDF Service

pico34’s picture

Note that with locale module :

yourthemename_removetab('Users', $vars);

is :

yourthemename_removetab(t('Users'), $vars);
leymannx’s picture

function MYMODULE_menu_local_tasks_alter(&$data) {
  foreach ($data['tabs'][0]['output'] as $key => $value) {
    if ($value['#link']['path'] == "node/%/view") {
      unset($data['tabs'][0]['output'][$key]);
    }
  }
}
ahsanra’s picture

Superb

atul4drupal’s picture

In order to remove a local task you can use

hook_local_tasks_alter(&$local_tasks);

defined in menu.api.php

example use :

function test_local_tasks_alter(&$local_tasks) {
// add your code to check required condition
if (CONDITION MATCHES) {
unset($local_tasks['Plugin ID']);
}
}

// NOTE: can get plugin ID using dpm(local_tasks)

after this rebuild cache and it will work

ahaomar’s picture

I want to hide "Moderated content" tab there is no view exist but it still appears. Drupal 8 any one guide me how to fix that.