I always wondered why there is no function for this in core, but afaik there is none.
So it looks like we need to roll our own, walking a complete menu tree until we find the subtree we need:
/**
* Extract a specific subtree from a menu tree based on a menu link id (mlid)
*
* @param array $tree
* A menu tree data structure as returned by menu_tree_all_data() or menu_tree_page_data()
* @param int $mlid
* The menu link id of the menu entry for which to return the subtree
* @return array
* The found subtree, or NULL if no entry matched the mlid
*/
function yourModule_menu_get_subtree($tree, $mlid) {
// Check all top level entries
foreach ($tree as $key => $element) {
// Is this the entry we are looking for?
if ($mlid == $element['link']['mlid']) {
// Yes, return while keeping the key
return array($key => $element);
}
else {
// No, recurse to children, if any
if ($element['below']) {
$submatch = yourModule_menu_get_subtree($element['below'], $mlid);
// Found wanted entry within the children?
if ($submatch) {
// Yes, return it and stop looking any further
return $submatch;
}
}
}
}
// No match at all
return NULL;
}
To use it, you first need to get the tree for the whole menu, using menu_tree_page_data()
or menu_tree_all_data()
, depending on what you need (check the API definitions for the difference). Then you extract the subtree you want, based on the mlid. This subtree can then be rendered into HTML via menu_tree_output()
:
$mlid = 123; // TODO: Replace with logic to determine wanted mlid
$tree = menu_tree_page_data('navigation'); // TODO: Replace 'navigation' with name of menu you're interested in
// Extract subtree
$subtree = yourModule_menu_get_subtree($tree, $mlid);
// Render as HTML menu list
$submenu = menu_tree_output($subtree);
Disclaimer: I am not sure if this is a good/proper way to do it - it is just the solution I came up with after going through the same procedure as the OP, that is, reading through the whole menu module functions, always wondering if I'm missing the obvious somewhere...