Mercurial > hg > rr-repo
comparison sites/all/modules/token/token.tokens.inc @ 0:ff03f76ab3fe
initial version
author | danieleb <danielebarchiesi@me.com> |
---|---|
date | Wed, 21 Aug 2013 18:51:11 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:ff03f76ab3fe |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * @file | |
5 * Token callbacks for the token module. | |
6 */ | |
7 | |
8 /** | |
9 * Implements hook_token_info_alter(). | |
10 */ | |
11 function token_token_info_alter(&$info) { | |
12 // Force 'date' type tokens to require input and add a 'current-date' type. | |
13 // @todo Remove when http://drupal.org/node/943028 is fixed. | |
14 $info['types']['date']['needs-data'] = 'date'; | |
15 $info['types']['current-date'] = array( | |
16 'name' => t('Current date'), | |
17 'description' => t('Tokens related to the current date and time.'), | |
18 'type' => 'date', | |
19 ); | |
20 | |
21 // Add a 'dynamic' key to any tokens that have chained but dynamic tokens. | |
22 $info['tokens']['date']['custom']['dynamic'] = TRUE; | |
23 | |
24 // The [file:size] may not always return in kilobytes. | |
25 // @todo Remove when http://drupal.org/node/1193044 is fixed. | |
26 $info['tokens']['file']['size']['description'] = t('The size of the file.'); | |
27 | |
28 // Remove deprecated tokens from being listed. | |
29 unset($info['tokens']['node']['tnid']); | |
30 unset($info['tokens']['node']['type']); | |
31 unset($info['tokens']['node']['type-name']); | |
32 | |
33 // Support 'url' type tokens for core tokens. | |
34 if (isset($info['tokens']['comment']['url']) && module_exists('comment')) { | |
35 $info['tokens']['comment']['url']['type'] = 'url'; | |
36 } | |
37 $info['tokens']['node']['url']['type'] = 'url'; | |
38 if (isset($info['tokens']['term']['url']) && module_exists('taxonomy')) { | |
39 $info['tokens']['term']['url']['type'] = 'url'; | |
40 } | |
41 $info['tokens']['user']['url']['type'] = 'url'; | |
42 | |
43 // Add [token:url] tokens for any URI-able entities. | |
44 $entities = entity_get_info(); | |
45 foreach ($entities as $entity => $entity_info) { | |
46 if (!isset($entity_info['token type'])) { | |
47 continue; | |
48 } | |
49 | |
50 $token_type = $entity_info['token type']; | |
51 if (!isset($info['types'][$token_type]) || !isset($info['tokens'][$token_type])) { | |
52 continue; | |
53 } | |
54 | |
55 // Add [entity:url] tokens if they do not already exist. | |
56 // @todo Support entity:label | |
57 if (!isset($info['tokens'][$token_type]['url']) && !empty($entity_info['uri callback'])) { | |
58 $info['tokens'][$token_type]['url'] = array( | |
59 'name' => t('URL'), | |
60 'description' => t('The URL of the @entity.', array('@entity' => drupal_strtolower($entity_info['label']))), | |
61 'module' => 'token', | |
62 'type' => 'url', | |
63 ); | |
64 } | |
65 | |
66 // Add [entity:original] tokens if they do not already exist. | |
67 if (!isset($info['tokens'][$token_type]['original'])) { | |
68 $info['tokens'][$token_type]['original'] = array( | |
69 'name' => t('Original @entity', array('@entity' => drupal_strtolower($entity_info['label']))), | |
70 'description' => t('The original @entity data if the @entity is being updated or saved.', array('@entity' => drupal_strtolower($entity_info['label']))), | |
71 'module' => 'token', | |
72 'type' => $token_type, | |
73 ); | |
74 } | |
75 } | |
76 | |
77 // Add support for custom date formats. | |
78 // @todo Remove when http://drupal.org/node/1173706 is fixed. | |
79 $date_format_types = system_get_date_types(); | |
80 foreach ($date_format_types as $date_format_type => $date_format_type_info) { | |
81 if (!isset($info['tokens']['date'][$date_format_type])) { | |
82 $info['tokens']['date'][$date_format_type] = array( | |
83 'name' => check_plain($date_format_type_info['title']), | |
84 'description' => t("A date in '@type' format. (%date)", array('@type' => $date_format_type, '%date' => format_date(REQUEST_TIME, $date_format_type))), | |
85 'module' => 'token', | |
86 ); | |
87 } | |
88 } | |
89 } | |
90 | |
91 /** | |
92 * Implements hook_token_info(). | |
93 */ | |
94 function token_token_info() { | |
95 // Node tokens. | |
96 $info['tokens']['node']['source'] = array( | |
97 'name' => t('Translation source node'), | |
98 'description' => t("The source node for this current node's translation set."), | |
99 'type' => 'node', | |
100 ); | |
101 $info['tokens']['node']['log'] = array( | |
102 'name' => t('Revision log message'), | |
103 'description' => t('The explanation of the most recent changes made to the node.'), | |
104 ); | |
105 $info['tokens']['node']['content-type'] = array( | |
106 'name' => t('Content type'), | |
107 'description' => t('The content type of the node.'), | |
108 'type' => 'content-type', | |
109 ); | |
110 | |
111 // Content type tokens. | |
112 $info['types']['content-type'] = array( | |
113 'name' => t('Content types'), | |
114 'description' => t('Tokens related to content types.'), | |
115 'needs-data' => 'node_type', | |
116 ); | |
117 $info['tokens']['content-type']['name'] = array( | |
118 'name' => t('Name'), | |
119 'description' => t('The name of the content type.'), | |
120 ); | |
121 $info['tokens']['content-type']['machine-name'] = array( | |
122 'name' => t('Machine-readable name'), | |
123 'description' => t('The unique machine-readable name of the content type.'), | |
124 ); | |
125 $info['tokens']['content-type']['description'] = array( | |
126 'name' => t('Description'), | |
127 'description' => t('The optional description of the content type.'), | |
128 ); | |
129 $info['tokens']['content-type']['node-count'] = array( | |
130 'name' => t('Node count'), | |
131 'description' => t('The number of nodes belonging to the content type.'), | |
132 ); | |
133 $info['tokens']['content-type']['edit-url'] = array( | |
134 'name' => t('Edit URL'), | |
135 'description' => t("The URL of the content type's edit page."), | |
136 // 'type' => 'url', | |
137 ); | |
138 | |
139 // Taxonomy term and vocabulary tokens. | |
140 if (module_exists('taxonomy')) { | |
141 $info['tokens']['term']['edit-url'] = array( | |
142 'name' => t('Edit URL'), | |
143 'description' => t("The URL of the taxonomy term's edit page."), | |
144 // 'type' => 'url', | |
145 ); | |
146 $info['tokens']['term']['parents'] = array( | |
147 'name' => t('Parents'), | |
148 'description' => t("An array of all the term's parents, starting with the root."), | |
149 'type' => 'array', | |
150 ); | |
151 $info['tokens']['term']['root'] = array( | |
152 'name' => t('Root term'), | |
153 'description' => t("The root term of the taxonomy term."), | |
154 'type' => 'term', | |
155 ); | |
156 | |
157 $info['tokens']['vocabulary']['machine-name'] = array( | |
158 'name' => t('Machine-readable name'), | |
159 'description' => t('The unique machine-readable name of the vocabulary.'), | |
160 ); | |
161 $info['tokens']['vocabulary']['edit-url'] = array( | |
162 'name' => t('Edit URL'), | |
163 'description' => t("The URL of the vocabulary's edit page."), | |
164 // 'type' => 'url', | |
165 ); | |
166 } | |
167 | |
168 // File tokens. | |
169 $info['tokens']['file']['basename'] = array( | |
170 'name' => t('Base name'), | |
171 'description' => t('The base name of the file.'), | |
172 ); | |
173 $info['tokens']['file']['extension'] = array( | |
174 'name' => t('Extension'), | |
175 'description' => t('The extension of the file.'), | |
176 ); | |
177 $info['tokens']['file']['size-raw'] = array( | |
178 'name' => t('File byte size'), | |
179 'description' => t('The size of the file, in bytes.'), | |
180 ); | |
181 | |
182 // User tokens. | |
183 // Add information on the restricted user tokens. | |
184 $info['tokens']['user']['cancel-url'] = array( | |
185 'name' => t('Account cancellation URL'), | |
186 'description' => t('The URL of the confirm delete page for the user account.'), | |
187 'restricted' => TRUE, | |
188 // 'type' => 'url', | |
189 ); | |
190 $info['tokens']['user']['one-time-login-url'] = array( | |
191 'name' => t('One-time login URL'), | |
192 'description' => t('The URL of the one-time login page for the user account.'), | |
193 'restricted' => TRUE, | |
194 // 'type' => 'url', | |
195 ); | |
196 if (variable_get('user_pictures', 0)) { | |
197 $info['tokens']['user']['picture'] = array( | |
198 'name' => t('Picture'), | |
199 'description' => t('The picture of the user.'), | |
200 'type' => 'file', | |
201 ); | |
202 } | |
203 $info['tokens']['user']['roles'] = array( | |
204 'name' => t('Roles'), | |
205 'description' => t('The user roles associated with the user account.'), | |
206 'type' => 'array', | |
207 ); | |
208 | |
209 // Current user tokens. | |
210 $info['tokens']['current-user']['ip-address'] = array( | |
211 'name' => t('IP address'), | |
212 'description' => 'The IP address of the current user.', | |
213 ); | |
214 | |
215 // Menu link tokens (work regardless if menu module is enabled or not). | |
216 $info['types']['menu-link'] = array( | |
217 'name' => t('Menu links'), | |
218 'description' => t('Tokens related to menu links.'), | |
219 'needs-data' => 'menu-link', | |
220 ); | |
221 $info['tokens']['menu-link']['mlid'] = array( | |
222 'name' => t('Link ID'), | |
223 'description' => t('The unique ID of the menu link.'), | |
224 ); | |
225 $info['tokens']['menu-link']['title'] = array( | |
226 'name' => t('Title'), | |
227 'description' => t('The title of the menu link.'), | |
228 ); | |
229 $info['tokens']['menu-link']['url'] = array( | |
230 'name' => t('URL'), | |
231 'description' => t('The URL of the menu link.'), | |
232 'type' => 'url', | |
233 ); | |
234 $info['tokens']['menu-link']['parent'] = array( | |
235 'name' => t('Parent'), | |
236 'description' => t("The menu link's parent."), | |
237 'type' => 'menu-link', | |
238 ); | |
239 $info['tokens']['menu-link']['parents'] = array( | |
240 'name' => t('Parents'), | |
241 'description' => t("An array of all the menu link's parents, starting with the root."), | |
242 'type' => 'array', | |
243 ); | |
244 $info['tokens']['menu-link']['root'] = array( | |
245 'name' => t('Root'), | |
246 'description' => t("The menu link's root."), | |
247 'type' => 'menu-link', | |
248 ); | |
249 | |
250 // Current page tokens. | |
251 $info['types']['current-page'] = array( | |
252 'name' => t('Current page'), | |
253 'description' => t('Tokens related to the current page request.'), | |
254 ); | |
255 $info['tokens']['current-page']['title'] = array( | |
256 'name' => t('Title'), | |
257 'description' => t('The title of the current page.'), | |
258 ); | |
259 $info['tokens']['current-page']['url'] = array( | |
260 'name' => t('URL'), | |
261 'description' => t('The URL of the current page.'), | |
262 'type' => 'url', | |
263 ); | |
264 $info['tokens']['current-page']['page-number'] = array( | |
265 'name' => t('Page number'), | |
266 'description' => t('The page number of the current page when viewing paged lists.'), | |
267 ); | |
268 $info['tokens']['current-page']['query'] = array( | |
269 'name' => t('Query string value'), | |
270 'description' => t('The value of a specific query string field of the current page.'), | |
271 'dynamic' => TRUE, | |
272 ); | |
273 | |
274 // URL tokens. | |
275 $info['types']['url'] = array( | |
276 'name' => t('URL'), | |
277 'description' => t('Tokens related to URLs.'), | |
278 'needs-data' => 'path', | |
279 ); | |
280 $info['tokens']['url']['path'] = array( | |
281 'name' => t('Path'), | |
282 'description' => t('The path component of the URL.'), | |
283 ); | |
284 $info['tokens']['url']['relative'] = array( | |
285 'name' => t('Relative URL'), | |
286 'description' => t('The relative URL.'), | |
287 ); | |
288 $info['tokens']['url']['absolute'] = array( | |
289 'name' => t('Absolute URL'), | |
290 'description' => t('The absolute URL.'), | |
291 ); | |
292 $info['tokens']['url']['brief'] = array( | |
293 'name' => t('Brief URL'), | |
294 'description' => t('The URL without the protocol and trailing backslash.'), | |
295 ); | |
296 $info['tokens']['url']['unaliased'] = array( | |
297 'name' => t('Unaliased URL'), | |
298 'description' => t('The unaliased URL.'), | |
299 'type' => 'url', | |
300 ); | |
301 $info['tokens']['url']['args'] = array( | |
302 'name' => t('Arguments'), | |
303 'description' => t("The specific argument of the current page (e.g. 'arg:1' on the page 'node/1' returns '1')."), | |
304 'type' => 'array', | |
305 ); | |
306 | |
307 // Array tokens. | |
308 $info['types']['array'] = array( | |
309 'name' => t('Array'), | |
310 'description' => t('Tokens related to arrays of strings.'), | |
311 'needs-data' => 'array', | |
312 ); | |
313 $info['tokens']['array']['first'] = array( | |
314 'name' => t('First'), | |
315 'description' => t('The first element of the array.'), | |
316 ); | |
317 $info['tokens']['array']['last'] = array( | |
318 'name' => t('Last'), | |
319 'description' => t('The last element of the array.'), | |
320 ); | |
321 $info['tokens']['array']['count'] = array( | |
322 'name' => t('Count'), | |
323 'description' => t('The number of elements in the array.'), | |
324 ); | |
325 $info['tokens']['array']['reversed'] = array( | |
326 'name' => t('Reversed'), | |
327 'description' => t('The array reversed.'), | |
328 'type' => 'array', | |
329 ); | |
330 $info['tokens']['array']['keys'] = array( | |
331 'name' => t('Keys'), | |
332 'description' => t('The array of keys of the array.'), | |
333 'type' => 'array', | |
334 ); | |
335 $info['tokens']['array']['join'] = array( | |
336 'name' => t('Imploded'), | |
337 'description' => t('The values of the array joined together with a custom string in-between each value.'), | |
338 'dynamic' => TRUE, | |
339 ); | |
340 $info['tokens']['array']['value'] = array( | |
341 'name' => t('Value'), | |
342 'description' => t('The specific value of the array.'), | |
343 'dynamic' => TRUE, | |
344 ); | |
345 | |
346 // Random tokens. | |
347 $info['types']['random'] = array( | |
348 'name' => t('Random'), | |
349 'description' => ('Tokens related to random data.'), | |
350 ); | |
351 $info['tokens']['random']['number'] = array( | |
352 'name' => t('Number'), | |
353 'description' => t('A random number from 0 to @max.', array('@max' => mt_getrandmax())), | |
354 ); | |
355 $info['tokens']['random']['hash'] = array( | |
356 'name' => t('Hash'), | |
357 'description' => t('A random hash. The possible hashing algorithms are: @hash-algos.', array('@hash-algos' => implode(', ', hash_algos()))), | |
358 'dynamic' => TRUE, | |
359 ); | |
360 | |
361 return $info; | |
362 } | |
363 | |
364 /** | |
365 * Implements hook_tokens(). | |
366 */ | |
367 function token_tokens($type, $tokens, array $data = array(), array $options = array()) { | |
368 $replacements = array(); | |
369 | |
370 $url_options = array('absolute' => TRUE); | |
371 if (isset($options['language'])) { | |
372 $url_options['language'] = $options['language']; | |
373 $language_code = $options['language']->language; | |
374 } | |
375 else { | |
376 $language_code = NULL; | |
377 } | |
378 | |
379 $sanitize = !empty($options['sanitize']); | |
380 | |
381 // Date tokens. | |
382 if ($type == 'date') { | |
383 $date = !empty($data['date']) ? $data['date'] : REQUEST_TIME; | |
384 | |
385 // @todo Remove when http://drupal.org/node/1173706 is fixed. | |
386 $date_format_types = system_get_date_types(); | |
387 foreach ($tokens as $name => $original) { | |
388 if (isset($date_format_types[$name]) && _token_module('date', $name) == 'token') { | |
389 $replacements[$original] = format_date($date, $name, '', NULL, $language_code); | |
390 } | |
391 } | |
392 } | |
393 | |
394 // Current date tokens. | |
395 // @todo Remove when http://drupal.org/node/943028 is fixed. | |
396 if ($type == 'current-date') { | |
397 $replacements += token_generate('date', $tokens, array('date' => REQUEST_TIME), $options); | |
398 } | |
399 | |
400 // Comment tokens. | |
401 if ($type == 'comment' && !empty($data['comment'])) { | |
402 $comment = $data['comment']; | |
403 | |
404 // Chained token relationships. | |
405 if (($url_tokens = token_find_with_prefix($tokens, 'url'))) { | |
406 $replacements += token_generate('url', $url_tokens, entity_uri('comment', $comment), $options); | |
407 } | |
408 } | |
409 | |
410 // Node tokens. | |
411 if ($type == 'node' && !empty($data['node'])) { | |
412 $node = $data['node']; | |
413 | |
414 foreach ($tokens as $name => $original) { | |
415 switch ($name) { | |
416 case 'source': | |
417 if (!empty($node->tnid) && $source_node = node_load($node->tnid)) { | |
418 $title = $source_node->title; | |
419 $replacements[$original] = $sanitize ? filter_xss($title) : $title; | |
420 } | |
421 break; | |
422 case 'log': | |
423 $replacements[$original] = $sanitize ? filter_xss($node->log) : $node->log; | |
424 break; | |
425 case 'content-type': | |
426 $type_name = node_type_get_name($node); | |
427 $replacements[$original] = $sanitize ? check_plain($type_name) : $type_name; | |
428 break; | |
429 } | |
430 } | |
431 | |
432 // Chained token relationships. | |
433 if (!empty($node->tnid) && ($source_tokens = token_find_with_prefix($tokens, 'source')) && $source_node = node_load($node->tnid)) { | |
434 $replacements += token_generate('node', $source_tokens, array('node' => $source_node), $options); | |
435 } | |
436 if (($node_type_tokens = token_find_with_prefix($tokens, 'content-type')) && $node_type = node_type_load($node->type)) { | |
437 $replacements += token_generate('content-type', $node_type_tokens, array('node_type' => $node_type), $options); | |
438 } | |
439 if (($url_tokens = token_find_with_prefix($tokens, 'url'))) { | |
440 $replacements += token_generate('url', $url_tokens, entity_uri('node', $node), $options); | |
441 } | |
442 } | |
443 | |
444 // Content type tokens. | |
445 if ($type == 'content-type' && !empty($data['node_type'])) { | |
446 $node_type = $data['node_type']; | |
447 | |
448 foreach ($tokens as $name => $original) { | |
449 switch ($name) { | |
450 case 'name': | |
451 $replacements[$original] = $sanitize ? check_plain($node_type->name) : $node_type->name; | |
452 break; | |
453 case 'machine-name': | |
454 // This is a machine name so does not ever need to be sanitized. | |
455 $replacements[$original] = $node_type->type; | |
456 break; | |
457 case 'description': | |
458 $replacements[$original] = $sanitize ? filter_xss($node_type->description) : $node_type->description; | |
459 break; | |
460 case 'node-count': | |
461 $query = db_select('node'); | |
462 $query->condition('type', $node_type->type); | |
463 $query->addTag('node_type_node_count'); | |
464 $count = $query->countQuery()->execute()->fetchField(); | |
465 $replacements[$original] = (int) $count; | |
466 break; | |
467 case 'edit-url': | |
468 $replacements[$original] = url("admin/structure/types/manage/{$node_type->type}", $url_options); | |
469 break; | |
470 } | |
471 } | |
472 } | |
473 | |
474 // Taxonomy term tokens. | |
475 if ($type == 'term' && !empty($data['term'])) { | |
476 $term = $data['term']; | |
477 | |
478 foreach ($tokens as $name => $original) { | |
479 switch ($name) { | |
480 case 'edit-url': | |
481 $replacements[$original] = url("taxonomy/term/{$term->tid}/edit", $url_options); | |
482 break; | |
483 | |
484 case 'parents': | |
485 if ($parents = token_taxonomy_term_load_all_parents($term->tid)) { | |
486 $replacements[$original] = token_render_array($parents, $options); | |
487 } | |
488 break; | |
489 | |
490 case 'root': | |
491 $parents = taxonomy_get_parents_all($term->tid); | |
492 $root_term = end($parents); | |
493 if ($root_term->tid != $term->tid) { | |
494 $replacements[$original] = $sanitize ? check_plain($root_term->name) : $root_term->name; | |
495 } | |
496 break; | |
497 } | |
498 } | |
499 | |
500 // Chained token relationships. | |
501 if (($url_tokens = token_find_with_prefix($tokens, 'url'))) { | |
502 $replacements += token_generate('url', $url_tokens, entity_uri('taxonomy_term', $term), $options); | |
503 } | |
504 // [term:parents:*] chained tokens. | |
505 if ($parents_tokens = token_find_with_prefix($tokens, 'parents')) { | |
506 if ($parents = token_taxonomy_term_load_all_parents($term->tid)) { | |
507 $replacements += token_generate('array', $parents_tokens, array('array' => $parents), $options); | |
508 } | |
509 } | |
510 if ($root_tokens = token_find_with_prefix($tokens, 'root')) { | |
511 $parents = taxonomy_get_parents_all($term->tid); | |
512 $root_term = end($parents); | |
513 if ($root_term->tid != $term->tid) { | |
514 $replacements += token_generate('term', $root_tokens, array('term' => $root_term), $options); | |
515 } | |
516 } | |
517 } | |
518 | |
519 // Vocabulary tokens. | |
520 if ($type == 'vocabulary' && !empty($data['vocabulary'])) { | |
521 $vocabulary = $data['vocabulary']; | |
522 | |
523 foreach ($tokens as $name => $original) { | |
524 switch ($name) { | |
525 case 'machine-name': | |
526 // This is a machine name so does not ever need to be sanitized. | |
527 $replacements[$original] = $vocabulary->machine_name; | |
528 break; | |
529 case 'edit-url': | |
530 $replacements[$original] = url("admin/structure/taxonomy/{$vocabulary->machine_name}/edit", $url_options); | |
531 break; | |
532 } | |
533 } | |
534 } | |
535 | |
536 // File tokens. | |
537 if ($type == 'file' && !empty($data['file'])) { | |
538 $file = $data['file']; | |
539 | |
540 foreach ($tokens as $name => $original) { | |
541 switch ($name) { | |
542 case 'basename': | |
543 $basename = pathinfo($file->uri, PATHINFO_BASENAME); | |
544 $replacements[$original] = $sanitize ? check_plain($basename) : $basename; | |
545 break; | |
546 case 'extension': | |
547 $extension = pathinfo($file->uri, PATHINFO_EXTENSION); | |
548 $replacements[$original] = $sanitize ? check_plain($extension) : $extension; | |
549 break; | |
550 case 'size-raw': | |
551 $replacements[$original] = (int) $file->filesize; | |
552 break; | |
553 } | |
554 } | |
555 } | |
556 | |
557 // User tokens. | |
558 if ($type == 'user' && !empty($data['user'])) { | |
559 $account = $data['user']; | |
560 | |
561 foreach ($tokens as $name => $original) { | |
562 switch ($name) { | |
563 case 'picture': | |
564 if (variable_get('user_pictures', 0)) { | |
565 $replacements[$original] = theme('user_picture', array('account' => $account)); | |
566 } | |
567 break; | |
568 case 'roles': | |
569 // The roles array may be set from checkbox values so ensure it always | |
570 // has 'proper' data with the role names. | |
571 $roles = array_intersect_key(user_roles(), $account->roles); | |
572 $replacements[$original] = token_render_array($roles, $options); | |
573 break; | |
574 } | |
575 } | |
576 | |
577 // Chained token relationships. | |
578 if (variable_get('user_pictures', 0) && !empty($account->picture) && ($picture_tokens = token_find_with_prefix($tokens, 'picture'))) { | |
579 // @todo Remove when core bug http://drupal.org/node/978028 is fixed. | |
580 $account->picture->description = ''; | |
581 $replacements += token_generate('file', $picture_tokens, array('file' => $account->picture), $options); | |
582 } | |
583 if ($url_tokens = token_find_with_prefix($tokens, 'url')) { | |
584 $replacements += token_generate('url', $url_tokens, entity_uri('user', $account), $options); | |
585 } | |
586 if ($role_tokens = token_find_with_prefix($tokens, 'roles')) { | |
587 // The roles array may be set from checkbox values so ensure it always | |
588 // has 'proper' data with the role names. | |
589 $roles = array_intersect_key(user_roles(), $account->roles); | |
590 $replacements += token_generate('array', $role_tokens, array('array' => $roles), $options); | |
591 } | |
592 } | |
593 | |
594 // Current user tokens. | |
595 if ($type == 'current-user') { | |
596 foreach ($tokens as $name => $original) { | |
597 switch ($name) { | |
598 case 'ip-address': | |
599 $ip = ip_address(); | |
600 $replacements[$original] = $sanitize ? check_plain($ip) : $ip; | |
601 break; | |
602 } | |
603 } | |
604 } | |
605 | |
606 // Menu link tokens. | |
607 if ($type == 'menu-link' && !empty($data['menu-link'])) { | |
608 $link = (array) $data['menu-link']; | |
609 | |
610 if (!isset($link['title'])) { | |
611 // Re-load the link if it was not loaded via token_menu_link_load(). | |
612 $link = token_menu_link_load($link['mlid']); | |
613 } | |
614 | |
615 foreach ($tokens as $name => $original) { | |
616 switch ($name) { | |
617 case 'mlid': | |
618 $replacements[$original] = $link['mlid']; | |
619 break; | |
620 case 'title': | |
621 $replacements[$original] = $sanitize ? check_plain($link['title']) : $link['title']; | |
622 break; | |
623 case 'url': | |
624 $replacements[$original] = url($link['href'], $url_options); | |
625 break; | |
626 case 'parent': | |
627 if (!empty($link['plid']) && $parent = token_menu_link_load($link['plid'])) { | |
628 $replacements[$original] = $sanitize ? check_plain($parent['title']) : $parent['title']; | |
629 } | |
630 break; | |
631 case 'parents': | |
632 if ($parents = token_menu_link_load_all_parents($link['mlid'])) { | |
633 $replacements[$original] = token_render_array($parents, $options); | |
634 } | |
635 break; | |
636 case 'root'; | |
637 if (!empty($link['p1']) && $link['p1'] != $link['mlid'] && $root = token_menu_link_load($link['p1'])) { | |
638 $replacements[$original] = $sanitize ? check_plain($root['title']) : $root['title']; | |
639 } | |
640 break; | |
641 } | |
642 } | |
643 | |
644 // Chained token relationships. | |
645 if (!empty($link['plid']) && ($source_tokens = token_find_with_prefix($tokens, 'parent')) && $parent = token_menu_link_load($link['plid'])) { | |
646 $replacements += token_generate('menu-link', $source_tokens, array('menu-link' => $parent), $options); | |
647 } | |
648 // [menu-link:parents:*] chained tokens. | |
649 if ($parents_tokens = token_find_with_prefix($tokens, 'parents')) { | |
650 if ($parents = token_menu_link_load_all_parents($link['mlid'])) { | |
651 $replacements += token_generate('array', $parents_tokens, array('array' => $parents), $options); | |
652 } | |
653 } | |
654 if (!empty($link['p1']) && $link['p1'] != $link['mlid'] && ($root_tokens = token_find_with_prefix($tokens, 'root')) && $root = token_menu_link_load($link['p1'])) { | |
655 $replacements += token_generate('menu-link', $root_tokens, array('menu-link' => $root), $options); | |
656 } | |
657 if ($url_tokens = token_find_with_prefix($tokens, 'url')) { | |
658 $replacements += token_generate('url', $url_tokens, array('path' => $link['href']), $options); | |
659 } | |
660 } | |
661 | |
662 // Current page tokens. | |
663 if ($type == 'current-page') { | |
664 $current_path = current_path(); | |
665 | |
666 foreach ($tokens as $name => $original) { | |
667 switch ($name) { | |
668 case 'title': | |
669 $title = drupal_get_title(); | |
670 $replacements[$original] = $sanitize ? $title : decode_entities($title); | |
671 break; | |
672 case 'url': | |
673 $replacements[$original] = url($current_path, $url_options); | |
674 break; | |
675 case 'page-number': | |
676 if ($page = filter_input(INPUT_GET, 'page')) { | |
677 // @see PagerDefault::execute() | |
678 $pager_page_array = explode(',', $page); | |
679 $page = $pager_page_array[0]; | |
680 } | |
681 $replacements[$original] = (int) $page + 1; | |
682 break; | |
683 } | |
684 } | |
685 | |
686 // @deprecated | |
687 // [current-page:arg] dynamic tokens. | |
688 if ($arg_tokens = token_find_with_prefix($tokens, 'arg')) { | |
689 foreach ($arg_tokens as $name => $original) { | |
690 if (is_numeric($name) && ($arg = arg($name)) && isset($arg)) { | |
691 $replacements[$original] = $sanitize ? check_plain($arg) : $arg; | |
692 } | |
693 } | |
694 } | |
695 | |
696 // [current-page:query] dynamic tokens. | |
697 if ($query_tokens = token_find_with_prefix($tokens, 'query')) { | |
698 foreach ($query_tokens as $name => $original) { | |
699 // @todo Should this use filter_input()? | |
700 if (isset($_GET[$name])) { | |
701 $replacements[$original] = $sanitize ? check_plain($_GET[$name]) : $_GET[$name]; | |
702 } | |
703 } | |
704 } | |
705 | |
706 // Chained token relationships. | |
707 if ($url_tokens = token_find_with_prefix($tokens, 'url')) { | |
708 $replacements += token_generate('url', $url_tokens, array('path' => $current_path), $options); | |
709 } | |
710 } | |
711 | |
712 // URL tokens. | |
713 if ($type == 'url' && !empty($data['path'])) { | |
714 $path = $data['path']; | |
715 | |
716 if (isset($data['options'])) { | |
717 // Merge in the URL options if available. | |
718 $url_options = $data['options'] + $url_options; | |
719 } | |
720 | |
721 foreach ($tokens as $name => $original) { | |
722 switch ($name) { | |
723 case 'path': | |
724 $value = empty($url_options['alias']) ? drupal_get_path_alias($path, $language_code) : $path; | |
725 $replacements[$original] = $sanitize ? check_plain($value) : $value; | |
726 break; | |
727 case 'alias': | |
728 // @deprecated | |
729 $alias = drupal_get_path_alias($path, $language_code); | |
730 $replacements[$original] = $sanitize ? check_plain($alias) : $alias; | |
731 break; | |
732 case 'absolute': | |
733 $replacements[$original] = url($path, $url_options); | |
734 break; | |
735 case 'relative': | |
736 $replacements[$original] = url($path, array('absolute' => FALSE) + $url_options); | |
737 break; | |
738 case 'brief': | |
739 $replacements[$original] = preg_replace(array('!^https?://!', '!/$!'), '', url($path, $url_options)); | |
740 break; | |
741 case 'unaliased': | |
742 $replacements[$original] = url($path, array('alias' => TRUE) + $url_options); | |
743 break; | |
744 case 'args': | |
745 $value = empty($url_options['alias']) ? drupal_get_path_alias($path, $language_code) : $path; | |
746 $replacements[$original] = token_render_array(arg(NULL, $value), $options); | |
747 break; | |
748 } | |
749 } | |
750 | |
751 // [url:arg:*] chained tokens. | |
752 if ($arg_tokens = token_find_with_prefix($tokens, 'args')) { | |
753 $value = empty($url_options['alias']) ? drupal_get_path_alias($path, $language_code) : $path; | |
754 $replacements += token_generate('array', $arg_tokens, array('array' => arg(NULL, $value)), $options); | |
755 } | |
756 | |
757 // [url:unaliased:*] chained tokens. | |
758 if ($unaliased_tokens = token_find_with_prefix($tokens, 'unaliased')) { | |
759 $unaliased_token_data['path'] = $path; | |
760 $unaliased_token_data['options'] = isset($data['options']) ? $data['options'] : array(); | |
761 $unaliased_token_data['options']['alias'] = TRUE; | |
762 $replacements += token_generate('url', $unaliased_tokens, $unaliased_token_data, $options); | |
763 } | |
764 } | |
765 | |
766 // Entity tokens. | |
767 if (!empty($data[$type]) && $entity_type = token_get_entity_mapping('token', $type)) { | |
768 $entity = $data[$type]; | |
769 | |
770 // Sometimes taxonomy terms are not properly loaded. | |
771 // @see http://drupal.org/node/870528 | |
772 if ($entity_type == 'taxonomy_term' && !isset($entity->vocabulary_machine_name)) { | |
773 $entity->vocabulary_machine_name = db_query("SELECT machine_name FROM {taxonomy_vocabulary} WHERE vid = :vid", array(':vid' => $entity->vid))->fetchField(); | |
774 } | |
775 | |
776 foreach ($tokens as $name => $original) { | |
777 switch ($name) { | |
778 case 'url': | |
779 if (_token_module($type, 'url') == 'token' && $uri = entity_uri($entity_type, $entity)) { | |
780 $replacements[$original] = url($uri['path'], $uri['options']); | |
781 } | |
782 break; | |
783 | |
784 case 'original': | |
785 if (_token_module($type, 'original') == 'token' && !empty($entity->original)) { | |
786 $label = entity_label($entity_type, $entity->original); | |
787 $replacements[$original] = $sanitize ? check_plain($label) : $label; | |
788 } | |
789 break; | |
790 } | |
791 } | |
792 | |
793 // [entity:url:*] chained tokens. | |
794 if (($url_tokens = token_find_with_prefix($tokens, 'url')) && _token_module($type, 'url') == 'token') { | |
795 $replacements += token_generate('url', $url_tokens, entity_uri($entity_type, $entity), $options); | |
796 } | |
797 | |
798 // [entity:original:*] chained tokens. | |
799 if (($original_tokens = token_find_with_prefix($tokens, 'original')) && _token_module($type, 'original') == 'token' && !empty($entity->original)) { | |
800 $replacements += token_generate($type, $original_tokens, array($type => $entity->original), $options); | |
801 } | |
802 | |
803 // Pass through to an generic 'entity' token type generation. | |
804 $entity_data = array( | |
805 'entity_type' => $entity_type, | |
806 'entity' => $entity, | |
807 'token_type' => $type, | |
808 ); | |
809 // @todo Investigate passing through more data like everything from entity_extract_ids(). | |
810 $replacements += token_generate('entity', $tokens, $entity_data, $options); | |
811 } | |
812 | |
813 // Array tokens. | |
814 if ($type == 'array' && !empty($data['array']) && is_array($data['array'])) { | |
815 $array = $data['array']; | |
816 | |
817 $sort = isset($options['array sort']) ? $options['array sort'] : TRUE; | |
818 $keys = element_children($array, $sort); | |
819 | |
820 foreach ($tokens as $name => $original) { | |
821 switch ($name) { | |
822 case 'first': | |
823 $value = $array[$keys[0]]; | |
824 $value = is_array($value) ? render($value) : (string) $value; | |
825 $replacements[$original] = $sanitize ? check_plain($value) : $value; | |
826 break; | |
827 case 'last': | |
828 $value = $array[$keys[count($keys) - 1]]; | |
829 $value = is_array($value) ? render($value) : (string) $value; | |
830 $replacements[$original] = $sanitize ? check_plain($value) : $value; | |
831 break; | |
832 case 'count': | |
833 $replacements[$original] = count($keys); | |
834 break; | |
835 case 'keys': | |
836 $replacements[$original] = token_render_array($keys, $options); | |
837 break; | |
838 case 'reversed': | |
839 $reversed = array_reverse($array, TRUE); | |
840 $replacements[$original] = token_render_array($reversed, $options); | |
841 break; | |
842 case 'join': | |
843 $replacements[$original] = token_render_array($array, array('join' => '') + $options); | |
844 break; | |
845 } | |
846 } | |
847 | |
848 // [array:value:*] dynamic tokens. | |
849 if ($value_tokens = token_find_with_prefix($tokens, 'value')) { | |
850 foreach ($value_tokens as $key => $original) { | |
851 if ($key[0] !== '#' && isset($array[$key])) { | |
852 $replacements[$original] = token_render_array_value($array[$key], $options); | |
853 } | |
854 } | |
855 } | |
856 | |
857 // [array:join:*] dynamic tokens. | |
858 if ($join_tokens = token_find_with_prefix($tokens, 'join')) { | |
859 foreach ($join_tokens as $join => $original) { | |
860 $replacements[$original] = token_render_array($array, array('join' => $join) + $options); | |
861 } | |
862 } | |
863 | |
864 // [array:keys:*] chained tokens. | |
865 if ($key_tokens = token_find_with_prefix($tokens, 'keys')) { | |
866 $replacements += token_generate('array', $key_tokens, array('array' => $keys), $options); | |
867 } | |
868 | |
869 // [array:reversed:*] chained tokens. | |
870 if ($reversed_tokens = token_find_with_prefix($tokens, 'reversed')) { | |
871 $replacements += token_generate('array', $reversed_tokens, array('array' => array_reverse($array, TRUE)), array('array sort' => FALSE) + $options); | |
872 } | |
873 | |
874 // @todo Handle if the array values are not strings and could be chained. | |
875 } | |
876 | |
877 // Random tokens. | |
878 if ($type == 'random') { | |
879 foreach ($tokens as $name => $original) { | |
880 switch ($name) { | |
881 case 'number': | |
882 $replacements[$original] = mt_rand(); | |
883 break; | |
884 } | |
885 } | |
886 | |
887 // [custom:hash:*] dynamic token. | |
888 if ($hash_tokens = token_find_with_prefix($tokens, 'hash')) { | |
889 $algos = hash_algos(); | |
890 foreach ($hash_tokens as $name => $original) { | |
891 if (in_array($name, $algos)) { | |
892 $replacements[$original] = hash($name, drupal_random_bytes(55)); | |
893 } | |
894 } | |
895 } | |
896 } | |
897 | |
898 // If $type is a token type, $data[$type] is empty but $data[$entity_type] is | |
899 // not, re-run token replacements. | |
900 if (empty($data[$type]) && ($entity_type = token_get_entity_mapping('token', $type)) && $entity_type != $type && !empty($data[$entity_type]) && empty($options['recursive'])) { | |
901 $data[$type] = $data[$entity_type]; | |
902 $options['recursive'] = TRUE; | |
903 $replacements += module_invoke_all('tokens', $type, $tokens, $data, $options); | |
904 } | |
905 | |
906 // If the token type specifics a 'needs-data' value, and the value is not | |
907 // present in $data, then throw an error. | |
908 if (!empty($GLOBALS['drupal_test_info']['test_run_id'])) { | |
909 // Only check when tests are running. | |
910 $type_info = token_get_info($type); | |
911 if (!empty($type_info['needs-data']) && !isset($data[$type_info['needs-data']])) { | |
912 trigger_error(t('Attempting to perform token replacement for token type %type without required data', array('%type' => $type)), E_USER_WARNING); | |
913 } | |
914 } | |
915 | |
916 return $replacements; | |
917 } | |
918 | |
919 /** | |
920 * Implements hook_tokens_alter(). | |
921 * | |
922 * Fix existing core tokens that do not work correctly. | |
923 */ | |
924 function token_tokens_alter(array &$replacements, array $context) { | |
925 $options = $context['options']; | |
926 | |
927 $sanitize = !empty($options['sanitize']); | |
928 $langcode = !empty($options['language']->language) ? $options['language']->language : NULL; | |
929 | |
930 // Comment token fixes. | |
931 if ($context['type'] == 'comment' && !empty($context['data']['comment'])) { | |
932 $comment = $context['data']['comment']; | |
933 | |
934 foreach ($context['tokens'] as $name => $original) { | |
935 switch ($name) { | |
936 case 'name': | |
937 case 'author': | |
938 // @todo Remove when http://drupal.org/node/920056 is fixed. | |
939 if (!empty($comment->uid)) { | |
940 $account = user_load($comment->uid); | |
941 } | |
942 else { | |
943 $account = drupal_anonymous_user(); | |
944 $account->name = $comment->name; | |
945 } | |
946 $name = format_username($account); | |
947 $replacements[$original] = $sanitize ? check_plain($name) : $name; | |
948 break; | |
949 } | |
950 } | |
951 } | |
952 | |
953 // Node token fixes. | |
954 if ($context['type'] == 'node' && !empty($context['data']['node'])) { | |
955 $node = $context['data']['node']; | |
956 | |
957 foreach ($context['tokens'] as $name => $original) { | |
958 switch ($name) { | |
959 case 'author': | |
960 // http://drupal.org/node/1185842 was fixed in core release 7.9. | |
961 if (version_compare(VERSION, '7.9', '<')) { | |
962 $account = user_load($node->uid); | |
963 $name = format_username($account); | |
964 $replacements[$original] = $sanitize ? check_plain($name) : $name; | |
965 } | |
966 break; | |
967 } | |
968 } | |
969 } | |
970 | |
971 // File token fixes. | |
972 if ($context['type'] == 'file' && !empty($context['data']['file'])) { | |
973 $file = $context['data']['file']; | |
974 | |
975 foreach ($context['tokens'] as $name => $original) { | |
976 switch ($name) { | |
977 case 'owner': | |
978 // http://drupal.org/node/978028 was fixed in core release 7.7. | |
979 if (version_compare(VERSION, '7.7', '<')) { | |
980 $account = user_load($file->uid); | |
981 $name = format_username($account); | |
982 $replacements[$original] = $sanitize ? check_plain($name) : $name; | |
983 } | |
984 break; | |
985 } | |
986 } | |
987 } | |
988 } | |
989 | |
990 /** | |
991 * Implements hook_token_info() on behalf of book.module. | |
992 */ | |
993 function book_token_info() { | |
994 $info['tokens']['node']['book'] = array( | |
995 'name' => t('Book'), | |
996 'description' => t('The book page associated with the node.'), | |
997 'type' => 'menu-link', | |
998 ); | |
999 return $info; | |
1000 } | |
1001 | |
1002 /** | |
1003 * Implements hook_tokens() on behalf of book.module. | |
1004 */ | |
1005 function book_tokens($type, $tokens, array $data = array(), array $options = array()) { | |
1006 $replacements = array(); | |
1007 $sanitize = !empty($options['sanitize']); | |
1008 | |
1009 // Node tokens. | |
1010 if ($type == 'node' && !empty($data['node'])) { | |
1011 $node = $data['node']; | |
1012 | |
1013 if (!empty($node->book['mlid'])) { | |
1014 $link = token_book_link_load($node->book['mlid']); | |
1015 | |
1016 foreach ($tokens as $name => $original) { | |
1017 switch ($name) { | |
1018 case 'book': | |
1019 $replacements[$original] = $sanitize ? check_plain($link['title']) : $link['title']; | |
1020 break; | |
1021 } | |
1022 } | |
1023 | |
1024 // Chained token relationships. | |
1025 if ($book_tokens = token_find_with_prefix($tokens, 'book')) { | |
1026 $replacements += token_generate('menu-link', $book_tokens, array('menu-link' => $link), $options); | |
1027 } | |
1028 } | |
1029 } | |
1030 | |
1031 return $replacements; | |
1032 } | |
1033 | |
1034 /** | |
1035 * Implements hook_token_info() on behalf of menu.module. | |
1036 */ | |
1037 function menu_token_info() { | |
1038 // Menu tokens. | |
1039 $info['types']['menu'] = array( | |
1040 'name' => t('Menus'), | |
1041 'description' => t('Tokens related to menus.'), | |
1042 'needs-data' => 'menu', | |
1043 ); | |
1044 $info['tokens']['menu']['name'] = array( | |
1045 'name' => t('Name'), | |
1046 'description' => t("The name of the menu."), | |
1047 ); | |
1048 $info['tokens']['menu']['machine-name'] = array( | |
1049 'name' => t('Machine-readable name'), | |
1050 'description' => t("The unique machine-readable name of the menu."), | |
1051 ); | |
1052 $info['tokens']['menu']['description'] = array( | |
1053 'name' => t('Description'), | |
1054 'description' => t('The optional description of the menu.'), | |
1055 ); | |
1056 $info['tokens']['menu']['menu-link-count'] = array( | |
1057 'name' => t('Menu link count'), | |
1058 'description' => t('The number of menu links belonging to the menu.'), | |
1059 ); | |
1060 $info['tokens']['menu']['edit-url'] = array( | |
1061 'name' => t('Edit URL'), | |
1062 'description' => t("The URL of the menu's edit page."), | |
1063 ); | |
1064 | |
1065 $info['tokens']['menu-link']['menu'] = array( | |
1066 'name' => t('Menu'), | |
1067 'description' => t('The menu of the menu link.'), | |
1068 'type' => 'menu', | |
1069 ); | |
1070 $info['tokens']['menu-link']['edit-url'] = array( | |
1071 'name' => t('Edit URL'), | |
1072 'description' => t("The URL of the menu link's edit page."), | |
1073 ); | |
1074 $info['tokens']['node']['menu-link'] = array( | |
1075 'name' => t('Menu link'), | |
1076 'description' => t("The menu link for this node."), | |
1077 'type' => 'menu-link', | |
1078 ); | |
1079 | |
1080 return $info; | |
1081 } | |
1082 | |
1083 /** | |
1084 * Implements hook_tokens() on behalf of menu.module. | |
1085 */ | |
1086 function menu_tokens($type, $tokens, array $data = array(), array $options = array()) { | |
1087 $replacements = array(); | |
1088 | |
1089 $url_options = array('absolute' => TRUE); | |
1090 if (isset($options['language'])) { | |
1091 $url_options['language'] = $options['language']; | |
1092 $language_code = $options['language']->language; | |
1093 } | |
1094 else { | |
1095 $language_code = NULL; | |
1096 } | |
1097 | |
1098 $sanitize = !empty($options['sanitize']); | |
1099 | |
1100 // Node tokens. | |
1101 if ($type == 'node' && !empty($data['node'])) { | |
1102 $node = $data['node']; | |
1103 | |
1104 foreach ($tokens as $name => $original) { | |
1105 switch ($name) { | |
1106 case 'menu-link': | |
1107 if ($link = token_node_menu_link_load($node)) { | |
1108 $replacements[$original] = $sanitize ? check_plain($link['title']) : $link['title']; | |
1109 } | |
1110 break; | |
1111 } | |
1112 | |
1113 // Chained token relationships. | |
1114 if ($menu_tokens = token_find_with_prefix($tokens, 'menu-link')) { | |
1115 if ($link = token_node_menu_link_load($node)) { | |
1116 $replacements += token_generate('menu-link', $menu_tokens, array('menu-link' => $link), $options); | |
1117 } | |
1118 } | |
1119 } | |
1120 } | |
1121 | |
1122 // Menu link tokens. | |
1123 if ($type == 'menu-link' && !empty($data['menu-link'])) { | |
1124 $link = (array) $data['menu-link']; | |
1125 | |
1126 foreach ($tokens as $name => $original) { | |
1127 switch ($name) { | |
1128 case 'menu': | |
1129 if ($menu = menu_load($link['menu_name'])) { | |
1130 $replacements[$original] = $sanitize ? check_plain($menu['title']) : $menu['title']; | |
1131 } | |
1132 break; | |
1133 case 'edit-url': | |
1134 $replacements[$original] = url("admin/structure/menu/item/{$link['mlid']}/edit", $url_options); | |
1135 break; | |
1136 } | |
1137 } | |
1138 | |
1139 // Chained token relationships. | |
1140 if (($menu_tokens = token_find_with_prefix($tokens, 'menu')) && $menu = menu_load($link['menu_name'])) { | |
1141 $replacements += token_generate('menu', $menu_tokens, array('menu' => $menu), $options); | |
1142 } | |
1143 } | |
1144 | |
1145 // Menu tokens. | |
1146 if ($type == 'menu' && !empty($data['menu'])) { | |
1147 $menu = (array) $data['menu']; | |
1148 | |
1149 foreach ($tokens as $name => $original) { | |
1150 switch ($name) { | |
1151 case 'name': | |
1152 $replacements[$original] = $sanitize ? check_plain($menu['title']) : $menu['title']; | |
1153 break; | |
1154 case 'machine-name': | |
1155 // This is a machine name so does not ever need to be sanitized. | |
1156 $replacements[$original] = $menu['menu_name']; | |
1157 break; | |
1158 case 'description': | |
1159 $replacements[$original] = $sanitize ? filter_xss($menu['description']) : $menu['description']; | |
1160 break; | |
1161 case 'menu-link-count': | |
1162 $query = db_select('menu_links'); | |
1163 $query->condition('menu_name', $menu['menu_name']); | |
1164 $query->addTag('menu_menu_link_count'); | |
1165 $count = $query->countQuery()->execute()->fetchField(); | |
1166 $replacements[$original] = (int) $count; | |
1167 break; | |
1168 case 'edit-url': | |
1169 $replacements[$original] = url("admin/structure/menu/manage/" . $menu['menu_name'], $url_options); | |
1170 break; | |
1171 } | |
1172 } | |
1173 } | |
1174 | |
1175 return $replacements; | |
1176 } | |
1177 | |
1178 /** | |
1179 * Implements hook_token_info() on behalf of profile.module. | |
1180 */ | |
1181 function profile_token_info() { | |
1182 $info = array(); | |
1183 | |
1184 foreach (_token_profile_fields() as $field) { | |
1185 $info['tokens']['user'][$field->token_name] = array( | |
1186 'name' => check_plain($field->title), | |
1187 'description' => t('@category @type field.', array('@category' => drupal_ucfirst($field->category), '@type' => $field->type)), | |
1188 ); | |
1189 | |
1190 switch ($field->type) { | |
1191 case 'date': | |
1192 $info['tokens']['user'][$field->token_name]['type'] = 'date'; | |
1193 break; | |
1194 } | |
1195 } | |
1196 | |
1197 return $info; | |
1198 } | |
1199 | |
1200 /** | |
1201 * Implements hook_tokens() on behalf of profile.module. | |
1202 */ | |
1203 function profile_tokens($type, $tokens, array $data = array(), array $options = array()) { | |
1204 $replacements = array(); | |
1205 $sanitize = !empty($options['sanitize']); | |
1206 $language_code = isset($options['language']) ? $options['language']->language : NULL; | |
1207 | |
1208 if ($type == 'user' && !empty($data['user'])) { | |
1209 $account = $data['user']; | |
1210 | |
1211 // Load profile fields if this is the global user account. | |
1212 // @see http://drupal.org/node/361471 | |
1213 // @see http://drupal.org/node/967330 | |
1214 if ($account->uid == $GLOBALS['user']->uid && isset($account->timestamp)) { | |
1215 $profile_users = array($account->uid => $account); | |
1216 profile_user_load($profile_users); | |
1217 $account = $profile_users[$account->uid]; | |
1218 } | |
1219 | |
1220 $profile_fields = _token_profile_fields(); | |
1221 foreach ($tokens as $name => $original) { | |
1222 if (isset($profile_fields[$name]) && !empty($account->{$profile_fields[$name]->name})) { | |
1223 $value = $account->{$profile_fields[$name]->name}; | |
1224 switch ($profile_fields[$name]->type) { | |
1225 case 'textarea': | |
1226 $replacements[$original] = $sanitize ? check_markup($value, filter_default_format($account), '', TRUE) : $value; | |
1227 break; | |
1228 case 'date': | |
1229 $timestamp = gmmktime(0, 0, 0, $value['month'], $value['day'], $value['year']); | |
1230 $replacements[$original] = format_date($timestamp, 'medium', '', NULL, $language_code); | |
1231 break; | |
1232 case 'url': | |
1233 $replacements[$original] = $sanitize ? check_url($value) : $value; | |
1234 break; | |
1235 case 'checkbox': | |
1236 // Checkbox field if checked should return the text. | |
1237 $replacements[$original] = $sanitize ? check_plain($profile_fields[$name]->title) : $profile_fields[$name]->title; | |
1238 break; | |
1239 case 'list': | |
1240 $value = preg_split("/[,\n\r]/", $value); | |
1241 $value = array_map('trim', $value); | |
1242 $value = implode(', ', $value); | |
1243 // Intentionally fall through to the default condition. | |
1244 default: | |
1245 $replacements[$original] = $sanitize ? check_plain($value) : $value; | |
1246 break; | |
1247 } | |
1248 } | |
1249 } | |
1250 | |
1251 // Chained token relationships. | |
1252 foreach ($profile_fields as $field) { | |
1253 if ($field->type == 'date' && isset($account->{$field->name}) && $field_tokens = token_find_with_prefix($tokens, $field->token_name)) { | |
1254 $date = $account->{$field->name}; | |
1255 $replacements += token_generate('date', $field_tokens, array('date' => gmmktime(0, 0, 0, $date['month'], $date['day'], $date['year'])), $options); | |
1256 } | |
1257 } | |
1258 } | |
1259 | |
1260 return $replacements; | |
1261 } | |
1262 | |
1263 /** | |
1264 * Fetch an array of profile field objects, keyed by token name. | |
1265 */ | |
1266 function _token_profile_fields() { | |
1267 $fields = &drupal_static(__FUNCTION__); | |
1268 | |
1269 if (!isset($fields)) { | |
1270 $fields = array(); | |
1271 $results = db_query("SELECT name, title, category, type FROM {profile_field}"); | |
1272 foreach ($results as $field) { | |
1273 $field->token_name = token_clean_token_name($field->name); | |
1274 $fields[$field->token_name] = $field; | |
1275 } | |
1276 } | |
1277 | |
1278 return $fields; | |
1279 } | |
1280 | |
1281 /** | |
1282 * Fetch an array of field data used for tokens. | |
1283 */ | |
1284 function _token_field_info($field_name = NULL) { | |
1285 $info = &drupal_static(__FUNCTION__); | |
1286 | |
1287 if (!isset($fields)) { | |
1288 if ($cached = cache_get('field:info', 'cache_token')) { | |
1289 $info = $cached->data; | |
1290 } | |
1291 else { | |
1292 $info = array(); | |
1293 | |
1294 $fields = field_info_fields(); | |
1295 $instances = field_info_instances(); | |
1296 $type_info = field_info_field_types(); | |
1297 $entity_info = entity_get_info(); | |
1298 | |
1299 foreach ($fields as $field) { | |
1300 $key = $field['field_name']; | |
1301 if (!empty($field['bundles'])) { | |
1302 foreach (array_keys($field['bundles']) as $entity) { | |
1303 // Make sure a token type exists for this entity. | |
1304 $token_type = token_get_entity_mapping('entity', $entity); | |
1305 if (empty($token_type)) { | |
1306 continue; | |
1307 } | |
1308 | |
1309 $info[$key]['token types'][] = $token_type; | |
1310 $info[$key] += array('labels' => array(), 'bundles' => array()); | |
1311 | |
1312 // Find which label is most commonly used. | |
1313 foreach ($field['bundles'][$entity] as $bundle) { | |
1314 // Field information will included fields attached to disabled | |
1315 // bundles, so check that the bundle exists before provided a | |
1316 // token for it. | |
1317 // @see http://drupal.org/node/1252566 | |
1318 if (!isset($entity_info[$entity]['bundles'][$bundle])) { | |
1319 continue; | |
1320 } | |
1321 | |
1322 $info[$key]['labels'][] = $instances[$entity][$bundle][$key]['label']; | |
1323 $info[$key]['bundles'][$token_type][$bundle] = $entity_info[$entity]['bundles'][$bundle]['label']; | |
1324 } | |
1325 } | |
1326 } | |
1327 | |
1328 if (isset($info[$key])) { | |
1329 $labels = array_count_values($info[$key]['labels']); | |
1330 arsort($labels); | |
1331 $info[$key]['label'] = check_plain(key($labels)); | |
1332 | |
1333 // Generate a description for the token. | |
1334 $info[$key]['description'] = t('@type field.', array('@type' => $type_info[$field['type']]['label'])); | |
1335 if ($also_known_as = array_unique(array_diff($info[$key]['labels'], array($info[$key]['label'])))) { | |
1336 $info[$key]['description'] .= ' ' . t('Also known as %labels.', array('%labels' => implode(', ', $also_known_as))); | |
1337 } | |
1338 } | |
1339 } | |
1340 | |
1341 drupal_alter('token_field_info', $info); | |
1342 cache_set('field:info', $info, 'cache_token'); | |
1343 } | |
1344 } | |
1345 | |
1346 if (isset($field_name)) { | |
1347 return isset($info[$field_name]) ? $info[$field_name] : FALSE; | |
1348 } | |
1349 | |
1350 return $info; | |
1351 } | |
1352 | |
1353 /** | |
1354 * Implements hook_token_info_alter() on behalf of field.module. | |
1355 * | |
1356 * We use hook_token_info_alter() rather than hook_token_info() as other | |
1357 * modules may already have defined some field tokens. | |
1358 */ | |
1359 function field_token_info_alter(&$info) { | |
1360 $fields = _token_field_info(); | |
1361 | |
1362 // Attach field tokens to their respecitve entity tokens. | |
1363 foreach ($fields as $field_name => $field) { | |
1364 foreach (array_keys($field['bundles']) as $token_type) { | |
1365 // If a token already exists for this field, then don't add it. | |
1366 if (isset($info['tokens'][$token_type][$field_name])) { | |
1367 continue; | |
1368 } | |
1369 | |
1370 // Ensure the tokens exist. | |
1371 if (!isset($info['types'][$token_type]) || !isset($info['tokens'][$token_type])) { | |
1372 continue; | |
1373 } | |
1374 | |
1375 if ($token_type == 'comment' && $field_name == 'comment_body') { | |
1376 // Core provides the comment field as [comment:body]. | |
1377 continue; | |
1378 } | |
1379 | |
1380 $info['tokens'][$token_type][$field_name] = array( | |
1381 // Note that label and description have already been sanitized by _token_field_info(). | |
1382 'name' => $field['label'], | |
1383 'description' => $field['description'], | |
1384 'module' => 'token', | |
1385 ); | |
1386 } | |
1387 } | |
1388 } | |
1389 | |
1390 /** | |
1391 * Implements hook_tokens() on behalf of field.module. | |
1392 */ | |
1393 function field_tokens($type, $tokens, array $data = array(), array $options = array()) { | |
1394 $replacements = array(); | |
1395 $sanitize = !empty($options['sanitize']); | |
1396 $langcode = isset($options['language']) ? $options['language']->language : NULL; | |
1397 | |
1398 // Entity tokens. | |
1399 if ($type == 'entity' && !empty($data['entity_type']) && !empty($data['entity']) && !empty($data['token_type'])) { | |
1400 $entity_type = $data['entity_type']; | |
1401 | |
1402 // The field API does weird stuff to the entity, so let's clone it. | |
1403 $entity = clone $data['entity']; | |
1404 | |
1405 // Reset the prepared view flag in case token generation is called from | |
1406 // inside field_attach_view(). | |
1407 unset($entity->_field_view_prepared); | |
1408 | |
1409 list(, , $bundle) = entity_extract_ids($entity_type, $entity); | |
1410 $fields = field_info_instances($entity_type, $bundle); | |
1411 | |
1412 foreach (array_keys($fields) as $field_name) { | |
1413 // Do not continue if the field is empty. | |
1414 if (empty($entity->{$field_name})) { | |
1415 continue; | |
1416 } | |
1417 | |
1418 // Replace the [entity:field-name] token only if token module added this | |
1419 // token. | |
1420 if (isset($tokens[$field_name]) && _token_module($data['token_type'], $field_name) == 'token') { | |
1421 $original = $tokens[$field_name]; | |
1422 | |
1423 $field_output = field_view_field($entity_type, $entity, $field_name, 'token', $langcode); | |
1424 $field_output['#token_options'] = $options; | |
1425 $field_output['#pre_render'][] = 'token_pre_render_field_token'; | |
1426 $replacements[$original] = drupal_render($field_output); | |
1427 } | |
1428 } | |
1429 | |
1430 // Remove the cloned object from memory. | |
1431 unset($entity); | |
1432 } | |
1433 | |
1434 return $replacements; | |
1435 } | |
1436 | |
1437 /** | |
1438 * Pre-render callback for field output used with tokens. | |
1439 */ | |
1440 function token_pre_render_field_token(&$elements) { | |
1441 // Remove the field theme hook, attachments, and JavaScript states. | |
1442 unset($elements['#theme']); | |
1443 unset($elements['#states']); | |
1444 unset($elements['#attached']); | |
1445 | |
1446 // Prevent multi-value fields from appearing smooshed together by appending | |
1447 // a join suffix to all but the last value. | |
1448 $deltas = element_get_visible_children($elements); | |
1449 $count = count($deltas); | |
1450 if ($count > 1) { | |
1451 $join = isset($elements['#token_options']['join']) ? $elements['#token_options']['join'] : ", "; | |
1452 foreach ($deltas as $index => $delta) { | |
1453 // Do not add a suffix to the last item. | |
1454 if ($index < ($count - 1)) { | |
1455 $elements[$delta] += array('#suffix' => $join); | |
1456 } | |
1457 } | |
1458 } | |
1459 return $elements; | |
1460 } |