diff options
author | Angie Byron <webchick@24967.no-reply.drupal.org> | 2010-11-20 07:19:15 +0000 |
---|---|---|
committer | Angie Byron <webchick@24967.no-reply.drupal.org> | 2010-11-20 07:19:15 +0000 |
commit | 48abcd88f456e5b0b4879a2291aa210ef7d5fd54 (patch) | |
tree | 3ccbdc60cc4f4ce9af48b91f603a31f1c70508d0 /includes/menu.inc | |
parent | 4cc8ae69a1df3d7ac1f33122c1a6afa6ba65fc0f (diff) | |
download | brdo-48abcd88f456e5b0b4879a2291aa210ef7d5fd54.tar.gz brdo-48abcd88f456e5b0b4879a2291aa210ef7d5fd54.tar.bz2 |
#550254 by Damien Tournoud, sun: Fixed some causes of menu links are sometimes not properly re-parented.
Diffstat (limited to 'includes/menu.inc')
-rw-r--r-- | includes/menu.inc | 110 |
1 files changed, 74 insertions, 36 deletions
diff --git a/includes/menu.inc b/includes/menu.inc index b72e3ff90..6536c484d 100644 --- a/includes/menu.inc +++ b/includes/menu.inc @@ -2907,42 +2907,8 @@ function menu_link_save(&$item) { } } - // If we have a parent link ID, we use it to inherit 'menu_name' and 'depth'. - if (isset($item['plid'])) { - if ($item['plid']) { - $parent = db_query("SELECT * FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $item['plid']))->fetchAssoc(); - } - // If the parent link ID is zero, then this link lives at the top-level. - else { - $parent = FALSE; - } - } - // Otherwise, try to find a valid parent link for this link. - else { - $query = db_select('menu_links'); - // Only links derived from router items should have module == 'system', and - // we want to find the parent even if it's in a different menu. - if ($item['module'] == 'system') { - $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', $item['menu_name']); - - // Find the parent - it must be unique. - $parent_path = $item['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); - } - // If a parent link was found, assign it and derive its menu. + // Try to find a parent link. If found, assign it and derive its menu. + $parent = _menu_link_find_parent($item); if (!empty($parent['mlid'])) { $item['plid'] = $parent['mlid']; $item['menu_name'] = $parent['menu_name']; @@ -3064,6 +3030,78 @@ function menu_link_save(&$item) { } /** + * Find 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: + * + * - use the passed parent link if specified and existing. + * - else, use the first existing link down the previous link hierarchy + * - else, for system menu links (derived from hook_menu()), reparent + * based on the path hierarchy. + * + * @param $menu_link + * A menu link. + * @return + * 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 = 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) { + $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; +} + +/** * Helper function to clear the page and block caches at most twice per page load. */ function _menu_clear_page_cache() { |