summaryrefslogtreecommitdiff
path: root/includes/menu.inc
diff options
context:
space:
mode:
authorAngie Byron <webchick@24967.no-reply.drupal.org>2010-11-20 07:19:15 +0000
committerAngie Byron <webchick@24967.no-reply.drupal.org>2010-11-20 07:19:15 +0000
commit48abcd88f456e5b0b4879a2291aa210ef7d5fd54 (patch)
tree3ccbdc60cc4f4ce9af48b91f603a31f1c70508d0 /includes/menu.inc
parent4cc8ae69a1df3d7ac1f33122c1a6afa6ba65fc0f (diff)
downloadbrdo-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.inc110
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() {