? 0-user-text-field-tokens.txt
? field_token.tpl.php
? jquery-ui-tree
? jstree
? menu.tokens.inc
? patches
? theme
? token.inc
? treeTable
Index: token.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/token/token.test,v
retrieving revision 1.30
diff -u -p -r1.30 token.test
--- token.test	18 Dec 2010 01:53:33 -0000	1.30
+++ token.test	5 Jan 2011 17:25:31 -0000
@@ -21,7 +21,10 @@ class TokenTestHelper extends DrupalWebT
     $values = token_generate($type, $token_input, array($type => $object), $options);
     foreach ($tokens as $token => $expected) {
       if (!isset($expected)) {
-        $this->assertTrue(!isset($values[$token]) || $result['values'][$token] === $token, t("Token value for [@type:@token] was not generated.", array('@type' => $type, '@token' => $token)));
+        $this->assertTrue(!isset($values[$token]), t("Token value for [@type:@token] was not generated.", array('@type' => $type, '@token' => $token)));
+      }
+      elseif (!isset($values[$token])) {
+        $this->fail(t("Token value for [@type:@token] was not generated.", array('@type' => $type, '@token' => $token)));
       }
       else {
         $this->assertIdentical($values[$token], $expected, t("Token value for [@type:@token] was '@actual', expected value '@expected'.", array('@type' => $type, '@token' => $token, '@actual' => $values[$token], '@expected' => $expected)));
@@ -144,6 +147,64 @@ class TokenUnitTestCase extends TokenTes
   }
 }
 
+class TokenCommentTestCase extends TokenTestHelper {
+  public static function getInfo() {
+    return array(
+      'name' => 'Comment token tests',
+      'description' => 'Test the comment tokens.',
+      'group' => 'Token',
+    );
+  }
+
+  function testCommentTokens() {
+    $node = $this->drupalCreateNode(array('comment' => COMMENT_NODE_OPEN));
+
+    $parent_comment = new stdClass;
+    $parent_comment->nid = $node->nid;
+    $parent_comment->pid = 0;
+    $parent_comment->cid = NULL;
+    $parent_comment->uid = 0;
+    $parent_comment->name = 'anonymous user';
+    $parent_comment->mail = 'anonymous@example.com';
+    $parent_comment->subject = $this->randomName();
+    $parent_comment->timestamp = mt_rand($node->created, REQUEST_TIME);
+    $parent_comment->language = LANGUAGE_NONE;
+    $parent_comment->body[LANGUAGE_NONE][0] = $this->randomName();
+    comment_save($parent_comment);
+
+    $tokens = array(
+      'url' => url('comment/' . $parent_comment->cid, array('fragment' => 'comment-' . $parent_comment->cid, 'absolute' => TRUE)),
+      'url:absolute' => url('comment/' . $parent_comment->cid, array('fragment' => 'comment-' . $parent_comment->cid, 'absolute' => TRUE)),
+      'url:relative' => url('comment/' . $parent_comment->cid, array('fragment' => 'comment-' . $parent_comment->cid, 'absolute' => FALSE)),
+      'url:path' => 'comment/' . $parent_comment->cid,
+      'url:alias' => 'comment/' . $parent_comment->cid,
+      'parent:url:absolute' => NULL,
+    );
+    $this->assertTokens('comment', $parent_comment, $tokens);
+
+    $comment = new stdClass();
+    $comment->nid = $node->nid;
+    $comment->pid = $parent_comment->cid;
+    $comment->cid = NULL;
+    $comment->uid = 1;
+    $comment->subject = $this->randomName();
+    $comment->timestamp = mt_rand($parent_comment->created, REQUEST_TIME);
+    $comment->language = LANGUAGE_NONE;
+    $comment->body[LANGUAGE_NONE][0] = $this->randomName();
+    comment_save($comment);
+
+    $tokens = array(
+      'url' => url('comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid, 'absolute' => TRUE)),
+      'url:absolute' => url('comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid, 'absolute' => TRUE)),
+      'url:relative' => url('comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid, 'absolute' => FALSE)),
+      'url:path' => 'comment/' . $comment->cid,
+      'url:alias' => 'comment/' . $comment->cid,
+      'parent:url:absolute' => url('comment/' . $parent_comment->cid, array('fragment' => 'comment-' . $parent_comment->cid, 'absolute' => TRUE)),
+    );
+    $this->assertTokens('comment', $comment, $tokens);
+  }
+}
+
 class TokenNodeTestCase extends TokenTestHelper {
   public static function getInfo() {
     return array(
@@ -159,7 +220,10 @@ class TokenNodeTestCase extends TokenTes
       'source' => NULL,
       'source:nid' => NULL,
       'log' => $source_node->log,
-      'path' => 'content/source-node',
+      'url:absolute' => url("node/{$source_node->nid}", array('absolute' => TRUE)),
+      'url:relative' => url("node/{$source_node->nid}", array('absolute' => FALSE)),
+      'url:path' => "node/{$source_node->nid}",
+      'url:alias' => 'content/source-node',
       'content-type' => 'Basic page',
       'content-type:name' => 'Basic page',
       'content-type:machine-name' => 'page',
@@ -178,7 +242,10 @@ class TokenNodeTestCase extends TokenTes
       'source' => $source_node->title,
       'source:nid' => $source_node->nid,
       'log' => '',
-      'path' => "node/{$translated_node->nid}",
+      'url:absolute' => url("node/{$translated_node->nid}", array('absolute' => TRUE)),
+      'url:relative' => url("node/{$translated_node->nid}", array('absolute' => FALSE)),
+      'url:path' => "node/{$translated_node->nid}",
+      'url:alias' => "node/{$translated_node->nid}",
       'content-type' => 'Article',
       'content-type:name' => 'Article',
       'content-type:machine-name' => 'article',
@@ -236,8 +303,11 @@ class TokenMenuTestCase extends TokenTes
       'menu:description' => 'The <em>Main</em> menu is used on many sites to show the major sections of the site, often in a top navigation bar.',
       'menu:menu-link-count' => 3, // Standard install creates one link.
       'menu:edit-url' => url("admin/structure/menu/manage/main-menu", array('absolute' => TRUE)),
-      'path' => 'root/parent',
       'url' => url('root/parent', array('absolute' => TRUE)),
+      'url:absolute' => url('root/parent', array('absolute' => TRUE)),
+      'url:relative' => url('root/parent', array('absolute' => FALSE)),
+      'url:path' => 'root/parent',
+      'url:alias' => 'root/parent',
       'edit-url' => url("admin/structure/menu/item/{$parent_link['mlid']}/edit", array('absolute' => TRUE)),
       'parent' => 'Root link',
       'parent:mlid' => $root_link['mlid'],
@@ -267,8 +337,8 @@ class TokenMenuTestCase extends TokenTes
       'menu-link:mlid' => $node->menu['mlid'],
       'menu-link:title' => 'Node link',
       'menu-link:menu' => 'Main menu',
-      'menu-link:path' => 'node/' . $node->nid,
       'menu-link:url' => url('node/' . $node->nid, array('absolute' => TRUE)),
+      'menu-link:url:path' => 'node/' . $node->nid,
       'menu-link:edit-url' => url("admin/structure/menu/item/{$node->menu['mlid']}/edit", array('absolute' => TRUE)),
       'menu-link:parent' => 'Parent link',
       'menu-link:parent:mlid' => $node->menu['plid'],
@@ -604,8 +674,11 @@ class TokenCurrentPageTestCase extends T
   function testCurrentPageTokens() {
     $tokens = array(
       '[current-page:title]' => 'Welcome to Drupal',
-      '[current-page:path]' => 'node',
       '[current-page:url]' => url('node', array('absolute' => TRUE)),
+      '[current-page:url:absolute]' => url('node', array('absolute' => TRUE)),
+      '[current-page:url:relative]' => url('node', array('absolute' => FALSE)),
+      '[current-page:url:path]' => 'node',
+      '[current-page:url:alias]' => 'node',
       '[current-page:page-number]' => 1,
       '[current-page:arg:0]' => 'node',
       '[current-page:arg:1]' => NULL,
@@ -615,8 +688,11 @@ class TokenCurrentPageTestCase extends T
     $node = $this->drupalCreateNode(array('title' => 'Node title', 'path' => array('alias' => 'node-alias')));
     $tokens = array(
       '[current-page:title]' => 'Node title',
-      '[current-page:path]' => 'node-alias',
       '[current-page:url]' => url("node/{$node->nid}", array('absolute' => TRUE)),
+      '[current-page:url:absolute]' => url("node/{$node->nid}", array('absolute' => TRUE)),
+      '[current-page:url:relative]' => url("node/{$node->nid}", array('absolute' => FALSE)),
+      '[current-page:url:path]' => "node/{$node->nid}",
+      '[current-page:url:alias]' => 'node-alias',
       '[current-page:page-number]' => 1,
       '[current-page:arg:0]' => 'node',
       '[current-page:arg:1]' => $node->nid,
Index: token.tokens.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/token/token.tokens.inc,v
retrieving revision 1.36
diff -u -p -r1.36 token.tokens.inc
--- token.tokens.inc	18 Dec 2010 01:53:33 -0000	1.36
+++ token.tokens.inc	5 Jan 2011 17:25:31 -0000
@@ -35,15 +35,29 @@ function token_token_info_alter(&$info) 
     }
     $token_type = $entity_info['token type'];
 
-    // Add [entity:path] tokens if they do not already exist.
-    if (!isset($info['tokens'][$token_type]['path']) && (!empty($entity_info['uri callback']) || !empty($entity_info['bundles'][$entity]['uri callback']))) {
-      $info['tokens'][$token_type]['path'] = array(
-        'name' => t('Path'),
-        'description' => t('The URL alias of the @entity.', array('@entity' => drupal_strtolower($entity_info['label']))),
+    // Add [entity:url] tokens if they do not already exist.
+    // @todo Support entity:label
+    if (!isset($info['tokens'][$token_type]['url']) && (!empty($entity_info['uri callback']) || !empty($entity_info['bundles'][$entity]['uri callback']))) {
+      $info['tokens'][$token_type]['url'] = array(
+        'name' => t('URL'),
+        'description' => t('The URL of the @entity.', array('@entity' => drupal_strtolower($entity_info['label']))),
         'module' => 'token',
+        'type' => 'url',
       );
     }
   }
+
+  $info['tokens']['comment']['url']['type'] = 'url';
+  //$info['tokens']['file']['url']['type'] = 'url';
+  $info['tokens']['node']['url']['type'] = 'url';
+  $info['tokens']['term']['url']['type'] = 'url';
+  $info['tokens']['user']['url']['type'] = 'url';
+  // @todo Support other tokens not named 'url'
+}
+
+function _token_module($type, $name) {
+  $token_info = token_get_info($type, $name);
+  return isset($token_info['module']) ? $token_info['module'] : NULL;
 }
 
 /**
@@ -91,6 +105,7 @@ function token_token_info() {
   $info['tokens']['content-type']['edit-url'] = array(
     'name' => t('Edit URL'),
     'description' => t("The URL of the content type's edit page."),
+    //'type' => 'url',
   );
 
   // Taxonomy term and vocabulary tokens.
@@ -98,6 +113,7 @@ function token_token_info() {
     $info['tokens']['term']['edit-url'] = array(
       'name' => t('Edit URL'),
       'description' => t("The URL of the taxonomy term's edit page."),
+      //'type' => 'url',
     );
 
     $info['tokens']['vocabulary']['machine-name'] = array(
@@ -107,6 +123,7 @@ function token_token_info() {
     $info['tokens']['vocabulary']['edit-url'] = array(
       'name' => t('Edit URL'),
       'description' => t("The URL of the vocabulary's edit page."),
+      //'type' => 'url',
     );
   }
 
@@ -122,11 +139,13 @@ function token_token_info() {
     'name' => t('Account cancellation URL'),
     'description' => t('The URL of the confirm delete page for the user account.'),
     'restricted' => TRUE,
+    //'type' => 'url',
   );
   $info['tokens']['user']['one-time-login-url'] = array(
     'name' => t('One-time login URL'),
     'description' => t('The URL of the one-time login page for the user account.'),
     'restricted' => TRUE,
+    //'type' => 'url',
   );
   if (variable_get('user_pictures', 0)) {
     $info['tokens']['user']['picture'] = array(
@@ -156,13 +175,10 @@ function token_token_info() {
     'name' => t('Title'),
     'description' => t('The title of the menu link.'),
   );
-  $info['tokens']['menu-link']['path'] = array(
-    'name' => t('Path'),
-    'description' => t('The URL alias of the menu link.'),
-  );
   $info['tokens']['menu-link']['url'] = array(
     'name' => t('URL'),
     'description' => t('The URL of the menu link.'),
+    'type' => 'url',
   );
   $info['tokens']['menu-link']['parent'] = array(
     'name' => t('Parent'),
@@ -184,13 +200,10 @@ function token_token_info() {
     'name' => t('Title'),
     'description' => t('The title of the current page.'),
   );
-  $info['tokens']['current-page']['path'] = array(
-    'name' => t('Path'),
-    'description' => t('The URL alias of the current page.'),
-  );
   $info['tokens']['current-page']['url'] = array(
     'name' => t('URL'),
     'description' => t('The URL of the current page.'),
+    'type' => 'url-fake',
   );
   $info['tokens']['current-page']['page-number'] = array(
     'name' => t('Page number'),
@@ -202,6 +215,28 @@ function token_token_info() {
     'dynamic' => TRUE,
   );
 
+  $info['types']['url'] = array(
+    'name' => t('URL'),
+    'description' => t('Tokens related to URLs.'),
+    'needs-data' => 'url',
+  );
+  $info['tokens']['url']['path'] = array(
+    'name' => t('Internal path'),
+    'description' => t('The internal Drupal path of the URL.'),
+  );
+  $info['tokens']['url']['alias'] = array(
+    'name' => t('Alias'),
+    'description' => t('The alias of the URL.'),
+  );
+  $info['tokens']['url']['relative'] = array(
+    'name' => t('Relative URL'),
+    'description' => t('The relative URL.'),
+  );
+  $info['tokens']['url']['absolute'] = array(
+    'name' => t('Absolute URL'),
+    'description' => t('The absolute URL.'),
+  );
+
   return $info;
 }
 
@@ -228,6 +263,16 @@ function token_tokens($type, $tokens, ar
     $replacements += token_generate('date', $tokens, array('date' => REQUEST_TIME), $options);
   }
 
+  // Comment tokens.
+  if ($type == 'comment' && !empty($data['comment'])) {
+    $comment = $data['comment'];
+
+    // Chained token relationships.
+    if (($url_tokens = token_find_with_prefix($tokens, 'url'))) {
+      $replacements += token_generate('url', $url_tokens, entity_uri('comment', $comment), $options);
+    }
+  }
+
   // Node tokens.
   if ($type == 'node' && !empty($data['node'])) {
     $node = $data['node'];
@@ -257,6 +302,9 @@ function token_tokens($type, $tokens, ar
     if (($node_type_tokens = token_find_with_prefix($tokens, 'content-type')) && $node_type = node_type_load($node->type)) {
       $replacements += token_generate('content-type', $node_type_tokens, array('node_type' => $node_type), $options);
     }
+    if (($url_tokens = token_find_with_prefix($tokens, 'url'))) {
+      $replacements += token_generate('url', $url_tokens, entity_uri('node', $node), $options);
+    }
   }
 
   // Content type tokens.
@@ -300,6 +348,11 @@ function token_tokens($type, $tokens, ar
           break;
       }
     }
+
+    // Chained token relationships.
+    if (($url_tokens = token_find_with_prefix($tokens, 'url'))) {
+      $replacements += token_generate('url', $url_tokens, entity_uri('taxonomy_term', $term), $options);
+    }
   }
 
   // Vocabulary tokens.
@@ -331,6 +384,8 @@ function token_tokens($type, $tokens, ar
           break;
       }
     }
+
+    // @todo Support [file:url:*]
   }
 
   // User tokens.
@@ -353,6 +408,9 @@ function token_tokens($type, $tokens, ar
       $account->picture->description = '';
       $replacements += token_generate('file', $picture_tokens, array('file' => $account->picture), $options);
     }
+    if (($url_tokens = token_find_with_prefix($tokens, 'url'))) {
+      $replacements += token_generate('url', $url_tokens, entity_uri('user', $account), $options);
+    }
   }
 
   // Current user tokens.
@@ -384,10 +442,6 @@ function token_tokens($type, $tokens, ar
         case 'title':
           $replacements[$original] = $sanitize ? check_plain($link['title']) : $link['title'];
           break;
-        case 'path':
-          $alias = drupal_get_path_alias($link['href'], $language_code);
-          $replacements[$original] = $sanitize ? check_plain($alias) : $alias;
-          break;
         case 'url':
           $replacements[$original] = url($link['href'], $url_options);
           break;
@@ -411,6 +465,9 @@ function token_tokens($type, $tokens, ar
     if (!empty($link['p1']) && $link['p1'] != $link['mlid'] && ($root_tokens = token_find_with_prefix($tokens, 'root')) && $root = token_menu_link_load($link['p1'])) {
       $replacements += token_generate('menu-link', $root_tokens, array('menu-link' => $root), $options);
     }
+    if ($url_tokens = token_find_with_prefix($tokens, 'url')) {
+      $replacements += token_generate('url', $url_tokens, array('path' => $link['href']), $options);
+    }
   }
 
   // Current page tokens.
@@ -422,10 +479,6 @@ function token_tokens($type, $tokens, ar
         case 'title':
           $replacements[$original] = drupal_get_title();
           break;
-        case 'path':
-          $alias = drupal_get_path_alias($current_path, $language_code);
-          $replacements[$original] = $sanitize ? check_plain($alias) : $alias;
-          break;
         case 'url':
           $replacements[$original] = url($current_path, $url_options);
           break;
@@ -448,6 +501,39 @@ function token_tokens($type, $tokens, ar
         }
       }
     }
+
+    // Chained token relationships.
+    if ($url_tokens = token_find_with_prefix($tokens, 'url')) {
+      $replacements += token_generate('url', $url_tokens, array('path' => $current_path), $options);
+    }
+  }
+
+  // URL tokens.
+  if ($type == 'url' && !empty($data['path'])) {
+    $path = $data['path'];
+
+    if (isset($data['options'])) {
+      // Merge in the URL options if available.
+      $url_options = $data['options'] + $url_options;
+    }
+
+    foreach ($tokens as $name => $original) {
+      switch ($name) {
+        case 'path':
+          $replacements[$original] = $sanitize ? check_plain($path) : $path;
+          break;
+        case 'alias':
+          $alias = drupal_get_path_alias($path, $language_code);
+          $replacements[$original] = $sanitize ? check_plain($alias) : $alias;
+          break;
+        case 'absolute':
+          $replacements[$original] = url($path, $url_options);
+          break;
+        case 'relative':
+          $replacements[$original] = url($path, array('absolute' => FALSE) + $url_options);
+          break;
+      }
+    }
   }
 
   // Entity tokens.
@@ -462,22 +548,18 @@ function token_tokens($type, $tokens, ar
 
     foreach ($tokens as $name => $original) {
       switch ($name) {
-        // @todo Support entity:label
-        // @todo Support entity:url
-        case 'path':
-          $token_info = token_get_info($type, $name);
-          if (!isset($token_info['module']) || $token_info['module'] != 'token') {
-            // We must check that this token was added by token.module itself
-            // otherwise we may cause an array to be returned.
-            continue;
-          }
-          if ($uri = entity_uri($entity_type, $entity)) {
-            $alias = drupal_get_path_alias($uri['path'], $language_code);
-            $replacements[$original] = $sanitize ? check_plain($alias) : $alias;
+        case 'url':
+          if (_token_module($type, 'url') == 'token' && $uri = entity_uri($entity_type, $entity)) {
+            $replacements[$original] = url($uri['path'], $uri['options']);
           }
           break;
       }
     }
+
+    // Chained token relationships.
+    if (($url_tokens = token_find_with_prefix($tokens, 'url')) && _token_module($type, 'url') == 'token') {
+      $replacements += token_generate('url', $url_tokens, entity_uri($entity_type, $entity), $options);
+    }
   }
 
   // If $type is a token type, $data[$type] is empty but $data[$entity_type] is
