(I'm looking for the exact same functionality as provided by Menu Trails for Drupal 5)

How do I programmatically add a node as a subitem to an existing menu item?

Ex:

- Section 1
- - Area 1
- - Area 2
- - Area 3
- Section 2
- - Area 4
- - Area 5

Each area matches a taxonomy term and have hundreds of nodes associated with them. I don't want to add the nodes in the menu system, but if a node is associated with i.e. the menu item "Area 3", the menu needs to be expanded to that item.

Any help? menu_set_location doesn't exists any more

Comments

deplifer’s picture

Drupal 5

1. http://api.drupal.org/api/function/menu_set_location/5
2. http://api.drupal.org/api/function/menu_set_active_item/5

Drupal 6

1. http://api.drupal.org/api/function/menu_set_active_trail/6
2. http://api.drupal.org/api/function/menu_set_active_item/6

Use the hook_nodeapi() and in the view operation set the active trail or location.

Be careful if you decide to use the menu_set_active_item function, if you use this too early as in the hook_menu you will change the actual location of the page.

andershal’s picture

Is this the Drupal way? My issue seems like a common thing to do, but the solution is pretty advanced; creating menu router items and shuffling them around :-)

Can you provide an example of the menu_set_active_trail usage?

--
Anders Hal

andershal’s picture

Looking at the code in menu_tree_page_data(), which is called to generate our menu tree, it seems unlikely that menu_set_active_trail() should have any influence at all on the returned menu. The only way seems to be creating all items dynamically in the menu_links table?

--
Anders Hal

pcave’s picture

Did you ever figure this out? I'm facing the same problem.

Thanks,
Phillip

andershal’s picture

Marko B’s picture

Its useless, doesnt work with more complex hierarhcy as you have to have all in separate categories and cannot mix taxonomies then.

joachim’s picture

Try http://drupal.org/project/node_breadcrumb
That lets you set fairly complex rules for placing nodes into menus. You can even use PHP conditions.

Marko B’s picture

Yeah, seems this could help. but it so tiresome. Seems then first i have to manualy set up all navigation in menu, for every item 5 main menus, 5 submenus and 4 of them another 5 submenu. Then i have to make all of the rules for all of this menus and still have to figure out how to apply this to menu so navigation knows where it is and doesnt reset itself on node view. Thanx joachim but if this is the only way then i am really disappointed with drupal :-(

joachim’s picture

Erm what are you trying to do?
This module *is* about setting menus on node view.
If you're doing this just for a few nodes, it sounds like you might as well put them into the menu structure directly.

Marko B’s picture

No it's not few nodes. I am trying to have active menu item set all the time, even when viewing node. Have 2 level menu with hundreds of nodes 4 node types and 4 taxonomies that combine with each other to form menus. So making it like you said wouldnt help :(

dquakenbush’s picture

Did anyone make progress on this?
I have a similar problem, and all of the standard solutions are too limiting.
I have a bunch of nodes that don't belong in the menu system, but that need to have a specific parent menu item active when they are viewed. Taxonomy doesn't go deep enough in our heirerarchy, and our content types are scattered throughout the site.

My thought is that Pathauto does a fine job of dealing with exactly this sort of complexity (every URL element happens to lead to a page in a consistent hierarchy). I'm trying to sort out how to define the active menu item from the pathauto URL.

Our site doesn't use breadcrumbs -- but if we did the breadcrumbs should reflect the pathauto URL. I had this working in 5, but it seems like we can't get there from here in 6.

-------| edit |-----

Actually, we can get there in v 6. Here's a little code snip for a module that asks the menu to unfurl for a node with no menu item based on the pathauto/url alias URL path. There's probably a much more effecient way to do this -- feel free to tinker.


/**
 * @file
 * pathauto2menu sets the active menu based on the pathauto path.
 * heavily influenced by the menutrails module.
 */



/***
* Implementation of hook_nodeapi
*
* This will evaluate individual nodes when being viewed and take the necessary
* steps to set the active_trail for menus.
*
*/

function pathauto2menu_nodeapi(&$node, $op, $a3 = NULL, $page = FALSE) {
  if ($op == 'view' && $page == TRUE) { 
    $item = pathauto2menu_find_top();
    if ($item) {
      menu_set_item(NULL, $item);
    }
  }
}


// inspired by _menu_get_active_trail()
function pathauto2menu_find_top() {
  // this should only fire if the menu isn't already active
  $item = menu_get_item();
  if (db_result(db_query("SELECT count(mlid) FROM {menu_links} WHERE link_path = '%s' AND module = 'menu'", $item['href'])) == 0) {
       
       //Grab the path for the node. $path is the pathauto path. 
       $path = $item[map][1]->path;
       $pathparts = explode('/', $path);
       $depth = count($pathparts);
              
       while($depth > '1') {
		   //try again with one less element from the pathauto path
			$drop = array_pop($pathparts);
			$depth = count($pathparts);
			$path = "";
			foreach($pathparts as $dir) {
				$path = $path . $dir . "/";
			}
			$path = substr("$path",0,-1); //remove the trailing slash
			
			$search = db_fetch_array(db_query("select count(*), url_alias.src from {url_alias}, {menu_links} where url_alias.src = menu_links.link_path AND url_alias.dst='%s'",$path));
			//Does this path have a menu?
		   if($search['count(*)'] != '0'){
			   
			   //return the drupal URL of the longest pathauto path
			   $item[href] = $search['src'];
			   return $item ;
       		}
       } //endwhile
    } else {
      //can't find a menu item?
	  return FALSE;
   }
}

Enjoy :-)

terbs’s picture

I had success with this little piece of code. I used this in my contemplate, but you can also put it in hook_nodeapi in the view operation.

//Sets the active menu item to foo/bar
$path = drupal_get_normal_path('foo/bar');
$menu_item = menu_get_item($path);
if($path && $menu_item) {
  menu_set_item(NULL, $menu_item);
}
lahode’s picture

Thanks aiquandol, very simple and works perfectly

Below, you'll find an example with Drupal 7, to display all "video" content types with the menu active

function MYMODULE_node_view($node, $view_mode, $langcode) {
  $nid = 185; // Or the ID from the page where is set in the menu
  if ($node->type == 'video') {
    $menu_item = menu_get_item('node/' . $nid);
    if($menu_item) {
      menu_set_item(NULL, $menu_item);
    }
  }
}

Fredrik Lahode
Développeur et Formateur web indépendant

monaw’s picture

I know the above comment is 2 years old but I'm using Drupal 7 and the above didn't work for me ):

Anybody else got this working?