From b2768d0b58fb62e3ccf42259b3423b1514c6049f Mon Sep 17 00:00:00 2001
From: Mark Carver <mark.carver@me.com>
Date: Wed, 7 Nov 2012 17:25:14 -0600
Subject: [PATCH] Fixes [#1826206] - Notice: Undefined property:
 stdClass::$nid in _menu_views_form_alter()

This also fixes menu items not getting saved on new nodes.
---
 menu_views.admin.inc |   2 +-
 menu_views.module    | 142 ++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 103 insertions(+), 41 deletions(-)

diff --git a/menu_views.admin.inc b/menu_views.admin.inc
index 3df6144..77e16c0 100644
--- a/menu_views.admin.inc
+++ b/menu_views.admin.inc
@@ -213,7 +213,7 @@ function _menu_views_form_alter(array &$element, array &$form, array &$form_stat
     else {
       $element['link_path'] = array(
         '#type' => 'value',
-        '#value' => $node->nid ? 'node/' . $node->nid : '',
+        '#value' => $node && isset($node->nid) ? 'node/' . $node->nid : '',
       );
     }
   }
diff --git a/menu_views.module b/menu_views.module
index 034bc63..0408f43 100644
--- a/menu_views.module
+++ b/menu_views.module
@@ -350,6 +350,46 @@ function menu_views_menu_link_alter(&$link) {
 }
 
 /**
+ * Helper function to return the menu link item based on it's original path.
+ *
+ * @param (string) $original_path
+ *   The [node] path for which to search for in menu views.
+ * @param (string)|(array) $menu_name
+ *   Limit the search of menu view items to the specified menu names.
+ * @return
+ *   (array) $mlids
+ *   A keyed array containing the identification integers matching the original path of menu items in the {menu_links} table,
+ *   or an empty array if no menu items were found.
+ *
+ * @see: menu_views_node_prepare() and menu_views_node_delete().
+ */
+function _menu_views_items_from_original_path($original_path, $menu_name = NULL) {
+  $mlids = array();
+  // Build the query.
+  $query = db_select('menu_links', 'm')
+            ->fields('m', array('mlid', 'options'))
+            ->condition('module', 'menu')
+            ->condition('link_path', '<view>');
+  // Set the menu_name condition if present.
+  if (!empty($menu_name)) {
+    $query = $query->condition('menu_name', $menu_name);
+  }
+  // Execute the query.
+  $query = $query->execute();
+  // Iterate through all available menu items that are views to match against the original path.
+  while($link = $query->fetchObject()) {
+    if ($options = unserialize($link->options)) {
+      $item = _menu_views_get_item($options);
+      if ($item['original_path'] == $original_path) {
+        $mlids[] = $link->mlid;
+        break;
+      }
+    }
+  }
+  return $mlids;
+}
+
+/**
  * Implements hook_node_prepare().
  */
 function menu_views_node_prepare($node) {
@@ -357,48 +397,18 @@ function menu_views_node_prepare($node) {
     // Prepare the node for the edit form so that $node->menu always exists.
     $menu_name = strtok(variable_get('menu_parent_' . $node->type, 'main-menu:0'), ':');
     $item = array();
-    $mlid = FALSE;
+    $mlids = array();
     // Give priority to the default menu.
     $type_menus = variable_get('menu_options_' . $node->type, array('main-menu' => 'main-menu'));
     if (in_array($menu_name, $type_menus)) {
-      // Iterate through all available menu items that are views to match against the original path.
-      $result = db_select('menu_links', 'm')
-                  ->fields('m', array('options'))
-                  ->condition('module', 'menu')
-                  ->condition('link_path', '<view>')
-                  ->condition('menu_name', $menu_name)
-                  ->execute();
-      while($options = unserialize($result->fetchField())) {
-        if ($options) {
-          $item = _menu_views_get_item($options);
-          if ($item['original_path'] == 'node/' . $node->nid) {
-            $mlid = $item['mlid'];
-            break;
-          }
-        }
-      }
+      $mlids = _menu_views_items_from_original_path('node/' . $node->nid, $menu_name);
     }
     // Check all allowed menus if a link does not exist in the default menu.
-    if (!$mlid && !empty($type_menus)) {
-      // Iterate through all available menu items that are views to match against the original path.
-      $result = db_select('menu_links', 'm')
-                  ->fields('m', array('options'))
-                  ->condition('module', 'menu')
-                  ->condition('link_path', '<view>')
-                  ->condition('menu_name', array_values($type_menus))
-                  ->execute();
-      while($options = unserialize($result->fetchField())) {
-        if ($options) {
-          $item = _menu_views_get_item($options);
-          if ($item['original_path'] == 'node/' . $node->nid) {
-            $mlid = $item['mlid'];
-            break;
-          }
-        }
-      }
+    if (empty($mlid) && !empty($type_menus)) {
+      $mlids = _menu_views_items_from_original_path('node/' . $node->nid, array_values($type_menus));
     }
     // Load the menu link if one was found.
-    $item = $mlid ? menu_link_load($mlid) : array();
+    $item = empty($mlids) ? array() : menu_link_load(reset($mlids));
     // Set default values.
     $default = array(
       'link_title' => '',
@@ -423,6 +433,16 @@ function menu_views_node_prepare($node) {
 }
 
 /**
+ * Implements hook_node_delete().
+ */
+function menu_views_node_delete($node) {
+  $mlids = _menu_views_items_from_original_path('node/' . $node->nid);
+  foreach ($mlids as $mlid) {
+    menu_link_delete($mlid);
+  }
+}
+
+/**
  * Implements hook_node_insert().
  */
 function menu_views_node_insert($node) {
@@ -430,6 +450,30 @@ function menu_views_node_insert($node) {
 }
 
 /**
+ * Implements hook_node_presave().
+ */
+function menu_views_node_presave($node) {
+  if (isset($node->menu)) {
+    $link = &$node->menu;
+    $item = _menu_views_get_item($link);
+    // Ensure the enabled property is set.
+    if (!isset($link['enabled'])) {
+      $link['enabled'] = !(bool) $link['hidden'];
+    }
+    // If this is a menu view item, override properties on the link so this module handles the save.
+    if ($link['enabled'] && $item['type'] == 'view') {
+      // Save the mlid in the menu_views array so the menu module doesn't delete the link when it detects the mlid.
+      if (!empty($link['mlid'])) {
+        $link['options']['menu_views']['mlid'] = $link['mlid'];
+        $link['mlid'] = 0;
+      }
+      // Ensure there is no title so the menu module doesn't try to save this menu item.
+      $link['link_title'] = '';
+    }
+  }
+}
+
+/**
  * Implements hook_node_update().
  */
 function menu_views_node_update($node) {
@@ -442,12 +486,30 @@ function menu_views_node_update($node) {
 function menu_views_node_save($node) {
   if (isset($node->menu)) {
     $link = &$node->menu;
-    if (empty($link['enabled'])) {
-      if (!empty($link['mlid'])) {
-        menu_link_delete($link['mlid']);
+    $item = _menu_views_get_item($link);
+    // Check to see if Menu Views should handle the menu item save.
+    if (!empty($link['enabled']) && $item['type'] == 'view') {
+      // If this an existing menu item, check to see if the mlid was saved in the menu view options array.
+      if (!empty($item['mlid']) && empty($link['mlid'])) {
+        $link['mlid'] = $item['mlid'];
       }
-    }
-    else {
+      // This is a new menu link, create one so we can get the mlid.
+      // Note: This will save the menu link twice on new nodes, which is unavoidable since
+      // we need the mlid to be saved in the menu views options array.
+      elseif (empty($link['mlid'])) {
+        if (!menu_link_save($link)) {
+          drupal_set_message(t('There was an error saving the menu link.'), 'error');
+          return;
+        }
+      }
+      // Ensure mlid is properly set.
+      $item['mlid'] = $link['mlid'];
+      // Ensure link_path is properly set.
+      $link['link_path'] = '<view>';
+      // Ensure original_path is properly set.
+      $item['original_path'] = 'node/' . $node->nid;
+      // Replace the menu view options in the link and save it.
+      $link['options']['menu_views'] = $item;
       if (!menu_link_save($link)) {
         drupal_set_message(t('There was an error saving the menu link.'), 'error');
       }
-- 
1.7.11.5

