2
// $Id: token.module,v 1.7.4.8 2008/07/14 19:15:10 greggles Exp $
6
* The Token API module.
8
* The Token module provides an API for providing tokens to other modules.
9
* Tokens are small bits of text that can be placed into larger documents
10
* via simple placeholders, like %site-name or [user].
15
function token_theme() {
17
'token_help' => array(
18
'arguments' => array('type' => 'all', 'prefix' => '[', 'suffix' => ']')
24
* For a given context, builds a formatted list of tokens and descriptions
25
* of their replacement values.
28
* The token types to display documentation for. Defaults to 'all'.
30
* The prefix your module will use when parsing tokens. Defaults to '['
32
* The suffix your module will use when parsing tokens. Defaults to ']'
33
* @return An HTML table containing the formatting docs.
35
function theme_token_help($type = 'all', $prefix = '[', $suffix = ']') {
37
$full_list = token_get_list($type);
39
$headers = array(t('Token'), t('Replacement value'));
41
foreach ($full_list as $key => $category) {
42
$rows[] = array(array('data' => drupal_ucfirst($key) .' '. t('tokens'), 'class' => 'region', 'colspan' => 2));
43
foreach ($category as $token => $description) {
45
$row[] = $prefix . $token . $suffix;
46
$row[] = $description;
51
$output = theme('table', $headers, $rows, array('class' => 'description'));
56
* Sample implementation of hook_token_values().
59
* A flag indicating the class of substitution tokens to use. If an
60
* object is passed in the second param, 'type' should contain the
61
* object's type. For example, 'node', 'comment', or 'user'. If your
62
* implemention of the hook inserts globally applicable tokens that
63
* do not depend on a particular object, it should only return values
64
* when $type is 'global'.
66
* Optionally, the object to use for building substitution values.
67
* A node, comment, user, etc.
69
* A keyed array containing the substitution tokens and the substition
70
* values for the passed-in type and object.
72
function token_token_values($type, $object = NULL) {
79
$values['user-name'] = $user->uid ? $user->name : variable_get('anonymous', t('Anonymous'));
80
$values['user-id'] = $user->uid ? $user->uid : 0;
81
$values['user-mail'] = $user->uid ? $user->mail : '';
82
$values['site-url'] = $base_url;
83
$values['site-name'] = variable_get('site_name', t('Drupal'));
84
$values['site-slogan'] = variable_get('site_slogan', '');
85
$values['site-mission'] = filter_xss_admin(variable_get('site_mission', ''));
86
$values['site-mail'] = variable_get('site_mail', '');
87
$values['site-date'] = format_date(time(), 'short', '', variable_get('date_default_timezone', 0));
94
* Sample implementation of hook_token_list(). Documents the individual
95
* tokens handled by your module.
98
* A flag indicating the class of substitution tokens to return
99
* information on. If this is set to 'all', a complete list is being
100
* built and your module should return its full list, regardless of
101
* type. Global tokens should always be returned, regardless of the
104
* A keyed array listing the substitution tokens. Elements should be
105
* in the form of: $list[$type][$token] = $description
107
function token_token_list($type = 'all') {
108
$tokens['global']['user-name'] = t('The name of the currently logged in user.');
109
$tokens['global']['user-id'] = t('The user ID of the currently logged in user.');
110
$tokens['global']['user-mail'] = t('The email address of the currently logged in user.');
111
$tokens['global']['site-url'] = t('The url of the current Drupal website.');
112
$tokens['global']['site-name'] = t('The name of the current Drupal website.');
113
$tokens['global']['site-slogan'] = t('The slogan of the current Drupal website.');
114
$tokens['global']['site-mission'] = t('The mission of the current Drupal website.');
115
$tokens['global']['site-mail'] = t('The contact email address for the current Drupal website.');
116
$tokens['global']['site-date'] = t("The current date on the site's server.");
121
* General function to include the files that token relies on for the real work.
124
function token_include() {
125
$path = drupal_get_path('module', 'token');
126
require_once("$path/token_node.inc");
127
require_once("$path/token_user.inc");
128
if (module_exists('taxonomy')) {
129
require_once("$path/token_taxonomy.inc");
131
if (module_exists('comment')) {
132
require_once("$path/token_comment.inc");
138
* Return the value of $original, with all instances of placeholder
139
* tokens replaced by their proper values. To replace mutliple types
140
* at once see token_replace_multiple().
143
* A string, or an array of strings, to perform token substitutions
146
* A flag indicating the class of substitution tokens to use. If an
147
* object is passed in the second param, 'type' should contain the
148
* object's type. For example, 'node', 'comment', or 'user'. If no
149
* type is specified, only 'global' site-wide substitution tokens are
152
* Optionally, the object to use for building substitution values.
153
* A node, comment, user, etc.
155
* Character(s) to prepend to the token key before searching for
156
* matches. Defaults to an open-bracket.
158
* Character(s) to append to the token key before searching for
159
* matches. Defaults to a close-bracket.
160
* @return The modified version of $original, with all substitutions
163
function token_replace($original, $type = 'global', $object = NULL, $leading = '[', $trailing = ']', $options = array()) {
164
$full = token_get_values($type, $object, FALSE, $options);
165
return _token_replace_tokens($original, $full->tokens, $full->values, $leading, $trailing);
169
* Return the value of $original, with all instances of placeholder
170
* tokens replaced by their proper values. Contrary to token_replace(),
171
* this function supports replacing mutiple types.
174
* A string, or an array of strings, to perform token substitutions
177
* An array of substitution classes and optional objects. The key is
178
* a flag indicating the class of substitution tokens to use.
179
* If an object is passed as value, the key should contain the
180
* object's type. For example, 'node', 'comment', or 'user'. The
181
* object will be used for building substitution values. If no type
182
* is specified, only 'global' site-wide substitution tokens are built.
184
* Character(s) to prepend to the token key before searching for
185
* matches. Defaults to an open-bracket.
187
* Character(s) to append to the token key before searching for
188
* matches. Defaults to a close-bracket.
189
* @return The modified version of $original, with all substitutions
192
function token_replace_multiple($original, $types = array('global' => NULL), $leading = '[', $trailing = ']', $options = array()) {
193
$full = new stdClass();
194
$full->tokens = $full->values = array();
195
foreach ($types as $type => $object) {
196
$temp = token_get_values($type, $object, FALSE, $options);
197
$full->tokens = array_merge($full->tokens, $temp->tokens);
198
$full->values = array_merge($full->values, $temp->values);
200
return _token_replace_tokens($original, $full->tokens, $full->values, $leading, $trailing);
203
// Internally used function to replace tokens.
204
function _token_replace_tokens($original, $tokens, $values, $leading, $trailing) {
205
$tokens = token_prepare_tokens($tokens, $leading, $trailing);
206
return str_replace($tokens, $values, $original);
210
* Return a list of valid substitution tokens and their values for
211
* the specified type.
214
* A flag indicating the class of substitution tokens to use. If an
215
* object is passed in the second param, 'type' should contain the
216
* object's type. For example, 'node', 'comment', or 'user'. If no
217
* type is specified, only 'global' site-wide substitution tokens are
220
* Optionally, the object to use for building substitution values.
221
* A node, comment, user, etc.
223
* A keyed array containing the substitution tokens and the substition
224
* values for the passed-in type and object.
226
function token_get_values($type = 'global', $object = NULL, $flush = FALSE, $options = array()) {
230
// Flush the static token cache. Useful for processes that need to slog through
231
// huge numbers of tokens in a single execution cycle. Flushing it will keep
232
// them from burning through memory.
233
if ($flush || !isset($tokens)) {
237
// Since objects in PHP5 are always passed by reference, we ensure we're
238
// working on a copy of the object.
239
if (is_object($object)) {
240
$object = drupal_clone($object);
243
// Simple recursion check. This is to avoid content_view()'s potential
244
// for endless looping when a filter uses tokens, which load the content
245
// view, which calls the filter, which uses tokens, which...
247
// We'll allow things to get two levels deep, but bail out after that
248
// without performing any substitutions.
249
$result = new stdClass();
250
$result->tokens = array();
251
$result->values = array();
259
$id = _token_get_id($type, $object);
260
if (isset($tokens[$type][$id])) {
261
$tmp_tokens = $tokens[$type][$id];
264
$tmp_tokens = module_invoke_all('token_values', $type, $object, $options);
265
$tokens[$type][$id] = $tmp_tokens;
268
// Special-case global tokens, as we always want to be able to process
269
// those substitutions.
270
if (!isset($tokens['global']['default'])) {
271
$tokens['global']['default'] = module_invoke_all('token_values', 'global');
274
$all = array_merge($tokens['global']['default'], $tokens[$type][$id]);
276
$result = new stdClass();
277
$result->tokens = array_keys($all);
278
$result->values = array_values($all);
286
* A helper function that retrieves all currently exposed tokens,
287
* and merges them recursively. This is only necessary when building
288
* the token listing -- during actual value replacement, only tokens
289
* in a particular domain are requested and a normal array_marge() is
293
* A flag indicating the class of substitution tokens to use. If an
294
* object is passed in the second param, 'type' should contain the
295
* object's type. For example, 'node', 'comment', or 'user'. If no
296
* type is specified, only 'global' site-wide substitution tokens are
299
* The array of usable tokens and their descriptions, organized by
302
function token_get_list($type = 'all') {
305
foreach (module_implements('token_list') as $module) {
306
$function = $module .'_token_list';
307
$result = $function($type);
308
if (is_array($result)) {
309
foreach ($result as $category => $tokens) {
310
foreach ($tokens as $token => $title) {
311
$return[$category][$token] = $title;
320
* A helper function that transforms all the elements of an
321
* array. Used to change the delimiter style from brackets to
322
* percent symbols etc.
325
* The array of tokens keys with no delimiting chacaters
327
* Character(s) to prepend to the token key before searching for
328
* matches. Defaults to an open-bracket.
330
* Character(s) to append to the token key before searching for
331
* matches. Defaults to a close-bracket.
333
* The array of token keys, each wrapped in the specified
336
function token_prepare_tokens($tokens = array(), $leading = '[', $trailing = ']') {
337
foreach ($tokens as $key => $value) {
338
$tokens[$key] = $leading . $value . $trailing;
343
// Internal utility function used for static caching. There are
344
// almost certainly better ways to do this, but for the moment it's
346
function _token_get_id($type = 'global', $object = NULL) {
347
if (!isset($object)) {
358
return crc32(serialize($object));