I am working to create a token that grabs the top taxonomy term synonym for a node to be used with Pathauto. I have tried using Custom Tokens (the module) but it only works when I do the Update Path Alias action from the content list. It does not work at the time the node is created. Is this because I don't have access to $node->taxonomy until after the node is saved?

Here's the code I have so far in my token starter module:

<?php

/**
* Implementation of hook_token_list().
*/
function token_synonym_token_list($type = 'all') {
$tokens = array();

if ($type == 'node' || $type == 'all') {
$tokens['node']['term-synonym'] = t("The top taxonomy term synonym");
}

return $tokens;
}

/**
* Implementation of hook_token_values().
*/
function token_synonym_token_values($type, $object = NULL) {
$values = array();
switch ($type) {
case 'node':
$node = $object;
foreach($node->taxonomy as $term){$term_array = taxonomy_get_synonyms($term->tid); }
$values['term-synonym'] = $term_array[0];
break;
}
return $values;
}

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

interestingaftermath’s picture

Oops, posted the code without the ending php tags


/**
 * Implementation of hook_token_list().
 */
function token_synonym_token_list($type = 'all') {
  $tokens = array();

  if ($type == 'node' || $type == 'all') {
    $tokens['node']['term-synonym']  = t("The top taxonomy term synonym");
  }

  return $tokens;
}

/**
 * Implementation of hook_token_values().
 */
function token_synonym_token_values($type, $object = NULL) {
  $values = array();
  switch ($type) {
    case 'node':
    	$node = $object;
    	foreach($node->taxonomy as $term){$term_array = taxonomy_get_synonyms($term->tid); }
		$values['term-synonym'] = $term_array[0];
		break;
  }
  return $values;
} 
interestingaftermath’s picture

Now I'm really lost. I figured I was doing something wrong in my code (even though it worked correctly when you'd update the path) so I copied the code from the token_node.inc file.

This does not work when the node is created or when the path is updated from the content list:


/**
 * @file
 * Token Synonym - Returns the top synonym term for a node
 *
 * @ingroup token
 */

/**
 * Implementation of hook_token_list().
 */
function token_synonym_token_list($type = 'all') {
  $tokens = array();

  if ($type == 'node' || $type == 'all') {
    $tokens['node']['term-synonym']  = t("The top taxonomy term synonym");
  }

  return $tokens;
}

/**
 * Implementation of hook_token_values().
 */
function token_synonym_token_values($type, $object = NULL) {
  $values = array();
  switch ($type) {
    case '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 compatibility with it.
      if (module_exists('taxonomy') && !empty($node->taxonomy) && is_array($node->taxonomy)) {
        foreach ($node->taxonomy as $term) {
          $original_term = $term;
          if ((object)$term) {
            // With free-tagging it's somewhat hard to get the tid, vid, name values
            // Rather than duplicating taxonomy.module code here you should make sure your calling module
            // has a weight of at least 1 which will run after taxonomy has saved the data which allows us to
            // pull it out of the db here.
            if (!isset($term->name) || !isset($term->tid)) {
              $vid = db_result(db_query_range("SELECT t.vid FROM {term_node} r INNER JOIN {term_data} t ON r.tid = t.tid INNER JOIN {vocabulary} v ON t.vid = v.vid WHERE r.nid = %d ORDER BY v.weight, t.weight, t.name", $object->nid, 0, 1));
              if (!$vid) {
                continue;
              }
              $term = db_fetch_object(db_query_range("SELECT t.tid, t.name FROM {term_data} t INNER JOIN {term_node} r ON r.tid = t.tid WHERE t.vid = %d AND r.vid = %d ORDER BY t.weight", $vid, $object->vid, 0, 1));
              $term->vid = $vid;
            }

            // Ok, if we still don't have a term name maybe this is a pre-taxonomy submit node
            // So if it's a number we can get data from it
            if (!isset($term->name) && is_array($original_term)) {
              $tid = array_shift($original_term);
              if (is_numeric($tid)) {
                $term = taxonomy_get_term($tid);
              }
            }
            
            $term_array = taxonomy_get_synonyms($term->tid);
            $values['term-synonym'] = $term_array[0];

            break;
          }
        }
      }
      // It's possible to leave that block and still not have good data.
      // So, we test for these and if not set, set them.
      if (!isset($values['term'])) {
        $values['term-synonym'] = '';
      }

      break;
  }

  return $values;
} 
interestingaftermath’s picture

Any ideas?

interestingaftermath’s picture

Status: Active » Fixed

I figured it out. Here my code was right but I was clearing it out with this

if (!isset($values['term'])) {
        $values['term-synonym'] = '';
      }

Since I wasn't setting "term" in my custom module, it was just clearing my new token. Oops! Here's the final code.


/**
 * @file
 * Token Synonym - Returns the top synonym term for a node
 *
 * @ingroup token
 */

/**
 * Implementation of hook_token_list().
 */
function tokenSYNONYM_token_list($type = 'all') {
  $tokens = array();

  if ($type == 'node' || $type == 'all') {
  	if (module_exists('taxonomy')) {
    	$tokens['node']['term-synonym']  = t("The top taxonomy term synonym");
    }
  }

  return $tokens;
}

/**
 * Implementation of hook_token_values().
 */
function tokenSYNONYM_token_values($type, $object = NULL) {
  $values = array();
    switch ($type) {
      case '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 compatibility with it.
        if (module_exists('taxonomy') && !empty($node->taxonomy) && is_array($node->taxonomy)) {
          foreach ($node->taxonomy as $term) {
            $original_term = $term;
            if ((object)$term) {
              // With free-tagging it's somewhat hard to get the tid, vid, name values
              // Rather than duplicating taxonomy.module code here you should make sure your calling module
              // has a weight of at least 1 which will run after taxonomy has saved the data which allows us to
              // pull it out of the db here.
              if (!isset($term->name) || !isset($term->tid)) {
                $vid = db_result(db_query_range("SELECT t.vid FROM {term_node} r INNER JOIN {term_data} t ON r.tid = t.tid INNER JOIN {vocabulary} v ON t.vid = v.vid WHERE r.nid = %d ORDER BY v.weight, t.weight, t.name", $object->nid, 0, 1));
                if (!$vid) {
                  continue;
                }
                $term = db_fetch_object(db_query_range("SELECT t.tid, t.name FROM {term_data} t INNER JOIN {term_node} r ON r.tid = t.tid WHERE t.vid = %d AND r.vid = %d ORDER BY t.weight", $vid, $object->vid, 0, 1));
                $term->vid = $vid;
              }
  
              // Ok, if we still don't have a term name maybe this is a pre-taxonomy submit node
              // So if it's a number we can get data from it
              if (!isset($term->name) && is_array($original_term)) {
                $tid = array_shift($original_term);
                if (is_numeric($tid)) {
                  $term = taxonomy_get_term($tid);
                }
              }
              
              $term_array = taxonomy_get_synonyms($term->tid);
              $values['term-synonym'] = $term_array[0];
  
              // The 'catpath' (and 'cat') tokens have been removed, as they caused quite a bit of confusion,
              // and the catpath was a relatively expensive query when the taxonomy tree was deep.
              //
              // It existed only to provide forward-compatability with pathauto module, and
              // for most uses of token.module, it was a relatively useless token -- it exposed
              // a list of term names formatted as a URL/path string. Once pathauto supports
              // tokens, *it* should handle this catpath alias as it's the primary consumer.
              break;
            }
          }
        }
        // It's possible to leave that block and still not have good data.
        // So, we test for these and if not set, set them.
        if (!isset($values['term-synonym'])) {
          $values['term-synonym'] = '';
        }
  
        break;
    }
  
    return $values;
  }
  

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

joachim’s picture

Title: Creating a token to get the top Taxonomy Term Synonym » Add a token to get the top Taxonomy Term Synonym
Category: support » feature
Status: Closed (fixed) » Needs review
FileSize
1.23 KB

interestingaftermath -- not entirely sure what your code is doing.

I've achieved this with the following pretty simple patch. Works great for URL aliases.

Status: Needs review » Needs work

The last submitted patch, 965702.token_.taxonomy-synonym.patch, failed testing.

interestingaftermath’s picture

I don't doubt that the code I wrote is more than it needs to be but that's primarily because I do not know how to write a patch and didn't want to edit the module itself. I had to pull all the code from the taxonomy tokens function and recreate it in my own module.

I would much rather see this added as a patch like you're attempting.

joachim’s picture

Status: Needs work » Needs review
FileSize
1.31 KB

Ah, that part of the module has changed a bit in dev.

Here is a reroll against git rather than the latest release.

Status: Needs review » Needs work

The last submitted patch, 965702-2.token_.taxonomy-synonym.patch, failed testing.

joachim’s picture

Status: Needs work » Needs review
FileSize
1.3 KB

*sigh*

I shouldn't complain -- changing $category to $term is a good fix :)

Status: Needs review » Needs work

The last submitted patch, 965702-3.token_.taxonomy-synonym.patch, failed testing.

joachim’s picture

Status: Needs work » Needs review
FileSize
1.34 KB

Ah. Yes.

This should pass tests, though it does raise the question of what the token should contain when there is no synonym. Any thoughts?

Status: Needs review » Needs work

The last submitted patch, 965702-4.token_.taxonomy-synonym.patch, failed testing.

joachim’s picture

O_o

I'm giving up on this for now at least...

Dave Reid’s picture

+++ token_taxonomy.incundefined
@@ -60,6 +61,10 @@ function taxonomy_token_values($type, $object = NULL, $options = array()) {
+    if (isset($synonyms[0]))
+      $values['cat-synonym'] = $synonyms[0];

Missing a { after the if statement. That's what's causing the fatal errors.

Powered by Dreditor.

interestingaftermath’s picture

it does raise the question of what the token should contain when there is no synonym. Any thoughts?

What happens when you use a token that doesn't have a value for the more "core" tokens? It could mimic that which I imagine would just be the print [token] or whatever. I know in my case, if I am using that token it's because every term possible for that node has a synonym.

interestingaftermath’s picture

Re-uploading jaochim's patch with the syntax fix that Dave Reid noticed.

interestingaftermath’s picture

Oops. This should work

[edit] someone want to educate me on how to get the patch to test? I'm a patching noob.

joachim’s picture

Status: Needs work » Needs review

Just set the status to 'needs review'.

And thanks! I was getting really fed up of this patch, for all its 4 lines!!!

interestingaftermath’s picture

No, thank you for taking a look at this issue. Although my code works it's quite excessive. Going to upgrade to the latest dev now with this new patch. Thanks again

bmx269’s picture

Added the patch to the node tokens as well against HEAD version 6.x-1.x-dev in git as of today.

bmx269’s picture

Not sure why I can not run the tests on my patch above, but please test. Thanks, I also took the previous patch and added that to it.

bmx269’s picture

Fixed my patch above and resubmitted the revision here. This adds the synonym patch to the node path as well as the taxonomy.

bmx269’s picture

This is a great patch. Thaks to all who contributed.

BarwonHack’s picture

Probably a great addition for Drupal Local SEO.

Can't wait until this is released - hint hint :D

Hylite’s picture

The patch works fabulously. However I was wondering how would I go about simply having it not show "[cat-synonym]" if no synonym was entered for a specific term?

bmx269’s picture

You are thinking a fallback right?

Hylite’s picture

Correct, currently it displays [content-synonym], id imagine if it just omitted that token if there is no synonym specified that it would solve the issue.

jcamfield’s picture

Is this patch or functionality available for 7.x?

Update: The patch in #18 here works for this in D7: http://drupal.org/node/741914