How to get all the menu items below a certain parent in drupal 7?

user1808858 picture user1808858 · Nov 8, 2012 · Viewed 9k times · Source

I am currently working on a module that finds out the parent menu item by url path then displays the current tree structure of that related menu by finding the top parent and most important only displaying that menu item and submenus from within that menu.

A simple solution would be having a foreach loop thru all items or an array with all items as keys.

path = '/system/menu/submenu';
parent = 'system';
output = parent + parent submenus.

All menu items in "Custom menu":

- System
   - Menu wrapper
     - SubMenu 1A
     - SubMenu 2A
     - SubMenu 3A    
- Main
  - SubMenu 1B
  - SubMenu 2B
  - SubChildMenu 3B

PHP code should return this:

- System
   - Menu wrapper
     - SubMenu 1A
     - SubMenu 2A
     - SubMenu 3A    

My code (currently not working):

 $menu = menu_tree('my-custom-menu');
 return = theme('my_custom_menu', array('system' => $menu_tree));

Notice: This needs to be php code and php code only, all other modules does not support this only thru manual selection. The content is displayed thru a block.

"For the navigation, Drupal will call menu_tree_page_data via menu_navigation_links which will only return a single level of links. You can follow this function up to menu_main_menu and then template_preprocess_page before it (which is how it ends up as a variable in page.tpl.php)

However, if you insert a menu as a block menu_tree_page_data is called by menu_tree (which calls menu_tree_output immediately after which does some additional work to the array for the final markup.) After both have run you have your whole menu tree available as an array which I then ran through some custom PHP code to loop through the array and render it into an HTML list."

People have asked this before but i've tried their solutions and no success probable cause would be those questions is for drupal 6. I'm currently working with drupal 7.

Your help is very much appreciated, thanks...

Related questions:


Restrict menu tree to first level

how to get all the menu items below a certain parent in drupal?

https://drupal.stackexchange.com/questions/28654/how-to-display-submenus-separate-from-their-menu-tree-in-drupal-7

https://drupal.stackexchange.com/questions/30112/displaying-a-menus-child-links

Answer

Felix Eve picture Felix Eve · Nov 19, 2012

First thing you need is the mlid of the page your currently on:

$q = variable_get('site_frontpage', 'node') == $_GET["q"] ? '<front>' : $_GET["q"];
$current_menu_item = db_select('menu_links' , 'ml')
  ->condition('ml.link_path' , $q)
  ->fields('ml', array('mlid', 'plid'))
  ->execute()
  ->fetchAll();

Now if the plid of this menu item is 0 then we know it is a top level menu item, if it is not 0 then we need to get the parent. So the top mlid of the tree we want to get is:

$top_level_mlid = $current_menu_item->plid == 0 ? $current_menu_item->mlid : $current_menu_item->plid;

Then you need to load your full menu:

$full_menu_items = menu_tree_all_data('main-menu');

Now loop though all the menu items and just get the bit we want:

foreach($full_menu_items as $menu_item) {
    if($menu_item['link']['mlid'] == $top_level_mlid) {
        $links = $menu_item['below'];
        break;
    }
}

$links now hold all of the links from the specific part of the menu that you are after.

And to output that array as a menu on the page:

echo theme('links__system_secondary_menu', array(
    'links' => $links, 
    'attributes' => array(
        'id' => 'secondary-menu', 
        'class' => array('links', 'clearfix')), 
        'heading' => array(
            'text' => t('Secondary menu'), 
            'level' => 'h2', 
            'class' => array('element-invisible')
        )
));