#761648-node-menu-upgrade

From: Damien Tournoud <damien@commerceguys.com>


---
 modules/menu/menu.install |   37 +++++++++++++++++++++++++++++++++++++
 modules/menu/menu.module  |   12 ++++++++----
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/modules/menu/menu.install b/modules/menu/menu.install
index 05aed28..7dfcde8 100644
--- a/modules/menu/menu.install
+++ b/modules/menu/menu.install
@@ -69,3 +69,40 @@ function menu_uninstall() {
   menu_rebuild();
 }
 
+/**
+ * @defgroup updates-7.x-extra Extra updates for 7.x
+ * @{
+ */
+
+/**
+ * Upgrade path for finer node menu controls.
+ */
+function menu_update_7000() {
+  // Retain Drupal 6 menu setting for node parents or set all menus if such
+  // setting was not found (such as a previously running Drupal 7 site).
+  $default_node_menu = variable_get('menu_default_node_menu');
+
+  // Upgrade only if setting was overriden.
+  if (isset($default_node_menu)) {
+    $defined_menus = db_query('SELECT * FROM {menu_custom}')->fetchAllAssoc('menu_name', PDO::FETCH_ASSOC);
+    // If menu does not exist node settings would use D7 defaults.
+    if (!isset($defined_menus[$default_node_menu])) {
+      return;
+    }
+
+    // Update the menu setting for each node type.
+    foreach (_update_7000_node_get_types() as $type => $type_object) {
+      $type_menus = variable_get('menu_options_' . $type);
+      // This upgrade function was implemented after the release of 7.0, so
+      // do not touch settings that are already set.
+      if (!isset($type_menus)) {
+        variable_set('menu_options_' . $key, array($default_node_menu));
+      }
+    }
+  }
+}
+
+/**
+ * @} End of "defgroup updates-7.x-extra"
+ * The next series of updates should start at 8000.
+ */
diff --git a/modules/menu/menu.module b/modules/menu/menu.module
index ec41c2f..1dd8bcc 100644
--- a/modules/menu/menu.module
+++ b/modules/menu/menu.module
@@ -592,8 +592,9 @@ function menu_form_node_form_alter(&$form, $form_state) {
   // @todo This must be handled in a #process handler.
   $type = $form['#node']->type;
   $options = menu_parent_options(menu_get_menus(), $type);
-  // If no possible parent menu items were found, there is nothing to display.
-  if (empty($options)) {
+  // If no possible parent menu items were found and no menu link exists,
+  // there is nothing to display.
+  if (empty($options) && empty($form['#node']->menu['mlid'])) {
     return;
   }
   $link = $form['#node']->menu;
@@ -647,9 +648,12 @@ function menu_form_node_form_alter(&$form, $form_state) {
   );
 
   $default = ($link['mlid'] ? $link['menu_name'] . ':' . $link['plid'] : variable_get('menu_parent_' . $type, 'main-menu:0'));
-  // @todo This will fail with the new selective menus per content type.
+
+  // If the item is in a menu that is not permitted for this content type,
+  // allow it to stay there.
   if (!isset($options[$default])) {
-    $default = 'navigation:0';
+    $all_options = menu_parent_options(menu_get_menus(), $link);
+    $options[$default] = $all_options[$default];
   }
   $form['menu']['link']['parent'] = array(
     '#type' => 'select',
