Using pathauto to create nested terms in URLs in taxonomy term pages in Drupal

| | 2 min read

On a Drupal site, when setting up pathauto for nodes, sometimes it is useful to have the full nested path of parent terms of the channel (or primary vocabulary) for the article in the url alias to give the impression of a directory structure to the taxonomy vocabulary. This will allow users to see urls to nodes like domain/term1/term2/term3/node-title-or-whatever where term3 is the channel under which the article is published.

This can be achieved using the hook_token_values hook. You will have to implement the token_values hook in your module and expose the nested path to the taxonomy term as a token. This token can then be used in the pathauto configuration page to assign the full nested path to the URL for the node.

function yourmodule_token_values($type, $object = NULL, $options = array()) {
  $values = array();
  switch ($type) {
    case 'node':
      $term = db_fetch_object(db_query_range("SELECT t.tid, t.name FROM {term_node} r 
        INNER JOIN {term_data} t ON r.tid = t.tid 
        WHERE r.nid = %d AND t.vid = %d ORDER BY t.weight, t.name", 
        array($object->nid, variable_get('yourmodule_channel_vocabulary', '1')), 0, 1));
      if ($term) {
        _pathauto_include();
        $separator = variable_get('pathauto_separator', '-');
        $parents = taxonomy_get_parents_all($term->tid);
        array_shift($parents);
        $channelpath = '';
        $channelpath_raw = '';
        foreach ($parents as $parent) {
          // Replace any / characters in individual terms which might create confusing URLs
          $channelpath = pathauto_cleanstring(check_plain(preg_replace('/\//', '', $parent->name))) 
            .'/'. $channelpath;
          $channelpath_raw = pathauto_cleanstring(preg_replace('/\//', '', $parent->name)) 
            .'/'. $channelpath_raw;
        }
        $values['channelpath'] = $channelpath .'/'. pathauto_cleanstring(check_plain($term->name));
        $values['channelpath-raw'] = $channelpath_raw .'/'. pathauto_cleanstring($term->name);
        $values['channel'] = check_plain($term->name);
        $values['channel-raw'] = $term->name;
      }
      else {
        $values['channelpath'] = '';
        $values['channelpath-raw'] = '';
        $values['channel'] = '';
        $values['channel-raw'] = '';
      }
  }
  return $values;
}