Finds a possible parent for a given menu link.
Because the parent of a given link might not exist anymore in the database, we apply a set of heuristics to determine a proper parent:
$menu_link: A menu link.
$parent_candidates: An array of menu links keyed by mlid.
A menu link structure of the possible parent or FALSE if no valid parent has been found.
function _menu_link_find_parent($menu_link, $parent_candidates = array()) {
$parent = FALSE;
// This item is explicitely top-level, skip the rest of the parenting.
if (isset($menu_link['plid']) && empty($menu_link['plid'])) {
return $parent;
}
// If we have a parent link ID, try to use that.
$candidates = array();
if (isset($menu_link['plid'])) {
$candidates[] = $menu_link['plid'];
}
// Else, if we have a link hierarchy try to find a valid parent in there.
if (!empty($menu_link['depth']) && $menu_link['depth'] > 1) {
for ($depth = $menu_link['depth'] - 1; $depth >= 1; $depth--) {
$candidates[] = $menu_link['p' . $depth];
}
}
foreach ($candidates as $mlid) {
if (isset($parent_candidates[$mlid])) {
$parent = $parent_candidates[$mlid];
}
else {
$parent = db_query("SELECT * FROM {menu_links} WHERE mlid = :mlid", array(
':mlid' => $mlid,
))
->fetchAssoc();
}
if ($parent) {
return $parent;
}
}
// If everything else failed, try to derive the parent from the path
// hierarchy. This only makes sense for links derived from menu router
// items (ie. from hook_menu()).
if ($menu_link['module'] == 'system') {
$query = db_select('menu_links');
$query
->condition('module', 'system');
// We always respect the link's 'menu_name'; inheritance for router items is
// ensured in _menu_router_build().
$query
->condition('menu_name', $menu_link['menu_name']);
// Find the parent - it must be unique.
$parent_path = $menu_link['link_path'];
do {
$parent = FALSE;
$parent_path = substr($parent_path, 0, strrpos($parent_path, '/'));
$new_query = clone $query;
$new_query
->condition('link_path', $parent_path);
// Only valid if we get a unique result.
if ($new_query
->countQuery()
->execute()
->fetchField() == 1) {
$parent = $new_query
->fields('menu_links')
->execute()
->fetchAssoc();
}
} while ($parent === FALSE && $parent_path);
}
return $parent;
}