A menu item's parent is derived from the structure of the path which forces people to construct complex paths to create menu structure. Provide a way to separate menu structure from path so that path can be used purely to specify the path.

A menu item's parent is derived from the structure of the path using the following code:

$parent = substr($parent, 0, strrpos($parent, '/'));

That line does not give modules the freedom to create structured menus when the path does not use a structure as occurs in taxonomy. The following taxonomy path could be three levels deep in a menu but cannot be decoded that way:
taxonomy/term/65

As an example, taxonomy_menu has to replace the taxonomy style path, taxonomy/term/65, with a duplicate path to generate a structured menu. The following path is an example of a taxonomy_menu path and creates a huge number of problems because a node cannot have multiple paths:
taxonomy_term/12/32/54/65

The ideal, in the taxonomy_menu case, is to use existing paths and define the menu structure another way. The flexibility will let us path purely as a path and define the menu structure independently. To achieve the independence, I added one extra test to allow manual specification of a parent via a 'parent' attribute.

I changed following code. The code logic looks a bit backward with the !isset and performing the complex case first.

if (!isset($item['pid']))
	{
	// Parent's location has not been customized, so figure it out using the path.
	$parent = $item['path'];
	if ($parent)
		{
		do
			{
			$parent = substr($parent, 0, strrpos($parent, '/'));
			}
		while ($parent && !isset($_menu['path index'][$parent]));
		}
	$pid = $parent ? $_menu['path index'][$parent] : 1;
	$_menu['items'][$mid]['pid'] = $pid;
	}
else
	{
	$pid = $item['pid'];
	}

I reversed the order for simplicity.

if (isset($item['pid']))
	{
	$pid = $item['pid'];
	}
else
	{
	// Parent's location has not been customized, so figure it out using the path.
	$parent = $item['path'];
	if ($parent)
		{
		do
			{
			$parent = substr($parent, 0, strrpos($parent, '/'));
			}
		while ($parent && !isset($_menu['path index'][$parent]));
		}
	$pid = $parent ? $_menu['path index'][$parent] : 1;
	$_menu['items'][$mid]['pid'] = $pid;
	}

Next I added one extra test for $item['parent']:

if (isset($item['pid']))
	{
	$pid = $item['pid'];
	}
elseif(isset($item['parent']) and isset($_menu['path index'][$item['parent']]))
	{
	$pid = $_menu['path index'][$item['parent']];
	$_menu['items'][$mid]['pid'] = $pid;
	}
else
	{
	// Parent's location has not been customized, so figure it out using the path.
	$parent = $item['path'];
	if ($parent)
		{
		do
			{
			$parent = substr($parent, 0, strrpos($parent, '/'));
			}
		while ($parent && !isset($_menu['path index'][$parent]));
		}
	$pid = $parent ? $_menu['path index'][$parent] : 1;
	$_menu['items'][$mid]['pid'] = $pid;
	}

Comments

RobRoy’s picture

Version: 4.7.4 » 6.x-dev

Features go to 6.x-dev. This has been a request of mine and as the menu system is going to be completely revamped in D6, we'll have to wait until then.

peterx’s picture

Skip D5, start on D6 now.

I forgot to mention, for those who want to apply this change before D6, the change is in includes/menu.inc, function _menu_find_parents(&$items). The function is the same in Drupal 4.7 and 5.0.

I will reference this request under some entries for taxonomy_menu as it fixes a problem with the combination of taxonomy, pathauto, and taxonomy_menu.

peterx’s picture

The change works for 5.0 RC2 in includes/menu.inc function _menu_find_parents(&$items) around line 1296.

Bevan’s picture

I've heard that chx is rewriting menu.module for d6. Does that mean this patch is no longer relevant? Will this patch be mixed in with chx rewrite? Does anyone know?

dropcube’s picture

Status: Active » Closed (fixed)

Closing this issue... If it still applies or you guys have any other comment, re-open it.