You can get the complete (main) menu tree with this in your THEME_preprocess_page
// Get the entire main menu tree
$main_menu_tree = menu_tree_all_data('main-menu');
// Add the rendered output to the $main_menu_expanded variable
$vars['main_menu_expanded'] = menu_tree_output($main_menu_tree);
Then you can pass that to a theme function in your page template:
<?php print theme('links__system_main_menu', array(
'links' => $main_menu_expanded,
'attributes' => array(
'id' => 'main-menu',
'class' => array('nav', 'navbar-nav'),
),
)); ?>
I've been using the function below to create a Bootstrap ready dropdown menu - you can clearly see how the submenus are themed by checking the $link['#below']
part of the array.
/**
* Implements hook_links__system_main_menu().
*
* @param array $vars
* @return string
* Themed HTML for bootstrap 3 ready main menu.
*/
function YOURTHEME_links__system_main_menu($vars) {
// Get the active trail
$menu_active_trail = menu_get_active_trail();
// Initialise our custom trail.
$active_trail = array();
// Get current path
$dest = drupal_get_destination();
if (is_string($dest['destination'])) {
$paths = explode('/', $dest['destination']);
// Loop through and add all active paths
foreach ($paths as $path) {
// Read previous element added to active trail (using array values
// preserves original array).
$safe = array_values($active_trail);
$previous = array_pop($safe);
if ($previous) {
$active_trail[] = $previous . '/' . $path;
}
// Or this is the first one
else {
$active_trail[] = $path;
}
}
}
// UL classes
$class = implode($vars['attributes']['class'], ' ');
$html = '<ul class="' . $class . '" id="' . $vars['attributes']['id'] . '">';
// Iterate links to build menu.
foreach ($vars['links'] as $key => $link) {
// Check this is a link not a property.
if (is_numeric($key)) {
$sub_menu = '';
$li_class = array();
$a_class = array();
// Check if link is in active trail and add class.
if (in_array($link['#original_link']['link_path'], $active_trail)) {
$li_class[] = 'active-trail';
}
if ($link['#original_link']['link_path'] == end($active_trail)) {
$li_class[] = 'active';
}
// Check if last element in list and see if LI contains actual link
$link['#attributes']['class'][] = strtolower(str_replace(array('& ', ' '), array('', '-'), $link['#title']));
$link_title = $link['#title'];
if (isset($link['#localized_options']['attributes'])) {
$link['#attributes'] = array_merge($link['#localized_options']['attributes'], $link['#attributes']);
}
// Check if we have a submenu.
if (!empty($link['#below'])) {
// Check if lvl 1, if higher do other stuff
if ($link['#original_link']['depth'] < 2) {
$li_class[] = 'dropdown';
$link_title .= '<b class="caret"></b>';
$link['#attributes']['class'][] = 'dropdown-toggle';
$link['#attributes']['data-toggle'] = 'dropdown';
} else {
$li_class[] = 'dropdown-submenu';
$link_title .= '<b class="caret"></b>';
}
// Theme submenu
$sub_menu = theme('links__system_main_menu', array('links' => $link['#below'], 'attributes' => array('class' => array('dropdown-menu'))));
}
// Build classes string
$classes = '';
if (!empty($li_class)) {
$classes = ' class="' . implode($li_class, ' ') . '"';
}
$html .= '<li' . $classes . '>' . l($link_title, $link['#href'], array('html' => 'true', 'attributes' => $link['#attributes'])) . $sub_menu . '</li>';
}
}
$html .= '</ul>';
return $html;
}