Taxonomy_menu module easily generates navigation blocks linked to taxonomy terms in a vocabulary. Even better, it gives perfect breadcrumbs and a listing page (without requiring a parent term in each vocab) for the top level of the menu (which is actually the vocab name) that pulls in all the nodes in that vocab.

The only problem is in using pathauto with the generated menu and nodes tagged with terms from that menu. You can alias the terms in the navigation block from www.domain.com/taxonomy_menu/vid/tid to www.domain.com/vocab-name/term-name, but the actual taxonomy terms remain unaliased. As a result, if you tag a node with terms from an aliased menu, the links to the terms still point to their taxonomy urls.

Any suggestions?

Comments

dkruglyak’s picture

I would like to find a way to do that too.

The feature seems to be lost somewhere in between pathauto and taxonomy_menu maintainers...

venkat-rk’s picture

I have written to the pathauto maintainer, offering to pay a bit for the feature. Hoping for a good result or an explanation.

Needless to say, it will be released to the community if the feature is implemented and it works.

Christoph C. Cemper’s picture

Did you get any feedback so far, any results? I'd pay a bit as well... christoph

venkat-rk’s picture

Mike Ryan (he no longer maintains pathauto, unfortunately) replied to me indicating that it would be better for the taxonomy_menu maintainer to implement the pathauto API as he would know the taxonomy_menu module better. And, there it stands :(

I didn't approach the taxonomy_menu module maintainer. Perhaps you should? I will be happy to contribute upto $50 as my share if he is willing to implement the pathauto API.

Christoph C. Cemper’s picture

I wrote JonBob - let's see it we can motivate him... assuming he's very busy with CCK

venkat-rk’s picture

Thanks for contacting him. I am keeping my fingers crossed.

doq’s picture

It could be (must say hardly it was:)) implemeted using custom_url_rewrite: you must change taxonomy/term/id links to their taxonomy_menu hierarchical equialents.

venkat-rk’s picture

That's an interesting suggestion. Thanks for sharing that. I am not a coder, but I am willing to try. Any pointers for where I should start?

peterx’s picture

<warning>There could be all sorts of problems with other modules if you implement this change. I am using only pathauto and taxonomy_menu. If you try this change and a demonic force takes away your Web site or your first born child or makes your ipod play Neil Diamond songs, that is your penance for experimenting with raw code.</warning>

Pathauto uses path_set_alias() and path_set_alias() contains the following code:

elseif($path_count == 1 && $alias_count == 1)
	{
	// This will delete the path that alias was originally pointing to:
	path_set_alias(NULL, $alias);
	path_set_alias($path);
	path_set_alias($path, $alias);
	}

pathauto creates one alias and taxonomy menu creates another. When you update a page you can end up with the pathauto alias returning a path count of 1 and the taxonomy_menu alias returning an alias count of 1. The code then deletes both entries before creating the new one, which is usually the pathauto entry.

To fix this problem you could change the url_alias table to contain the name of the module that creates an alias and limit modules to maintaining their own aliases.

Another fix would be to use the pid (path id) if supplied. Change the path_set_alias() code to process the pid before the other stuff. Pathauto supplies a pid when it wants to update pids. If the pid is supplied and the pid exists then update the pid.

I changed the start of path_set_alias() from:

function path_set_alias($path = NULL, $alias = NULL, $pid = NULL)
	{
	if ($path && !$alias)

to:

function path_set_alias($path = NULL, $alias = NULL, $pid = NULL)
	{
	if ($pid)
		{
		db_query("UPDATE {url_alias} SET dst = '%s', src = '%s' WHERE pid = %d", $alias, $path, $pid);
		drupal_clear_path_cache();
		return;
		}
	if ($path && !$alias)

That removed one incompatibility between pathauto and taxonomy_menu because pathauto no longer deletes taxonomy_menu entries when updating pathauth entries.

There is still a problem where pathauto will not create the right path for a new page. I get around it by creating the page then immediately updating it. For page x/y/z, pathauto creates path x/y/z_0 and I immediately update the URL to remove the _0.

petermoulding.com/web_architect

peterx’s picture

Test the following code as a pathauto API version of taxonomy_menu. Try placing the following in a file named pathauto_taxonomy_menu.inc within the modules/pathauto directory. You can then remove the path alias build out of taxonomy_menu and test the result. The second chunck of code is the replacement taxonomy_menu_menu() for taxonomy_menu.module.

Do not try this on any Web site that controls nuclear submarines or is connected to the Internet or is useful or is anything else.

pathauto_taxonomy_menu.inc

/* Copyright PeterMoulding.com 2006
Free for use in Drupal.
*/

/*
 * Implementation of hook_pathauto()
 */

function taxonomy_menu_pathauto($op)
	{
	switch ($op)
		{
		case 'settings':
			return taxonomy_menu_pathauto_settings();
		default:
			break;
		}
	}

function taxonomy_menu_pathauto_settings()
	{
	/* Copyright PeterMoulding.com 2006 04 07
	2/ Add use of variable taxonomy_menu_display_vocabulary.
	*/
	$use_vocabulary_name = false;
	if(variable_get('taxonomy_menu_display_vocabulary', 1))
		{
		$use_vocabulary_name = true;
		}
	
	$settings = array();
	$settings['module'] = 'taxonomy_menu';
	$settings['groupheader'] = t('Category menu path settings');
	$settings['patterndescr'] = t('Default menu path pattern (applies to all vocabularies with blank patterns below)');
	$settings['patterndefault'] = t('[vocab]/[catpath]');
	if($use_vocabulary_name)
		{
		$settings['patterndefault'] = t('[catpath]');
		}
	$settings['placeholders'] = array(
		t('[vocab]') => t("The vocabulary that the page's first category belongs to."),
		t('[cat]') => t('The name of the category.'),
		t('[catpath]') => t('As [cat], but including its supercategories.'),
		t('[tid]') => t('The id number of the category.')
		);
	// Look for extensions from other modules
	$placeholders = module_invoke_all('pathauto_taxonomy_menu', 'placeholders');
	$settings['placeholders'] = array_merge($settings['placeholders'], $placeholders);
	
	$settings['bulkname'] = t('Bulk update category menu paths');
	$settings['bulkdescr'] = 
	t('Generate menu aliases for all existing categories which do not already have aliases.');
	
	$vocabularies = taxonomy_get_vocabularies();
	if (sizeof($vocabularies) > 0)
		{
		$settings['patternitems'] = array();  
		foreach ($vocabularies as $vocabulary)
			{
			$vocabulary_name = $vocabulary->name;
			$fieldlabel = t('Pattern for all ' . $vocabulary_name . ' menu paths');
			$settings['patternitems'][$vocabulary->vid] = $fieldlabel;
			}
		}
	return (object) $settings;
	}

/**
 * Implementation of hook_taxonomy().
 */
function pathauto_taxonomy_menu($op, $type, $object = NULL)
	{
	switch ($type)
		{
		case 'term':
			pathauto_taxonomy_menu_term($op, $object);
			break;
		default:
			break;
		}
	}
function pathauto_taxonomy_menu_term($op, $object = NULL)
	{
	switch ($op)
		{
		case 'insert':
		case 'update':
			pathauto_taxonomy_menu_term_insert($op, $object);
			break;
		case 'delete':
			pathauto_taxonomy_menu_term_delete($object);
			break;
		default:
			break;
		}
	}
function pathauto_taxonomy_menu_term_delete($object = NULL)
	{
	/*
	** If the category is deleted, remove the path aliases
	**
	*/
	$category = (object) $object;
	path_set_alias('taxonomy_menu/' . $category->tid);
	}
function pathauto_taxonomy_menu_term_insert($op, $object = NULL)
	{
	//case 'insert':
	//case 'update':
	/*
	** Use the category info to automatically create an alias
	*/
	$category = (object) $object;
	if ($category->name)
		{
		$placeholders = array();
		
		$vid = $category->vid;
		$vocabulary = taxonomy_get_vocabulary($vid);
		$placeholders[t('[vocab]')] = pathauto_cleanstring($vocabulary->name);
		
		$placeholders[t('[cat]')] = pathauto_cleanstring($category->name);
		$placeholders[t('[tid]')] = $category->tid;
		
		if ($category->parent)
			{
			$catpath = pathauto_cleanstring($category->name);
			$parents = taxonomy_get_parents_all($category->parent);
			}
		else
			{
			$catpath = '';
			$parents = taxonomy_get_parents_all($category->tid);
			}
		
		foreach ($parents as $parent)
			{
			$catpath = pathauto_cleanstring($parent->name) . '/' . $catpath;
			}
		$placeholders[t('[catpath]')] = $catpath;
		
		// Append any additional extensions
		$extplaceholders = module_invoke_all('pathauto_taxonomy-menu', 'values', $category);
		$placeholders = array_merge($placeholders, $extplaceholders);
		
		$src = 'taxonomy_menu/' . $category->tid;
		$alias = pathauto_create_alias('taxonomy_menu', $op, $placeholders, $src, $vid);
		}
	}

// Generate menu aliases for all categories without aliases
function taxonomy_menu_pathauto_bulkupdate()
	{
	$query = 'select tid, vid, name, src, dst from {term_data} '.
		"left join {url_alias} on concat('taxonomy_menu/', tid) = src";
	$result = db_query($query);
	$count = 0;
	while($category = db_fetch_object($result))
		{
		$vid = $category->vid;
		$vocabulary = taxonomy_get_vocabulary($vid);
		$placeholders = array();
		$placeholders[t('[vocab]')] = pathauto_cleanstring($vocabulary->name);
		$placeholders[t('[cat]')] = pathauto_cleanstring($category->name);
		$placeholders[t('[tid]')] = $category->tid;
		$src_list = array();
		
		if ($category->parent)
			{
			$catpath = pathauto_cleanstring($category->name);
			$parents = taxonomy_get_parents_all($category->parent);
			}
		else
			{
			$catpath = '';
			$parents = taxonomy_get_parents_all($category->tid);
			}
		
		foreach ($parents as $parent)
			{
			$catpath = pathauto_cleanstring($parent->name) . '/' . $catpath;
			array_unshift($src_list, $parent->tid);
			}
		$placeholders['[catpath]'] = $catpath;
		
		array_unshift($src_list, $vid);
		$src = 'taxonomy_menu/' . implode('/', $src_list);
		if ($alias = pathauto_create_alias('taxonomy_menu', 'bulkupdate',
			$placeholders, $src, $vid))
			{
			$count++;
			}
		}
	
	drupal_set_message(format_plural($count,
		'Bulk update of terms completed, one menu alias generated.',
		'Bulk update of terms completed, %count menu aliases generated.'));
	}

 

taxonomy_menu.module

Replace taxonomy_menu_menu().

/* Copyright PeterMoulding.com 2005 09 09
1/ Fix formatting.
2/ Add use of variable taxonomy_menu_display_vocabulary.
*/
function taxonomy_menu_menu($may_cache)
	{
	$items = array();
	if ($may_cache)
		{
		$access = user_access('access content');
		
		/* Copyright PeterMoulding.com 2006 04 07
		2/ Add use of variable taxonomy_menu_display_vocabulary.
		*/
		$use_vocabulary_name = false;
		if(variable_get('taxonomy_menu_display_vocabulary', 1))
			{
			$use_vocabulary_name = true;
			}
		
		foreach (taxonomy_get_vocabularies() as $vocabulary)
			{
			if (variable_get('taxonomy_menu_show_'. $vocabulary->vid, 1))
				{
				$path = 'taxonomy_menu/'. $vocabulary->vid;
				/* Copyright PeterMoulding.com 2006 04 07
				2/ Add use of variable taxonomy_menu_display_vocabulary.
				$items[] = array('path' => $path, 'title' => t($vocabulary->name),
					'callback' => 'taxonomy_menu_page', 'access' => $access,
					'weight' => $vocabulary->weight);
				*/
				if($use_vocabulary_name)
					{
					$items[] = array('path' => $path, 'title' => t($vocabulary->name),
						'callback' => 'taxonomy_menu_page', 'access' => $access,
						'weight' => $vocabulary->weight);
					}
				
				$tree = taxonomy_get_tree($vocabulary->vid);
				$old_depth = -1;
				$old_path = $path;
				foreach ($tree as $term)
					{
					if ($term->depth <= $old_depth)
						{
						$slashes_to_remove = $old_depth - $term->depth + 1;
						for ($i = 0; $i < $slashes_to_remove; $i++)
							{
							$old_path = substr($old_path, 0, strrpos($old_path, '/'));
							}
						}
					
					$path = $old_path .'/'. $term->tid;
					$old_depth = $term->depth;
					$old_path = $path;
					
					/* Copyright PeterMoulding.com 2005 09 09
					2/ Add use of variable taxonomy_menu_display_vocabulary.
					$items[] = array('path' => $path, 'title' => t($term->name),
					'weight' => $term->weight);
					*/
					if($use_vocabulary_name or $term->depth > 0)
						{
						$items[] = array('path' => $path, 'title' => t($term->name),
							'weight' => $term->weight);
						}
					else
						{
						$items[] = array('path' => $path, 'title' => t($term->name),
							'callback' => 'taxonomy_menu_page',
							'access' => $access,
							'weight' => $term->weight);
						}
					}
				}
			}
		}
	return $items;
	}

petermoulding.com/web_architect

venkat-rk’s picture

Thank you peterx, for sharing this. I gave up on taxonomy_menu and now use the category module, but it is always good to have solutions for people who still use taxonomy.

Success’s picture

Are there any updates to this?

peterx’s picture

I am busy implemented other stuff for different sites. 4.7.0 seems to be frozen in preparation for 5.0.0 and I have not looked to see if there are any changes in this area for 5.0.0. If 5.0.0 changes path, pathauto or taxonomy_menu then I may wait for the 5.0.0 version before investing more time. Does anyone know what is happening with these modules in 5.0.0?

petermoulding.com/web_architect

peterx’s picture

See Allow manual specification of parent. It is the start of a change to make taxonomy menu work using the aliases from taxonomy+pathauto, the paths of the form taxonomy/term/99. I have the change working on a test system and will put it in a production system next week.

If you feel comfortable modifying includes/menu.inc then let me know and I will post the related changes for taxonomy_menu.

petermoulding.com/web_architect

icelink’s picture

I have made changes to the includes/menu.inc. Can you post the changes for taxonomy_menu. thanks

peterx’s picture

I changed taxonomy menu to work using the aliases from taxonomy+pathauto, the aliases of the form taxonomy/term/99.

  1. Remove modules/pathauto/pathauto_taxonomy_menu.inc
  2. Change includes/menu.inc
  3. Change modules/taxonomy.module
  4. Change modules/taxonomy_menu.module
  5. Change table drupal_menu
  6. Clean out table drupal_url_alias
  7. Rebuild paths using pathauto
  8. Clean out table drupal_cache

modules/pathauto/pathauto_taxonomy_menu.inc

If you are using modules/pathauto/pathauto_taxonomy_menu.inc, remove it because it attempts to make pathauto implemented paths structured for taxonomy menu. We want an unmodified pathauto to create unmodified paths for taxonomy so that taxonomy_menu can use taxonomy's paths.

includes/menu.inc

See Allow manual specification of parent, where you modify includes/menu.inc to accept a parent parameter so that you can submit a structured menu using the unstructured taxonomy path. This change does not affect normal operation of Drupal and can be implemented before the other chnages.

This change or a similar change will be incorporated in Drupal release 6.

modules/taxonomy.module

See function taxonomy_term_path($term) $items[] = array('path' => 'taxonomy/term' remove breadcrumb display, where you modify modules/taxonomy.module to not display a "taxonomy term" element in the breadcrumb. I have not tested the effect of this change without the subsequent changes to taxonomy_menu.

This change or a similar change could be made into an administration setting or could be implemented so that taxonomy_menu could request the change.

modules/taxonomy_menu.module

The following code changes function taxonomy_menu_menu($may_cache) to build a menu with links of the form taxonomy/term/nn with callbacks to taxonomy_menu.

/* Copyright PeterMoulding.com 2006 12 16. Free for use in Drupal.
1/ Fix formatting.
2/ Change to use URL aliases from taxonomy+pathauto by creating paths
   of the form taxonomy/term/nn and manually specifying the parent of
   each menu item. Requires modification to menu.inc.
*/
function taxonomy_menu_menu($may_cache)
	{
	$items = array();
	if ($may_cache)
		{
		$access = user_access('access content');
		foreach (taxonomy_get_vocabularies() as $vocabulary)
			{
			if (variable_get('taxonomy_menu_show_'. $vocabulary->vid, 1))
				{
				$parents = array();
				$tree = taxonomy_get_tree($vocabulary->vid);
				foreach ($tree as $term)
					{
					$parent = reset($term->parents);
					if($parent > 0)
						{
						$parents[$term->tid] = reset($term->parents);
						}
					$item = array();
					$item['path'] = 'taxonomy/term/' . $term->tid;
					$item['title'] = t($term->name);
					$item['weight'] = $term->weight;
					if(isset($parents[$term->tid]))
						{
						$item['parent'] = 'taxonomy/term/' . $parents[$term->tid];
						}
					
					if(!$use_vocabulary_name and $term->depth > 0)
						{
						$item['callback'] = 'taxonomy_menu_page';
						$item['access'] = $access;
						}
					$items[] = $item;
					}
				}
			}
		}
	return $items;
	}

At this point there are two things left to fix.

  • taxonomy_menu has a nodeapi function that needs a change to create the correct entries for new menu items.
  • "Read more" links to the term instead of the path.

drupal_menu

Change table drupal_menu to use taxonomy entries, of the form taxonomy/term/nn, instead of the taxonomy_menu specific entries. I have not yet worked out the SQL for this change. You need to find all the entries starting with taxonomy_menu, "path like 'taxonomy_menu%'", find the last term id after the last forward slash, then change the path to taxonomy/term/ followed by the term you extracted earlier. Your SQL would look something like the following SQL:

update `drupal_menu`
	set `path` = concat('taxonomy/term/', right(path, locate('/', reverse(path))))
	where path like 'taxonomy_menu/%'

drupal_url_alias

Clean out table drupal_url_alias using phpMyAdmin or SQL similar to delete from drupal_url_alias where src like 'taxonomy_menu%'. This removes the old taxonomy_menu entries.

Rebuild paths using pathauto

Rebuild the aliases using pathauto. Go to admin > settings > pathauto. Bulk update category paths then bulk update user paths then bulk update node paths. I emptied the alias table then ran the three bulk updates in the order category, user, then node. You may not be able to empty the table if you have other modules building aliases.

drupal_cache

Clean out table drupal_cache using phpMyAdmin or SQL similar to truncate table drupal_cache. This removes all the menu entries so that they will be rebuilt.

petermoulding.com/web_architect

icelink’s picture

Works Great!

ira42’s picture

Hey there, this seems to be a great solution for the problem I've been having.

(I almost had to scrap Drupal all together because my clients really needed to use taxonomy_menu to drive the main nav for the site, but also needed proper, readable urls.)

So, I've implemented the changes above, and the urls are working really well (/vocab/term/title). The problem is that now my taxonomy_menu module is no longer showing up in the admin/module listing! Could it be that the fix above is only for version 4.x.x or something? I'm using the latest version of Drupal and taxonomy_menu, any ideas?

Should this work for version 5.x.x?

Thanks in advance,

Ira

gatta’s picture

I had the same problem until I fixed the taxonomy_menu.module. The part containing 'path' => 'admin/settings/taxonomy_menu' etc. is missing.

function taxonomy_menu_menu($may_cache) {
  $items = array();

  if ($may_cache) {
   $items[]= array (
      'path' => 'admin/settings/taxonomy_menu',
      'title' => t('Taxonomy Menu settings'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array('taxonomy_menu_admin_settings'),
      'access' => user_access('administer site configuration'),
      'description' => t('Global configuration of taxonomy menu functionality.'),
      'type' => MENU_NORMAL_ITEM,
    );

        $access = user_access('access content');
        foreach (taxonomy_get_vocabularies() as $vocabulary)
            {
            if (variable_get('taxonomy_menu_show_'. $vocabulary->vid, 1))
                {
                $parents = array();
                $tree = taxonomy_get_tree($vocabulary->vid);
                foreach ($tree as $term)
                    {
                    $parent = reset($term->parents);
                    if($parent > 0)
                        {
                        $parents[$term->tid] = reset($term->parents);
                        }
                    $item = array();
                    $item['path'] = 'taxonomy/term/' . $term->tid;
                    $item['title'] = t($term->name);
                    $item['weight'] = $term->weight;
                    if(isset($parents[$term->tid]))
                        {
                        $item['parent'] = 'taxonomy/term/' . $parents[$term->tid];
                        }
                   
                    if(!$use_vocabulary_name and $term->depth > 0)
                        {
                        $item['callback'] = 'taxonomy_menu_page';
                        $item['access'] = $access;
                        }
                    $items[] = $item;
        }
      }
    }
  }

  return $items;
}
executex’s picture

Now, I do know php, and I did what you did, and it didn't change anything in my site. What was the point of all that work?

PATHAUTO needs to change all taxonomy_menu/1/2 etc to node/vocab-term/tutorial etc
But it didn't change taxonomy_menu at all.

peterx’s picture

Taxonomy_menu creates a menu from taxonomy.
Taxonomy generates URLs in the form taxonomy/term/23.
Pathauto converts taxonomy/term/23 using the pathauto_taxonomy.inc extension to Pathauto using code including the following line:
path_set_alias('taxonomy/term/'.$category->tid);
In Admin, Site configuration, Pathauto, Category path settings, I have Default path pattern set to [catpath]

You could change the code to generate node/something. You could look at where I changed code and change the changes to generate node/something or node/1/2 and let Pathauto reformat node/1/2 to node/something.

petermoulding.com/web_architect

executex’s picture

I'm an experienced PHP developer, although I'm a bit unfamiliar with Drupal modules. I didn't understand what you are talking about.
So are you suggesting I do:
path_set_alias('taxonomy_menu/1/2'.$category->tid);
That wouldn't really make any sense.
Isn't there a loop I can do so that pathauto generates paths for all taxonomy_menu stuff to the correct taxonomy values that pathauto already generated?

Taxonomy_menu certainly does not create paths according to taxonomy... they seem like two irrelevant modules.
Taxonomy_menu makes paths as: taxonomy_menu/1/2 [taxonomy_menu]/[vocab]/[term]...
Now how can I add another option in pathauto admin, so that it changes those paths too?

executex’s picture

Ok, I edited taxonomy_menu_menu, but it didn't work at all. Mainly kept replacing wrong things, or the links wouldn't match up. And this is kind of a dirty fix. Is there a way to get pathauto to just change taxonomy_menu/1/2 directly to [vocab]/[term]?

I tried this for taxonomy_menu_menu:

foreach (taxonomy_get_vocabularies() as $vocabulary) {
      if (variable_get('taxonomy_menu_show_'. $vocabulary->vid, 1)) {
        /*$path = 'taxonomy_menu/'. strtolower($vocabulary->name);*/
				$path = 'taxonomy_menu/'. $vocabulary->tid);
        $items[] = array('path' => $path, 'title' => t($vocabulary->name),
          'callback' => 'taxonomy_menu_page', 'access' => $access,
          'weight' => $vocabulary->weight);

        $tree = taxonomy_get_tree($vocabulary->vid);
        $old_depth = -1;
        $old_path = $path;

        foreach ($tree as $term) {
          if ($term->depth <= $old_depth) {
            $slashes_to_remove = $old_depth - $term->depth + 1;
            for ($i = 0; $i < $slashes_to_remove; $i++) {
              $old_path = substr($old_path, 0, strrpos($old_path, '/'));
            }
          }
					/*$term->name = str_replace($term->name, " ", "-");
					$term->name = str_replace($term->name, array('a','an','as','at','before','but','by','for','from','is','in','into','like',
					'of','off','on','onto','per','since','than','the','this','that','to','up','via','with'), array());
					$old_path = str_replace($old_path, "taxonomy_menu/", "");*/
          /*$path = $old_path .'/'. strtolower($term->name);*/
					$path = $old_path .'/'. $term->tid;
          $old_depth = $term->depth;
          $old_path = $path;
          $items[] = array('path' => $path, 'title' => t($term->name),
            'weight' => $term->weight);
        }
      }
    }
gatta’s picture

I followed your solution and it's been working great. Just a couple of points:
In the step where we update the drupal_menu table, I think the SQL you provided will produce taxonomy/term//nn instead of taxonomy/term/nn
I did it like this:

update `drupal_menu`
set `path` = concat('taxonomy/term', right(path, locate('/', reverse(path))))
where path like 'taxonomy_menu/%'

In taxonomy_menu.module, I've to add this in function taxonomy_menu_menu($may_cache), in order to have Taxonomy Menu settings under Site Configuration.

  if ($may_cache) {
   $items[]= array (
      'path' => 'admin/settings/taxonomy_menu',
      'title' => t('Taxonomy Menu settings'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array('taxonomy_menu_admin_settings'),
      'access' => user_access('administer site configuration'),
      'description' => t('Global configuration of taxonomy menu functionality.'),
      'type' => MENU_NORMAL_ITEM,
    );

I also have the same problems as described in http://drupal.org/node/41450#comment-169715 where a new category term is created with <root> as the parent, I can't edit its menu item as the menu number is a negative number, and it's not added to the menu table either.
It'll be greatly appreciated if you can provide some insights. Thanks.

beatnikdude’s picture

I have also implemented the changes listed by peterx, along with the caveats listed by gatta and it is working for me.
Thanks!
Note: I assume that you can skip step #3 if you don't care about what the breadcrumbs were doing by default.

tille’s picture

sorry for cross-posting (also here http://drupal.org/node/121513) but i'm currently deprerately trying to get this work on a dp 5.. - ..withouth great success..:|
..actually i do get this far that i get nice url aliasses - but then some other hell seems to break loose: the menu collapses (no more hirachy for the once oh-so-nicely arranged taxonomy-menu-tree) and the related menu items are neither editable nor movable in the admin..

so here's onle again what i encountered so far:

• getting very nice url-aliasses after bulk url generation trough pathauto.. - ..hurray..:]
• but the menu kind of exploded - instead of heavin a hirachy in a seperate menu its all on 'top level' in the main navi-menu..
• getting negative id-numbers in the admin area
• cant modify nor delete nor do whatever to the dynamically created menu items

..does anyone know of a 1-2-3-instruction on how to do this on drupal 5..?

..thank you very much, greetz, till..

___________________________

tille’s picture

..I was just thinking this whole 'problem' over - and coudn't come up with an answer to the question WHY taxonomy_menu ist actually generating these URLs at all..?!¿

In other words: my question would be: Why does taxonomy_menu generate URLs like "taxonomy_menu/2/27" and not like "taxonomy/term/27"....? In my opinion this would/could makes things a lot easier - since it could cooperate nicely with the pathauto-aliases.. - ..or am I terribly wrong....?

thanks, greetz, till..

___________________________

executex’s picture

The only possible reason I can find logically for the developers to that (if they're not stupid), is that they're really really lazy. Now I have to figure out PathAuto AND taxonomy_menu, to create these dynamic URLs, and I have to waste hours of my own time to figure out how to get this:

taxonomy_menu/2/24

TO

Tutorials/PHP/how-to-use-curl

Which is how my taxonomy module shows because of pathauto.

Btw, I STILL have not had the time to fully figure this out :'(... helpz!

tille’s picture

I actually just switched to the module called Category -> http://drupal.org/project/category which seems to be quite complex - but as far as I can see it does everything I ever dreamed of..:] ..well at least the menu is now working perfectly fine - with nice urls (through pathauto) and then I will probably also be able to have nice 'category views' instead of 'taxonomy lists' ..if you know what I mean..? ..well - I'll still have to figure that out - but so far I'm quite optimistic about everything..:]

anyways - I first somehow ignored that module completely - probably because of its name beeing so close to its function that I thought it cant actually be a module of its own - but it is - and it seems to work fine..:]

switching is a bit of a stress - since you'll have to import all the taxonomy terms - and then mdify the modifications and set the settings - but I have at least the feeling that I'm way more pleased by what it offers than by what I got from taxonoy+menu..

greetz, till..

___________________________
my pictures: www.bilderbook.org

___________________________

summit’s picture

Hi,

I have just the opposite experience.
I used the category module. And it was fine with only a couple of nodes.
Now I have hunderds of nodes and the module becomes very..very slow. I don't know why exactly, but it is the fact.
next to the fact that the category module doesn't support taxonomy batch operations (for drupal 4.7) and taxonomy super select, and other taxonomy related modules.

These reasons made me switch back to taxonomy.
It is working fine, except the menu items. The menu items for the categories are nodes because of the category module.
Is there a way to automatically change the menu items to the right taxonomy/term syntax?

Update: I use the .htaccess hack which is stated here: http://drupal.org/node/121513. It works great! The url_aliases are now placed in the url.

greetings,
Martijn
www.best-information.eu

Junesun’s picture

I have to warn everybody NOT to use the Category module as it screwed up everything for me. The entire hierarchy got lost and all elements showed up on the same level (they used to be nested). Also, there appear to be issues with translated taxonomies. Then, the Category module upon first use claims to create backups, but nobody can tell me where they are or how to revert all the changes that it made to my database. IF you still want to give it a try, definitely make a full backup of your entire database right before adding this, and also check twice to see if the backup isn't corrupted. Chances are very good that you'll need it.

najibx’s picture

yes, I follow the steps and stuck at your stage. What the real solution here? Maybe other taxonomy menu modules could solve this?

• getting very nice url-aliasses after bulk url generation trough pathauto.
• but the menu kind of exploded - instead of heavin a hirachy in a seperate menu its all on 'top level' in the main navi-menu..
• getting negative id-numbers in the admin area
• cant modify nor delete nor do whatever to the dynamically created menu items

-najibx-

jiangxijay’s picture

Subscribe.

tille’s picture

after trying out various modules/approaches (http://drupal.org/node/170752) I temporarily gave up the idea of having a dynamically updated menu trees generated by my toxonomies - at least for this one project I'm currently working on.. Instead I'll have 'hand-made' taxo-menues..

Anyways - the problem remains the same..

I tried to start a discussion on "what's your dynamic menu approach" over here: http://drupal.org/node/171535
and I tried to write down my experiences and wishes over here: http://drupal.org/node/170752
..but both with very little response.
Instead I received a notification about a new module tax'o'menu: http://drupal.org/project/taxomenu
..but I actually haven't found the time to digg into it - yet.

Has anybody tried it out..? ..or even other/better experiences..?

greetz, t..

___________________________
my pictures: www.bilderbook.org

___________________________

jiangxijay’s picture

This is of great interest to me, too, as I am building a large prototype for higher education.

I am seeking the optimal threads and groups for the discussion ...

najibx’s picture

have you tried Taxonomy context

I have used it replacing taxonomy_menu. I meet my requirement. In think yours too.

-najibx-

peterx’s picture

Is there a public site where we can see your use of taxonomy context in use?

petermoulding.com/web_architect

najibx’s picture

Hi Peter,

Remember me ....I had problem using taxonomy_menu earlier. Now it's solved via taxonomy_context. it's easy to get it running. You see it does more than providing taxonomy menu in blocks. I don't have it up and running yet on public domain. only local server.

- displaying the title and description of the current term. optionally.
- you can choose to list "nodes title within the term" in menu blocksor simply the term.
- "breadcrumb" trail of the current taxonomy term and any parent terms. So do not need taxonomy_breadcrumb now.
- titles and descriptions of any sub-terms of the current term. So no need taxonomy_list or taxonomy directory
- includes a context-sensitive menu block for each vocabulary. so you set whenever you wish.

http://drupal.org/project/taxonomy_context

-najibx-

Caleb G2’s picture

but it's not a total replacement for taxonomy_menu. Getting a block listing of taxonomy items is not a substitute for having the menu items actually show up at admin/build/menu for certain things.

=====
HigherVisibility

Junesun’s picture

I have now switched to Taxonomy_context because I need nice-looking URLs. Even though there appears to be no "stable" version around, the 5.1 "dev" version works fine for me - quite in contrast to the 5.2 "stable" version of taxonomy_menu, which screwed up everything. After contacting the author, he said he knows of the problems many people have been having and recommended staying with the latest stable 5.1 release, which is only available by going through the complete list of releases.

If you want to see taxonomy_context in action, feel free to browse my site http://www.esperanto.info - it wasn't made for the purpose of demoing this module, but it uses it.

P. S.: By the way, you can use either taxonomy_menu or taxonomy_context for multilingual menus if you change the Translation module as described at http://drupal.org/node/108070 .

bobject’s picture

> http://www.esperanto.info

It's darn confusing all these taxonomy modules... I guess it's a luxury problem :-)

I tried t_c and I like it. What I miss is a real menu and the breadcrumbs on the nodes...

so I guess I'm still searching

______________________
"When the sheep hits the fan... who you're gonna call?"

H3rnand3z’s picture

subscribing

bgoines78’s picture

Apparently, I overlooked the efforts of another user and have my own version of taxonomy_menu with pathauto support. The code below is a complete replacement for taxonomy_menu.module. This module will create the appropriate URL aliases for the taxonomy_menu/* URLs as well as appropriate aliases for taxonony/term/*/feed. Unfortunately, there may be some overlap in feed aliases should you choose to create aliases for taxonomy terms as well. Given the fact that I have only known of Drupal for less than a week now, please use the following code with caution and be sure to backup your URL aliases.

<?php
// $Id: taxonomy_menu.module,v 1.4 2007/10/01 23:00:01 sinis Exp $

/**
 * Implementation of hook_help().
 */
 function taxonomy_menu_help($section) {
     switch ($section) {
         case 'admin/help#taxonomy_menu':
             $output = '<p>'. t('Taxonomy terms allow classification of content into categories and subcategories.  The taxonomy menu module adds links to the navigation menu for taxonomy terms.  This is useful when the community is focused on creating content that is organized in a taxonomy.') .'</p>';
             $output .= '<p>'. t('The taxonomy menu administration interface allows taxonomy terms to be enabled to show in the navigation menu.  You can also select whether a term\'s descendents subterms are displayed.') .'</p>';
             $output .= t('<p>You can</p>
<ul>
<li>view a list of taxonomies in <a href="@admin-taxonomy">Administer &gt;&gt; Content management &gt;&gt; Categories</a>.</li>
<li>create a new vocabulary at <a href="@admin-taxonomy-add-vocabulary">Administer &gt;&gt; Content management &gt;&gt; Categories &gt;&gt; Add vocabulary</a>.</li>
</ul>', array('@admin-taxonomy' => url('admin/content/taxonomy'), '@admin-taxonomy-add-vocabulary' => url('admin/content/taxonomy/add/vocabulary')));
             $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@taxonomy_menu">Taxonomy menu page</a>.', array('@taxonomy_menu' => 'http://www.drupal.org/handbook/modules/taxonomy_menu/')) .'</p>';
             return $output;
     }
 }

 /**
  * Implementation of hook_menu().
  *
  * Most of the heavy lifting of the module is done here.
  */
  function taxonomy_menu_menu($may_cache) {
      $items = array();

      if ($may_cache) {
          $items[]= array (
          'path' => 'admin/settings/taxonomy_menu',
          'title' => t('Taxonomy Menu settings'),
          'callback' => 'drupal_get_form',
          'callback arguments' => array('taxonomy_menu_admin_settings'),
          'access' => user_access('administer site configuration'),
          'description' => t('Global configuration of taxonomy menu functionality.'),
          'type' => MENU_NORMAL_ITEM,
          );

          $access = user_access('access content');

          foreach (taxonomy_get_vocabularies() as $vocabulary) {
              if (variable_get('taxonomy_menu_show_'. $vocabulary->vid, 1)) {
                  $path = 'taxonomy_menu/'. $vocabulary->vid;
                  $items[] = array(
                  'path' => $path,
                  'title' => t($vocabulary->name),
                  'callback' => 'taxonomy_menu_page',
                  'access' => $access,
                  'weight' => $vocabulary->weight
                  );

                  $tree = taxonomy_get_tree($vocabulary->vid);
                  $old_depth = -1;
                  $old_path = $path;

                  foreach ($tree as $term) {
                      if ($term->depth <= $old_depth) {
                          $slashes_to_remove = $old_depth - $term->depth + 1;
                          for ($i = 0; $i < $slashes_to_remove; $i++) {
                              $old_path = substr($old_path, 0, strrpos($old_path, '/'));
                          }
                      }
                      $path = $old_path .'/'. $term->tid;
                      $old_depth = $term->depth;
                      $old_path = $path;
                      $items[] = array(
                      'path' => $path,
                      'title' => t($term->name),
                      'weight' => $term->weight
                      );
                  }
              }
          }
      }

      return $items;
  }

  /**
   * Implementation of hook_taxonomy().
   *
   * Invalidates the menu cache on taxonomy changes.
   */
   function taxonomy_menu_taxonomy($op, $type, $object = NULL) {
       if(module_exists('pathauto')) {
           _pathauto_include();

           switch ($type) {
               case 'term':
                   $category = (object) $object;
                   $vocabulary = taxonomy_get_vocabulary($category->vid);

                   $parents = taxonomy_get_parents_all($category->tid);
                   $path = $category->tid;
                   foreach ($parents as $parent) {
                       if( $category->tid != $parent->tid) { // Skip ourselves
                           // Replace any / characters in individual terms which might create confusing URLs
                           $separator = variable_get('pathauto_separator', '-');
                           $path = $parent->tid .'/'. $path;
                       }
                   }
                   $path = 'taxonomy_menu/' . $vocabulary->vid . '/' . $path;

                   switch ($op) {
                       case 'insert':
                       case 'update':
                           $placeholders = pathauto_get_placeholders('taxonomy_menu', $category);

                           /*
                            ** Use the category info to automatically create an alias
                            */

                            if ($category->name) {
                                $alias = pathauto_create_alias('taxonomy_menu', 'update', $placeholders, $path, null);

                                # Fixup to point the feeds at the taxonomy module rather than here
                                if( variable_get('pathauto_taxonomy_menu_supportsfeeds', '') ) {
                                    $feed = (variable_get('taxonomy_menu_display_descendants', 1) ? 'all' : 0) .'/feed';
                                    path_set_alias('taxonomy/term/' . $term->tid . '/' . $feed, $alias . '/' . $feed);
                                }

                            }
                            break;
                       case 'delete':
                           $feed = (variable_get('taxonomy_menu_display_descendants', 1) ? 'all' : 0) .'/feed';
                           //If the category is deleted, remove the path aliases
                           path_set_alias($path);
                           path_set_alias($path . $feed);
                           break;
                       default:
                           break;
                   }
                   break;

                       case 'vocabulary':
                           $vid = $object['vid'];
                           $name = $object['name'];
                           switch ($op) {
                               case 'insert':
                               case 'update':
                                   $path = 'taxonomy_menu/' . $vid;
                                   $placeholders = array(
                                   'tokens' => array(
                                   '[taxonomy_menu_catpath]',
                                   '[taxonomy_menu_catalias]',
                                   '[taxonomy_menu_vocab]',
                                   '[taxonomy_menu_cat]',
                                   ), 'values' => array(
                                   '',
                                   '',
                                   $name,
                                   '',
                                   ),
                                   );
                                   pathauto_create_alias('taxonomy_menu', 'update', $placeholders, $path, null);
                                   break;
                               case 'delete':
                                   $feed = (variable_get('taxonomy_menu_display_descendants', 1) ? 'all' : 0) .'/feed';
                                   // First, we must recursively delete aliases for terms
                                   $tree = taxonomy_get_tree($vid);
                                   $old_depth = -1;
                                   $old_path = 'taxonomy_menu/' . $vid;

                                   foreach ($tree as $term) {
                                       if ($term->depth <= $old_depth) {
                                           $slashes_to_remove = $old_depth - $term->depth + 1;
                                           for ($i = 0; $i < $slashes_to_remove; $i++) {
                                               $old_path = substr($old_path, 0, strrpos($old_path, "/"));
                                           }
                                       }
                                       $path = $old_path .'/'. $term->tid;
                                       $old_depth = $term->depth;
                                       $old_path = $path;
                                       
                                       path_set_alias($path);
                                       path_set_alias($path . $feed);
                                   }

                                   // Now remove the vocabulary aliases
                                   path_set_alias('taxonomy_menu/'. $vid);
                                   path_set_alias('taxonomy_menu/'. $vid . $feed);
                                   break;
                               default:
                                   break;
                           }
                               default:
                                   break;
           }
       }

       menu_rebuild();
   }

   /**
    * Menu callback; manage settings for taxonomy menu.
    */
    function taxonomy_menu_admin_settings() {
        $form['taxonomy_menu_display_descendants'] = array(
        '#type' => 'checkbox',
        '#title' => t('Display descendants'),
        '#return_value' => 1,
        '#default_value' => variable_get('taxonomy_menu_display_descendants', 1),
        '#description' => t('If checked, then when a term is selected all nodes belonging to subterms are also displayed.'),
        );
         
        foreach (taxonomy_get_vocabularies() as $vocabulary) {
            $form['taxonomy_menu_show_' . $vocabulary->vid] = array(
            '#type' => 'checkbox',
            '#title' => t('Show "%vocab" in menu', array('%vocab' => t($vocabulary->name))),
            '#return_value' => 1,
            '#default_value' => variable_get('taxonomy_menu_show_' . $vocabulary->vid, 1),
            );
        }

        return system_settings_form($form);
    }

    /**
     * Page callback that renders a node listing for the selected term.
     */
     function taxonomy_menu_page() {
         if (arg(2)) {
             $arguments = explode('/', $_GET['q']);
             $main_tid = db_escape_string(array_pop($arguments));

             $feed = url('taxonomy/term/'. $main_tid .'/'. (variable_get('taxonomy_menu_display_descendants', 1) ? 'all' : 0) .'/feed');
             drupal_add_feed($feed);

             $result = taxonomy_select_nodes(array($main_tid), 'or', variable_get('taxonomy_menu_display_descendants', 1) ? 'all' : 0);
         }
         else {
             // If no arg(2), we're looking at just the vid. If display_descendants
             // is on, grab all terms regardless of depth. If off, grab depth 0 terms.
             $tree = taxonomy_get_tree(arg(1));
             $descendants = variable_get('taxonomy_menu_display_descendants', 1);
             foreach ($tree as $term) {
                 if ($descendants || $term->depth == 0) {
                     $tids[] = $term->tid;
                 }
             }

             // The requested terms have already been determined, so don't request
             // descendants here.
             $result = taxonomy_select_nodes($tids, 'or', 0);
         }


         return taxonomy_render_nodes($result);
     }

     /**
      * Implementation of hook_nodeapi().
      *
      * This hook enables the menu to be displayed in context during node views.
      */
      function taxonomy_menu_nodeapi(&$node, $op, $a3, $a4) {
          switch ($op) {
              case 'view':
                  if ($a4 == TRUE) {
                      // The node is being displayed on its own page.
                      foreach (taxonomy_get_vocabularies() as $vocabulary) {
                          if (variable_get('taxonomy_menu_show_'. $vocabulary->vid, 1)) {
                              $path = 'taxonomy_menu/' . $vocabulary->vid;

                              $tree = taxonomy_get_tree($vocabulary->vid);
                              $old_depth = -1;
                              $old_path = $path;

                              foreach ($tree as $term) {
                                  if ($term->depth <= $old_depth) {
                                      $slashes_to_remove = $old_depth - $term->depth + 1;
                                      for ($i = 0; $i < $slashes_to_remove; $i++) {
                                          $old_path = substr($old_path, 0, strrpos($old_path, "/"));
                                      }
                                  }
                                  $path = $old_path .'/'. $term->tid;
                                  $old_depth = $term->depth;
                                  $old_path = $path;
                                  if (in_array($term->tid, array_keys(taxonomy_node_get_terms($node->nid)))) {
                                      menu_set_location(array(array('path' => $path, 'title' => t($term->name)), array('path' => 'node/'. $node->nid, 'title' => $node->title)));
                                      // Quit after the first match.
                                      return;
                                  }
                              }
                          }
                      }
                  }
                  break;
          }
      }

      /**
       * Implementation of hook_token_values() for Pathauto specific tokens
       */
       function taxonomy_menu_token_values($type, $category = NULL) {

           if($type == 'taxonomy_menu') {
               $parents = taxonomy_get_parents_all($category->tid);
               $menupath = $category->tid;
               foreach ($parents as $parent) {
                   // Replace any / characters in individual terms which might create confusing URLs
                   $separator = variable_get('pathauto_separator', '-');
                   $catpath = preg_replace('/\//', '', $parent->name) .'/'. $catpath;
                   $menupath = $category->tid . '/' . $menupath;
               }
               $values['taxonomy_menu_catpath'] = $catpath;
               $menupath = $category->vid . '/' . $menupath;

               $vocabulary = taxonomy_get_vocabulary($category->vid);
               $values['taxonomy_menu_vocab'] = $vocabulary->name;

               $values['taxonomy_menu_cat'] = $category->name;

               $values['taxonomy_menu_catalias'] = drupal_get_path_alias('taxonomy_menu/' . $menupath);
               if (!strncasecmp($values['taxonomy_menu_catalias'], 'taxonomy_menu', 13)) {
                   $values['taxonomy_menu_catalias'] = $values['taxonomy_menu_cat'];
               }
           }

           return $values;
       }

       /**
        * Implementation of hook_token_list() for Pathauto specific tokens
        */
        function taxonomy_menu_token_list($type = 'all') {
            if ($type == 'taxonomy_menu' || $type == 'all') {
                $tokens['taxonomy_menu']['taxonomy_menu_catpath'] = t("This category including its supercategories separated by /.");
                $tokens['taxonomy_menu']['taxonomy_menu_catalias'] = t("URL alias for the category.");
                $tokens['taxonomy_menu']['taxonomy_menu_vocab'] = t('The first vocabulary name returned for this category.');
                $tokens['taxonomy_menu']['taxonomy_menu_cat'] = t('The current category.');
            }

            return $tokens;
        }

        /*
         * Implementation of hook_pathauto()
         */

         function taxonomy_menu_pathauto($op) {
             switch ($op) {
                 case 'settings':
                     $settings = array();
                     $settings['module'] = 'taxonomy_menu';
                     $settings['groupheader'] = t('Taxonomy menu path settings');
                     $settings['patterndescr'] = t('Default path pattern');
                     $settings['patterndefault'] = t('');
                     $patterns = token_get_list('taxonomy_menu');
                     $settings['placeholders'] = array();
                     foreach ($patterns as $type => $pattern_set) {
                         if ($type != 'global') {
                             foreach ($pattern_set as $pattern => $description) {
                                 $settings['placeholders'][t('['. $pattern .']')] = t($description);
                             }
                         }
                     }

                     $settings['supportsfeeds'] = (variable_get('taxonomy_menu_display_descendants', 1) ? 'all' : 0) .'/feed';
                     $settings['bulkname'] = t('Bulk generate aliases for categories that are not aliased');
                     $settings['bulkdescr'] = t('Generate aliases for all existing categories which do not already have aliases. Note: Bulk Update may not complete on large or slow sites. See the README.txt for more information.');

                     $vocabularies = taxonomy_get_vocabularies();
                     if (sizeof($vocabularies) > 0) {
                         $settings['patternitems'] = array();
                         foreach ($vocabularies as $vocab) {
                             $vocabname = $vocab->name;
                             $fieldlabel = t('Pattern for all %vocab-name paths', array('%vocab-name' => $vocabname));
                             $settings['patternitems'][$vocab->vid] = $fieldlabel;
                         }
                     }

                     return (object) $settings;
                 default:
                     break;
             }
         }

         /**
          * Generate aliases for all categories without aliases
          *
          */
          function taxonomy_menu_pathauto_bulkupdate() {
              $count = 0;

              foreach (taxonomy_get_vocabularies() as $vocabulary) {
                  if (variable_get('taxonomy_menu_show_'. $vocabulary->vid, 1)) {
                      $path = 'taxonomy_menu/' . $vocabulary->vid;
                      $placeholders = array(
                      'tokens' => array(
                      '[taxonomy_menu_catpath]',
                      '[taxonomy_menu_catalias]',
                      '[taxonomy_menu_vocab]',
                      '[taxonomy_menu_cat]',
                      ), 'values' => array(
                      '',
                      '',
                      $vocabulary->name,
                      '',
                      ),
                      );
                      pathauto_create_alias('taxonomy_menu', 'bulkupdate', $placeholders, $path, null);
                      $count++;

                      $tree = taxonomy_get_tree($vocabulary->vid);
                      $old_depth = -1;
                      $old_path = $path;

                      foreach ($tree as $term) {
                          if ($term->depth <= $old_depth) {
                              $slashes_to_remove = $old_depth - $term->depth + 1;
                              for ($i = 0; $i < $slashes_to_remove; $i++) {
                                  $old_path = substr($old_path, 0, strrpos($old_path, "/"));
                              }
                          }
                          $path = $old_path .'/'. $term->tid;
                          $old_depth = $term->depth;
                          $old_path = $path;
                          $placeholders = pathauto_get_placeholders('taxonomy_menu', $term);
                          $alias = pathauto_create_alias('taxonomy_menu', 'bulkupdate', $placeholders, $path, null);

                          # Fixup to point the feeds at the taxonomy module rather than here
                          if( variable_get('pathauto_taxonomy_menu_supportsfeeds', '') ) {
                              $feed = (variable_get('taxonomy_menu_display_descendants', 1) ? 'all' : 0) .'/feed';
                              path_set_alias('taxonomy/term/' . $term->tid . '/' . $feed, $alias . '/' . $feed);
                          }
                          $count++;
                      }
                  }
              }

              drupal_set_message(format_plural($count,
              "Bulk generation of terms completed, one alias generated.",
              "Bulk generation of terms completed, @count aliases generated.")
              );

          }
bgoines78’s picture

Just a heads up, there appears to be a problem in the above code where feed aliases are not create properly. I think I have a fix, but I am still trying to understand the feed a little better, specifically to how they relate to views. For now, it is not safe to enable "Create feed aliases" for the Taxonomy menu administrative pathauto options.

mhuebl’s picture

It seems, that this snippet saves my christmas-holiday :-)
Thanks a lot bgoines.

xpi’s picture

i think i miss something.
You are using the token [taxonomy_menu_cat] which is not valid within the scope of tokens where you are using it.

What does that mean ?

Thanks.

zet’s picture

Hello Seems that this code is working well, but no raw input
Can bgoines78 or someoane else edit this code to allow raw input too ?

default path pattern [taxonomy_menu_vocab]/[taxonomy_menu_catpath] ( i think the only combination that display's good paths for BOTH secondary links as well as for primary links)

Regarding characters in path the default path pattern above is working well ONLY for secondary links (eg: http://chic.zetnet.ro/moda/ce-mai-nou)

But for the primary links it gives me :
http://chic.zetnet.ro/mod%C4%83
category "modă"(-romanian word-; en: fashion) is replaced by mod%C4%83 in URL instead of moda

See example at:
http://chic.zetnet.ro/mod%C4%83

EDITED:
in the mean time I manualy edited the primary links from the generated URL aliases list

zet’s picture

Can you make this for autopath taxonomy menu compatible with drupal 6 ?

Mguel’s picture

Subscribing

mioan’s picture

I am new (1 week) to drupal
I created a new site.
Just before inviting the search engines in, I want to solve the duplicate links created by the taxonomy menu.

The taxonomy menu produces links like
http://www.24hsoftware.com/taxonomy_menu/2/28
while the same category is at
http://www.24hsoftware.com/taxonomy/term/28

Here is a different idea:
How about putting the
/taxonomy_menu/*
in the robots.txt

search engines will not find it as duplicate content while other site links could give an entry point for the spiders in the categories.

What do you think?

Michael

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
www.24Hsoftware.com

EmanueleQuinto’s picture

Ok I read all articles and spent some time thinking about this in the morning.

The problems seems coming from the fact that menu needs a proper url /taxonomy_menu/1/3 in order to use the function taxonomy_menu_page. That's fine.

But we all need also to use the alias with category/vocabulary_1/term_3 aliased to taxonomy/term/3.

bgoines78 rewrote part of the module recreating aliases with pathauto but what about leveraging work already done by pathauto simply checking if a path for a taxonomy term already exist?

Mi 2 eurocent suggestion is then to check if the alias exist then change the 'src' leaving all the rest. Just add the if line on menu definition as follows:

$path = $old_path .'/'. $term->tid;
if($alias = drupal_lookup_path('alias','taxonomy/term/' . $term->tid)) path_set_alias($path, $alias);
$old_depth = $term->depth;

Checked on my site and seems working. I didn't check for feed or everything else.

Hope this work.

ema

P.S.
Works for Drupal 5 - taxonomy_menu.module,v 1.17.2.1.2.1 2007/02/22

Un'altra Pavia e' possibile
www.kronstadt.it - www.mupa.it

mpaler’s picture

One more vote for changing the default path of taxonomy menu to taxonomy/term/id. This would simplify life SOOOO much and make the module so much more flexible out the box. It's a true pain in the hack to ass this module with all the code so generously supplied in this thread.

FWIW, I gave taxonomy context a go and was able to create a vocabulary/taxonomy menu with aliased urls in literally about 5 minutes.

Oh...and another thing. Taxonomy context menu items visiblity can be controlled with TAC Lite.

summit’s picture

+1 I second that!
Please make the path change to taxonomy/term/id.
greetings,
Martijn

ferrangil’s picture

Yea! Use taxonomy/term/id will be greaaat!!! Please do it :)

featherbelly’s picture

Hi Emanuele,

Just to say - that worked for me... Simple fix that seems to do the trick....? I added in a check to make sure the module exists...

$path = $old_path .'/'. $term->tid;
if (module_exists('path')) {
  if($alias = drupal_lookup_path('alias','taxonomy/term/' . $term->tid)) path_set_alias($path, $alias);
}
$old_depth  = $term->depth;
$old_path   = $path;

I am a bit of a newbie with Drupal though - seems to be working fine on my v5.12 site just now.

Thanks,

Kester Hynds
www.komoko.co.uk

Mguel’s picture

Is this solved with the 5.x-1.0 release?

Better paths: instead creating paths based only on Terms IDs, it uses also the Terms Names

Thanks

darumaki’s picture

One of the things I dislike about taxonomy_menu is having to manually redo the URL, why can't this be automated based on the vocab and terms, url category/2 makes absolutely no sense, neither does category/vocab/term
we shouldn't have to manually edit every content

ie if the vocab is blog and the term is apples then the url should naturally be domain/blog/apples

creazion_dev’s picture

Based on the module "Rewrite" by levavie I put the following code at the end of my settings.php:

 if(!function_exists("custom_url_rewrite")){
	function custom_url_rewrite($type, $alias, $real_path) {
	  $path = ( $alias ) ? $alias : $real_path;
	  $parts = explode('/', $path);
	  if ($parts[0] == variable_get('taxonomy_menu_display_page', 'taxonomy_menu')) {
	    $path = 'taxonomy/term/'. end($parts);

	    $result = db_query( "SELECT dst FROM {url_alias} WHERE src= '%s'", $path);
	    while ($row = db_fetch_object($result)) {
	      $path = $row->dst;
	      break;
	    }

	  }
	  return $path;
	}
}

Now it works fine with pathauto generated paths.

---------------------------------------------
www.creazion.de - www.happyfaces-kinderschminken.de - www.3p-consulting.com

TheSmegHead’s picture

creazion_dev-

What version of Drupal are you using...should this work for 6.1? (I tried but it is not working for me). Are there additional steps?

ardee-1’s picture

Thank you Creazion!

Adding that to settings.php (in my Drupal 5.7 installation) worked for me, whereas many other attempts to solve the problem did not.

I am very grateful!

snipe’s picture

that works for me
thank you creazion

Demarlos Solutions
www.demarlos.com

chrisschaub’s picture

I think you might need to add a check if the path is a vocabulary or a term path:

      if ($parts[0] == variable_get('taxonomy_menu_display_page', 'taxonomy_menu')) {

        // a vocab path
        if (preg_match("/category\/\d$/", $real_path)) {
          $path = 'taxonomy/vocabulary/'.end($parts);

        // a term path
        } else {
          $path = 'taxonomy/term/'. end($parts);
        }

I don't know if there is a better way to do this. Otherwise, your example will make vocabulary paths have the path alias like term paths. This is really important when using taxonomy context in conjunction with taxonomy_menu.

fallsemo’s picture

Yes! Thanks Creazion (and schaub123)!

EDIT*

This function override works in that it aliases my taxonomy menu terms to reflect the pathauto settings I have set taxonomy/term to be if I mouse over each taxonomy_menu link.

HOWEVER:. THE LINKS FROM MY TAXONOMY MENU ARE NOW NOT RENDERED PROPERLY IF I CLICK THEM!
it directs me to nodes that title: http://example/taxonomy/term/node-title ... NOT THE CATEGORY PATH I HAVE SWITCHED PATHAUTO SETTINGS TO.

I hope this explains my problem: mousing over taxonomy menu links appears normal but it doesn't direct properly. It doesn't appear to find the pathauto settings I have set taxonomy to.

This is pretty critical thing.
is there a work around this?

summit’s picture

Hi,

Looks promissing! Also possible for different depth of terms?
See: http://drupal.org/node/231913#comment-1011453
Thanks in advance for your reply!
greetings,
Martijn