I am writing a module that relates to status messages. Sometimes, I have a message that involves two users. Is it possible to do something to this effect using replace?

$message = token_replace("[user:name] replied to [owner:name]'s post", array('user' => $user, 'owner' => $owner));

In this situation, $user and $owner are both user objects that come from user_load.

Comments

zhgenti’s picture

Subscribing
need the same feature.

I've found a small work around, but these custom tokens won't appear in the tokens help.

this code adds [author:FIELD_NAME] tokens only. without native user fields like name and email. but you can add it too.

$data['author'] = $account;
$string = token_replace($body, $data, array('callback' => 'custom_tokens_callback', 'language' => $params['language']));

function custom_tokens_callback(&$replacements, $data) {
  if (isset($data['author'])) {
    foreach(field_info_instances('user', 'user') as $instance) {
      $value = field_get_items('user', $data['author'], $instance['field_name'], $data['langcode']);
      $replacements['[author:' . str_replace("_", "-", $instance['field_name']) . ']'] = ($value && isset($value[0]['value']) ? $value[0]['value'] : '');
    }
  }
}
zhgenti’s picture

Hey,

Here is more elegant solution. works just great for me. Hope will help you too.

$data['author'] = $author_account;
$data['user'] = $user;
$replaced_string = token_replace($body, $data, array('language' => $langcode, 'aliases' => array('author' => 'user')));

function MY_MODULE_tokens_alter(array &$replacements, array $context) {
  if (isset($context['options']['aliases']) && in_array($context['type'], array_keys($context['options']['aliases']))) {
    $new_data = array($context['options']['aliases'][$context['type']] => $context['data'][$context['type']]);
    $replacements += token_generate($context['options']['aliases'][$context['type']], $context['tokens'], $new_data, $context['options']);
  }
}

But tokens still won't be available in the help, when printing it with theme('token_tree') ...

dave reid’s picture

What is the 'author' user account the author of? You should probably be chaining tokens like [status-message:author].

dave reid’s picture

Status: Active » Postponed (maintainer needs more info)
zhgenti’s picture

Yes, author is an account.

Here is another scenario when multiple user instances need to be replaced in the message.
Lets say you want to suggest friend(user of the site) to another user. You need to replace names of three users in the one letter.

Hi [user:name],

I'd like you to meet [friend:name].

Best regards,
[current-user:name]

we can use aliases like

function some_function() {
  $data['user'] = $account;
  $data['friend'] = $friend_account;
  $data['current-user'] = $current_user;
  $replaced_string = token_replace($body, $data, array('language' => $langcode, 'aliases' => array('friend' => 'user', 'current-user' => 'user')));
}

function MY_MODULE_tokens_alter(array &$replacements, array $context) {
  if (isset($context['options']['aliases']) && in_array($context['type'], array_keys($context['options']['aliases']))) {
    $new_data = array($context['options']['aliases'][$context['type']] => $context['data'][$context['type']]);
    $replacements += token_generate($context['options']['aliases'][$context['type']], $context['tokens'], $new_data, $context['options']);
  }
}
moonray’s picture

Status: Postponed (maintainer needs more info) » Active

Would like the answer to this as well.

dave reid’s picture

1. You cannot give 'current-user' an account object. It doesn't work that way.
2. You have to use hook_token_info() to define more 'user' token types similar to how current-user works. In this case you would define a 'friend' token type in your module's hook_token_info().

dave reid’s picture

Status: Active » Fixed

Answer provided in #7.

Status: Fixed » Closed (fixed)

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

rudiedirkx’s picture

Issue summary: View changes
Status: Closed (fixed) » Needs review

Having to implement hook_token_info() is silly. Some messages have 'friend', other messages have 'person', other messages have 'person4' etc etc etc. Some config you have to do during runtime, when calling token_replace().

Sometimes there is no 1 common denominator, like 'status-message' and other times that common has completely different properties (since it can't always be an entity).

#1920688: Support multiple instances of the same token type in token replacement wants it too, but that's D8 so that's simpler, because entity info (type) is always included.

I created this function:

/**
 * Replace multiple tokens of unregistered names.
 *
 * @see token_replace()
 */
function token_replace_multiple($text, $data, $types, $options = array()) {
  // Replace base tokens.
  $text = token_replace($text, $data, $options);

  // Replace tokens with other names.
  foreach ($types as $token_name => $token_type) {
    $text = preg_replace('#\[' . $token_name . '([[:])#', '[' . $token_type . '$1', $text);
    $text = token_replace($text, array($token_type => $data[$token_name]), $options);
  }

  return $text;
}

So you can do:

$node1 = node_load(
$text = 'I'm a text with a node title: [node1:title] and another node title: [node2:title].';
$text = token_replace($text, compact('node1', 'node2'), array('node1' => 'node', 'node2' => 'node'));

Unfortunately that requires 3 token_replace() calls, but it's the best I could come up with in 11 minutes.

dave reid’s picture

Status: Needs review » Closed (fixed)

Please file as a separate feature request rather than re-opening a long-closed issue.

xaris.tsimpouris’s picture

I know this is an old one, but I would like to post what I did to help others to a different direction.
What I wanted to do is create two new groups of type user in a custom module (referrer/recipient) in order to create customised emails between two accounts for a new invitations system. This is what I came up with.

function invitations_token_info() {
  $referrer = array(
    'name' => t('Referrer'),
    'description' => t('Tokens related to referrer account.'),
    'needs-data' => 'referrer',
  );

  $recipient = array(
    'name' => t('Recipient'),
    'description' => t('Tokens related to recipient account.'),
    'needs-data' => 'recipient',
  );

  return array(
    'types' => array('referrer' => $referrer, 'recipient' => $recipient),
    'tokens' => array('referrer' => array(), 'recipient' => array()),
  );
}

function invitations_token_info_alter(&$data) {
  $data['tokens']['referrer'] = $data['tokens']['user'];
  $data['tokens']['recipient'] = $data['tokens']['user'];
}

function invitations_tokens($type, $tokens, array $data = array(), array $options = array()) {
  if ($type == 'referrer' && isset($data['referrer'])) {
    $data['user'] = clone $data['referrer'];
    return module_invoke_all('tokens', 'user', $tokens, $data, $options);
  }
  if ($type == 'recipient' && isset($data['recipient'])) {
    $data['user'] = clone $data['recipient'];
    return module_invoke_all('tokens', 'user', $tokens, $data, $options);
  }
}
  • invitations_token_info: Creates the new groups to be shown
  • invitations_token_info_alter: Clones all existing tokens of user type to the new ones
  • invitations_tokens: redirects all custom tokens towards the user group

With the above idea, I have fully capable new groups, that are shown in the token list and work as expected.
Hope it helps.