Hi all,

Is it possible to remove the 'Edit' tab from the 'My Account' Page without changing core files.

I can achieve what I want by tweaking user.module, but I'd really rather do it via a module.

The user.module hack is to add an if statement at line 828 to only add the menu item for the admin user

  if ($user->uid == 1) {
    $items[] = array('path' => 'user/'. arg(1) .'/edit', 'title' => t('Edit'),
      'callback' => 'drupal_get_form', 'callback arguments' => array('user_edit'),
      'access' => $admin_access || $user->uid == arg(1), 'type' => MENU_LOCAL_TASK);
  }

Any ideas?
Thanks
Andy

Comments

gausarts’s picture

Found this somewhere, but forget the link:

1. Place this in your template.php:
function yourtheme_removetab($label, &$vars) {
$tabs = explode("\n", $vars['tabs']);
$vars['tabs'] = '';

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

2. Then, call that under function _phptemplate_variables($hook, $vars = array()) {, perhaps after the switch case 'page':

if (arg(0) == 'user') {
yourtheme_removetab('Edit', $vars);
}

break;

Good luck.

love, light n laughter
blogid.net

love, light n laughter

ajg112’s picture

Hi Gaus,

Thanks for the help. That bit of code works really well. The only problem is that you can still access a user edit page if you browse directly to it. I'd like to disable access to non-admin users as well.

Any ideas?
Thanks
Andy

gpk’s picture

The path 'user/xx/edit' is a dynamic menu item added in http://api.drupal.org/api/function/user_menu/5.

You will need a tiny custom module to overwrite the existing permissions on this (currently 'access' => $admin_access || $user->uid == arg(1)).

Create a menu item for 'path' => 'user/'. arg(1) .'/edit' for $may_cache = FALSE and set 'access' => $admin_access, where $admin_access is as defined in user_menu(). Then you need to make sure that your menu hook is called *after* user.module's - this will ensure that your definition overwrites the default. To do this either name your module so that alphabetically it comes after user.module, or else give your module a weight of at least 1 in the {system} table, either manually or else via an install hook in your module's .install file.

gpk
----
www.alexoria.co.uk

ajg112’s picture

Hi Giles,

Thanks again for helping me out. It works but with a slight tweak :)

I added this:

 function my_module_menu($may_cache) {
     $items = array();

     if ($may_cache) {
        // Other menu items
     }
     else {  
       if (is_numeric(arg(1))) {
           $items[] = array(
              'title' => t('Edit'),
              'path' => 'user/'. arg(1) .'/edit',
              'access' => user_access('administer users'),
              'type' => MENU_LOCAL_TASK,
           );
        }
     }

     return $items;
  }

But it turns out that the weight need to be less than that of the user module. Although that does seem a bit backwards???
UPDATE system set weight=-1 WHERE name='my_module';

Thanks again
Andy

gpk’s picture

>But it turns out that the weight need to be less than that of the user module
I'm glad you worked that out (or guessed!) - might not have occurred to me!

I was looking at http://api.drupal.org/api/function/menu_rebuild/5 which calls http://api.drupal.org/api/function/_menu_build/5 which in turn does a module_invoke_all('menu', TRUE);

http://api.drupal.org/api/function/module_invoke_all/5 does an array_merge() with the potential for the later stuff to overwrite existing stuff.

Except that I am way off. For a start, menu hooks return a $items array which is indexed numerically, so no overwriting occurs.

Secondly, we need module_invoke_all('menu', FALSE); - this is in http://api.drupal.org/api/function/_menu_append_contextual_items/5. What is actually happening is the same quirk of the menu system that prevents dynamic ("contextual") items from being able to override the 'access' element of a cached menu item. (In the code, only if a menu item for the given path *doesn't* already exist (if (!isset($_menu['path index'][$item['path']])) {) do we create a new $_menu['path index'][$item['path']] based on $item; otherwise, only the callback and callback arguments can be overriden).

Hence yes, you either need a lower weight, or else just make your module alphabetically before user.module! Then, user.module is unable to override the access element of the menu item because you have already set it :D

gpk
----
www.alexoria.co.uk

ajg112’s picture

Thanks for the explanation. I admit, I did guess. I just wondered if giving it a lower weight would make it work! At least now I know why it made it work!

Thanks again
Andy

danieltome’s picture

You can see that it checks for
MENU_CREATED_BY_ADMIN in the type.

So instead of changing the weight of your module or the letter.
You can add: + MENU_CREATED_BY_ADMIN;
to the type of your menu item.

cheers,

Danno
http://www.danieltome.com

gpk’s picture

Ah yes of course, cunning... :)

gpk
----
www.alexoria.co.uk