Community Documentation

Choosing a vocabulary for [term] in Token and Pathauto

Last updated June 5, 2009. Created by fgm on January 6, 2008.
Edited by greggles. Log in to edit this page.

The Goal

When choosing a [term] token in one of your aliases, you want to exert some control over which term in which vocabulary is used. There is no way in the current version to specify to which vocabulary the term must belong: for node types with terms from multiple vocabularies one may be more "canonical" to the meaning than others.

Case in point: on my demo site for the G2 Glossary module, G2 definition nodes carry three visible vocabularies:

  • thematic context: things like storage, networking, machines...
  • grammatical nature
  • language

As you can guess, the thematic context is the one to be used by aliases: the entries from the other two vocabularies are interesting, but nowhere near meaningful enough to warrant appearing in the alias, whereas the context definitely adds semantic value to the URLs.

The Internals

(Skip if you're not interested in pathauto internals) Function pathauto_token_values starts by extracting a single $vid for the node being aliased, using db_result(db_query(some SQL .. ORDER BY v.weight, t.weight, t.name ... LIMIT 1));.

At this point, it only has a single vocabulary from which to choose a term, and it is not necessarily the one you want.

The Solution

The vocabulary selection query orders its result by vocabulary weight, so the term actually chosen by pathauto to build the alias is actually selected as the first term in alphabetical order among the lightest terms in the lightest vocabularies.

Which gives the needed solution: order the vocabularies used by the selected node type by weight so that the vocabulary from which you want to use terms for aliasing is the lightest one. You can find these weights at http://example.com/admin/content/taxonomy/edit/vocabulary/<vid>

Comments

Using terms from multiple taxonomies

If you want to use terms from multiple taxonomies, the following work-around may be helpful:-

I had a vocabulary of towns / venues and another of labels / bands.
I wanted to create a "gigs" node with a url containing town/venue/band
The venue and band are selected from the two taxonomies as part of the node creation/update.

The following workaround works for me:-

Using the Automatic Nodetitles module (http://drupal.org/project/auto_nodetitle), I set the option "Automatically generate the title and hide the title field" within "Automatic title generation"

This option allows pre-population of the node title.

I also checked the "Evaluate PHP in pattern" option and inserted the following code in the "Pattern for the title" textarea.

$result = "";
$node = node_load(arg(1));
$vid = 1;  // Labels and Artists
if($node->taxonomy){
  $term = taxonomy_node_get_terms_by_vocabulary($node, $vid);
  foreach($term as $t) { $terms[] = $t->name; }
  $result = implode('+',$terms) ;
}
return $result;

This code populates the title field with terms from taxonomy 1 (Labels & Artists) which is the more heavily weighted taxonomy in my site.

Then, I set the "Node path settings" within "URL aliases" for the relevant node type to "gigs/[termpath-raw]/[title-raw]".

As the title contains terms from the heavier taxonomy, the final path contains terms from both taxonomies.

Obviously the PHP code used in my example could reference many taxonomies, but this method does rely on not needing the node title for anything else.

HTH
Terry

Saved Me

A spin on this saved me from a headspin on trying to get a clean auto-title out of dual, multi-tiered, Hierarchical Select taxonomies for one of my content types. Below is what I'm using in the auto_nodetitle settings:

<?php
$result1
= "";
$vid1 = 1// Home Team (HS multi-level taxonomy)
$vid2 = 2// Venue (Freetagging taxonomy)
if($node->taxonomy){
 
$term1 = taxonomy_node_get_terms_by_vocabulary($node, $vid1);
  foreach(
$term1 as $t1) {
   
$tid = $t1->tid;
    if(
count(taxonomy_get_children($tid, $vid, 'tid')) == 0) { // Only grab the deepest term (Sport >> Division >> Team (No child terms allowed))
     
$terms1[] = $t1->name;
    }
  }
 
$result1 = $terms1[0];
 
 
$term2 = taxonomy_node_get_terms_by_vocabulary($node, $vid2);
  foreach(
$term2 as $t2) { $terms2[] = $t2->name; }
 
$result2 = $terms2[0];
}
else{
 
$result = 'failed-attempt-at-auto-titling';
}
return
$result1 . ' at ' . $result2;
?>

Thank you!

Use this code to allow to use

Use this code to allow to use terms from one vocabulary:

/**
* Implementation of hook_token_list() for Pathauto specific tokens.
*/
function $YOURMODULE_token_list($type = 'all') {
  $tokens = array();
  if (module_exists('taxonomy')) {
    if ($type == 'node' || $type == 'all') {
      $vocs = taxonomy_get_vocabularies();
      foreach ($vocs as $voc) {
        $tokens['node']['term-' . $voc->vid] = t("Name of top taxonomy term in vocabulary " . $voc->name);
        $tokens['node']['term-' . $voc->vid . '-raw'] = t("Unfiltered name of top taxonomy term in vocabulary " . $voc->name . ". WARNING - raw user input.");
      }
    }
  }
  return $tokens;
}

/**
* Implementation of hook_token_values().
*/
function $YOURMODULE_token_values($type, $object = NULL, $options = array()) {
  $values = array();
  if ($type == 'node') {
    $node = $object;

    // And now taxonomy, which is a bit more work. This code is adapted from
    // pathauto's handling code; it's intended for compatability with it.
    if (module_exists('taxonomy') && !empty($node->taxonomy) && is_array($node->taxonomy)) {
      $vocs = taxonomy_get_vocabularies();
      foreach ($vocs as $voc) {
        $terms = taxonomy_node_get_terms_by_vocabulary($node, $voc->vid);
        $raw_terms = array();
        foreach ($terms as $term) {
          $raw_terms[] = $term->name;
        }
        $raw_terms_str = implode('-', $raw_terms);
       
        $values['term-' . $voc->vid] = check_plain($raw_terms_str);
        $values['term-' . $voc->vid . '-raw'] = $raw_terms_str;
      }
    }
  }

  return $values;
}

worked great

this worked great. thank you!

Thanks!

Worked Perfectly :)

from Tridz, Bangalore

Token Vocab Module

See this, instant top terms per vocab as token:
http://drupal.org/node/185446#comment-1480398

Morningtime, a digital agency
Drupal services, web development, project management.

"The vocabulary selection

"The vocabulary selection query orders its result by vocabulary weight, so the term actually chosen by pathauto to build the alias is actually selected as the first term in alphabetical order among the lightest terms in the lightest vocabularies." Jesus Christ!

Just say- Set the lowest weight to the one you want pathauto to use.

Some people make things too complicated. (/rant off)

About this page

Drupal version
Drupal 5.x
Drupal’s online documentation is © 2000-2013 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License. Comments on documentation pages are used to improve content and then deleted.
nobody click here