26

How would you go about programmatically creating a token? I wish to add some custom tokens for my module.

1

6 Answers 6

7

In Drupal 6, you use hook_token_values().

This hook will allow you to create tokens. You can create them in the global scope or you can use an object like a node, or a user to seed the values.

You should also use hook_token_list() to explain what your tokens are.

The token.api documentation is quite clear.

function my_user_token_values($type, $object = NULL, $options = array()) {
  if ($type == 'user') {
    $user = $object;
    $tokens['name']      = $user->name;
    $tokens['mail']      = $user->mail;
    return $tokens;
  }
}

I won't X post the whole thing but that should give you a high level idea.

0
21

In Drupal 7 the code for handling tokens is part of the Drupal core module.

The hooks the token modules need to implement are:

  • hook_token_info() is the hook that provides information about the tokens implemented by a module.
  • hook_tokens() is the hook that needs to be implemented to provide the actual values that replace the tokens.

Other modules can alter the token implementation provided from a module using hook_token_info_alter() and hook_tokens_alter().

Differently from the Token module, the code in Drupal core allows to create the content of a token only when strictly necessary. In Drupal 6, the Token module would ask to the modules implementing tokens all the values for their token using hook_token_values(); this means that a module can compute the value for a token which is then not required for the tokens being replaced. In Drupal 7, the implementation of hook_tokens() receives $tokens, an array of tokens to be replaced, as argument; the module is then able to compute the value of a token, knowing it will be used.

The function that in Drupal 7 is used to replace the tokens with their value is token_replace(), which is the only function used to replace the tokens with their values.

Other difference between the Token module for Drupal 6 and the code in Drupal 7 are:

  • In Drupal 7, [node:author] returns the name of the author; [node:author:mail] returns the email address associated with the author of a node, and [node:author:url] returns the URL of the user profile for the node author. In other words, it is possible to use [node:author:xyz], where "xyz" is one of the tokens returned for a user object.
  • In Drupal 7, there are not raw tokens; the implementation of hook_tokens() get a parameter that tells to the hook when the content of the token needs to be sanitized; when the token value doesn't need to be sanitized, the content is not passed to the functions check_plain() or filter_xss().
  • In Drupal 7, there isn't any function that show the list of the available tokens. If a module needs to show the list of available tokens, it must build the list of the tokens itself and show it in the description of a form field; alternatively, it can use the theme function still available in the Token module.
0
11

I wanted to add a new token to the Site information section of tokens, called City name. This is how I did it in Drupal 7.

 /**
 * Implements hook_token_info().
 */
function my_module_token_info() {

  // Add tokens.
  $site['city_name'] = array(
    'name' => t('Token Name'),
    'description' => t('Token Description'),
  );

  return array(
    'tokens' => array(
      'site' => $site,
    ),
  );
}

/**
 * Implements hook_tokens().
 */
function my_module_tokens($type, $tokens, array $data = array(), array $options = array()) {
  $replacements = array();

 if ($type == 'site') {
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'city_name':
          $city_name = variable_get('city_name');
          $replacements[$original] = $options['sanitize'] ? check_plain($city_name) : $city_name;
          break;
      }
    }
  }

  // Return the replacements.
  return $replacements;
}
6
  • Thanks for providing an example. They are always helpful
    – iStryker
    Commented Mar 12, 2015 at 13:01
  • 1
    So the token would be in above example: [site:city_name]. Make sure you clear the caches or restart memcached if used.
    – kenorb
    Commented Sep 4, 2015 at 9:21
  • Note: $sanitize in above example is not defined, so you'll get Notice: Undefined variable about that.
    – kenorb
    Commented Sep 4, 2015 at 9:28
  • @kenorb good eye, and I see this answer has since been updated :)
    – WebMW
    Commented Jun 5, 2019 at 19:49
  • @WebMW Actually, it never was. I fixed it.
    – mbomb007
    Commented May 21, 2020 at 21:20
7

For Drupal 8, example using the node object:

You can put tokens in your module at mymodule.tokens.inc using hook_token_info() to register them and hook_tokens() for the the replacement data.

If you want to create a custom token for an existing token type, such as for nodes, you'll need to put your token within the subarray within hook_token_info(). Refer to node.tokens.inc in the node module to see what you're building off of.

mymodule.tokens.inc:

<?php

use Drupal\Core\Render\BubbleableMetadata;
use Drupal\image\Entity\ImageStyle;

/**
 * Implements hook_token_info().
 */
function mymodule_token_info() {
  $info = array();

  $info['tokens']['node']['custom_title'] = [
    'name' => t("Custom Title"),
    'description' => t("a custom node title token"),
  ];
  // Return them.
  return $info;
}

/**
 * Implements hook_tokens().
 */
function mymodule_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {

  $replacements = array();
  if ($type == 'node') {
    foreach ($tokens as $name => $original) {
      // Find the desired token by name
      switch ($name) {
        case 'custom_title':
          $node = $data['node'];
          $replacements[$original] = $node->label();
          break;
      }
    }
  }
  // Return the replacements.
  return $replacements;
}
0
5

For Drupal 8

// We need to include the needed class for tokens.

use Drupal\Core\Render\BubbleableMetadata;

/**
 * Implements hook_token_info().
 */
function modulename_token_info() {
  $info = array();
  // Add any new tokens.
  $info['tokens']['customtokentype']['customtoken'] = t('Telling drupal that you define custom token');
  // Return them.
  return $info;
}

/**
 * Implements hook_tokens().
 */
function modulename_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
  $replacements = array();
  $simple = $data["customanything"];
  if ($type == 'customtokentype') {
    foreach ($tokens as $name => $original) {
      // Find the desired token by name
      switch ($name) {
        case 'customtoken':
          $new = $simple;
          $replacements[$original] = $new;
          break;
      }
    }
  }   
  // Return the replacements.
  return $replacements;
}

Getting the value of tokens in your function requires code similar to the following one.

$token = \Drupal::token();
$message_html = "hello my custom token is replaced see it here [customtokentype:customtoken]";

// Token data.
$data = array('customanything' => $tosendtotokens);
$message_html = $token->replace($message_html, $data);
3
  • 1
    What is new and simple in this example?
    – user1359
    Commented Sep 11, 2017 at 2:50
  • use Drupal\Core\Render\BubbleableMetadata; $token = \Drupal::token(); function modulename_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) { ... } Commented Sep 11, 2017 at 6:16
  • 1
    This should go in modulename.tokens.inc
    – oknate
    Commented Feb 2, 2018 at 14:19
1

In my_module.tokens.inc place two functions like this:

<?php

/**
 * Implements hook_token_info().
 */
function my_module_token_info() {
  $info['tokens']['node']['my_custom_title'] = [
    'name' => t("Custom title"),
    'description' => t("The first 10 characters of the title"),
  ];
  return $info;
}
/**
 * Implements hook_tokens().
 */
function my_module_tokens($type, $tokens, array $data, array $options, \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata) {
  $replacements = [];
  if ($type == 'node') {
    foreach ($tokens as $name => $original) {
      // Find the desired token by name
      switch ($name) {
        case 'my_custom_title':
          $node = $data['node'];
          $replacements[$original] = substr($node->getTitle(), 0, 10);
          break;
      }
    }
  }
  return $replacements;
}
1
  • 1
    I created this answer as previous answers by oknate and Karthikeyan had some unecessary complications.
    – Jonathan
    Commented Jul 30, 2020 at 15:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.