3

I want to modify the main system menu in Drupal 7. Actually I want to display only some specific elements of the menu and hide some other specific elements, in a given case (which I will implement by a if or switch statement in a function).

What is the easiest way to do this ? And how to do it ? Can you give me an example ?

I have read that using hook_theme or hook_menu can be done, but I have no idea how to do this.

1
  • Finally I have adopted a more simple method suggested from your comments. I have created for each situation a new menu containing the elements that I needed. Thanks to everyone for your suggestions.
    – EKK
    Mar 17, 2011 at 9:02

4 Answers 4

4

There are different levels to alter the system menu. If you want to add a top level container like drupal commerce does for the admin shop section, you need to add a menu item with hook menu like this:

// Top level "Store" container.
$items['admin/commerce'] = array(
  'title' => 'Store',
  'description' => 'Administer your store.',
  'page callback' => 'system_admin_menu_block_page',
  'access arguments' => array('access administration pages'),
  'file path' => drupal_get_path('module', 'system'),
  'file' => 'system.admin.inc',
  'weight' => -7,
);

system_admin_menu_block_page is what will do the job, of making it a part of the system menu.

If you want to make the menu appear under one of the sections, like configuration etc, you just need to adjust your path in hook_menu, fx

$items['admin/config/section'] = array(...);

Every time you want to create a section that should hold other menu items, simply add

'page callback' => 'system_admin_menu_block_page',
'access arguments' => array('access administration pages'),
'file' => 'system.admin.inc',
'file path' => drupal_get_path('module', 'system'),

When creating a menu item in a section, just create a normal menu item.

Update
Since the menu structure is cached, you can't alter the menu by a per user scenario. But there are still some methods available.

  • Since menus are only displayed if the user has access, you could create a custom access control function for all the menus and put your logic in there.
  • You could also try to do this in the theming layer, and alter the output to only display the desired menus. I haven't tried this in Drupal 7, but generally, altering the output of menus this way is hard, as the menu system is quite complex.

If you need to alter the menus, to change the access control, you should use hook_menu_alter.

2
  • Thanks for your answer. Maybe I wasn't very clear in my question (I have edit it), but actually I want to display only some specific elements of the menu and hide some other specific elements, in a given case (which I will implement by a if or switch statement in a function).
    – EKK
    Mar 16, 2011 at 10:09
  • @Ek Kosmos I updated the answer, to fit your question.
    – googletorp
    Mar 16, 2011 at 11:27
2

Without more information about your use case (including: the content of this mysterious condition "which [you] will implement by a if or switch statement in a function", and the definition of "some part of the menu"), it is difficult to give you a definite answer.

Just know that Drupal's menu system is a complex tool designed to handle a wide variety of use cases and menu structures. Its standard display logic is designed to show the user only the links it can actually access, so that no Drupal user should ever land on a 403 page.

The menu system also supports dynamic alterations of the menu links (and of their visibility) via hook_translated_menu_link_alter(), but it requires a little bit of work:

  • First you need to mark the menu links you want to target as "alterable", for example by settings their $link['options']['alter'] to TRUE in a hook_menu_link_alter() or hook_menu_alter() if they are menu router items.
  • Then you can implement hook_translated_menu_link_alter() and set the 'access' property of the links you want to hide to FALSE.

You can also use per-packaged solutions like the menu_per_role module already mentioned.

Modifying the menu structure just before rendering in the theming level is never the solution.

1
  • +1 for the suggestion contained in the last sentence. I would add another +1 for reminding that $link['options']['alter'] can be set also in a implementation of hook_menu_alter(), but the system doesn't allow me.
    – apaderno
    Mar 16, 2011 at 19:21
2

You want to hide the menu based on a condition. It depends on what the condition is, however. If you can base it on role, there is a module for that: Menu Per Role

If you have more complicated logic you may have to create different menus for the different cases. The menu system caches menus so it is difficult to alter dynamically. By creating multiple menus, you can show different ones in a block based on your condition by using the Menu Block module.

1

There are many ways you could do this in the theme template files, or in a preprocessor. However if you don't want links in the menu why not just go to /admin/build/menu and remove them from the menu?

1
  • I can not work with /admin/build/menu, because actually I want to display only some part of the menu and hide other part in a given case.
    – EKK
    Mar 16, 2011 at 9:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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