token.install 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. <?php
  2. /**
  3. * @file
  4. * Install, update and uninstall functions for the token module.
  5. */
  6. /**
  7. * Implements hook_requirements().
  8. */
  9. function token_requirements($phase = 'runtime') {
  10. $requirements = [];
  11. if ($phase == 'runtime') {
  12. // Check for various token definition problems.
  13. $token_problems = token_get_token_problems();
  14. // Format and display each token problem.
  15. foreach ($token_problems as $problem_key => $problem) {
  16. if (!empty($problem['problems'])) {
  17. $problems = array_unique($problem['problems']);
  18. $build = [
  19. '#theme' => 'item_list',
  20. '#items' => $problems,
  21. ];
  22. $requirements['token-' . $problem_key] = [
  23. 'title' => $problem['label'],
  24. 'value' => \Drupal::service('renderer')->renderPlain($build),
  25. 'severity' => $problem['severity'],
  26. ];
  27. }
  28. }
  29. }
  30. return $requirements;
  31. }
  32. /**
  33. * Implements hook_install().
  34. */
  35. function token_install() {
  36. // Create a token view mode for each entity type.
  37. $info = \Drupal::entityTypeManager()->getDefinitions();
  38. foreach ($info as $entity_type => $entity_type_info) {
  39. // We're only interested in entity types with a view builder.
  40. if (!$entity_type_info->getViewBuilderClass()) {
  41. continue;
  42. }
  43. // Try to find a token view mode for that entity type.
  44. $storage = \Drupal::entityTypeManager()->getStorage('entity_view_mode');
  45. // Add a token view mode if it does not already exist.
  46. if (!$storage->load("$entity_type.token")) {
  47. $storage->create([
  48. 'targetEntityType' => $entity_type,
  49. 'id' => "$entity_type.token",
  50. 'status' => TRUE,
  51. 'label' => t('Token'),
  52. ])->save();
  53. }
  54. }
  55. }
  56. /**
  57. * Build a list of Drupal 6 tokens and their Drupal 7 token names.
  58. */
  59. function _token_upgrade_token_list() {
  60. $tokens = [
  61. // Global tokens
  62. 'user-name' => 'current-user:name',
  63. 'user-id' => 'current-user:id',
  64. 'user-mail' => 'current-user:mail',
  65. 'site-url' => 'site:url',
  66. 'site-name' => 'site:name',
  67. 'site-slogan' => 'site:slogan',
  68. 'site-mission' => 'site:mission',
  69. 'site-mail' => 'site:mail',
  70. 'site-date' => 'date:short',
  71. //'site-date-' => '', // Date tokens expanded below
  72. 'current-page-path' => 'current-page:path',
  73. 'current-page-url' => 'current-page:url',
  74. 'page-number' => 'current-page:page-number',
  75. // Comment tokens
  76. 'comment-cid' => 'comment:cid',
  77. 'comment-nid' => 'comment:node:nid',
  78. 'comment-title' => 'comment:title',
  79. 'comment-body' => 'comment:body',
  80. 'comment-author-name' => 'comment:author:name',
  81. 'comment-author-mail' => 'comment:author:mail',
  82. //'comment-body-format' => '',
  83. //'comment-' => '', // Date tokens expanded below
  84. 'comment-node-title' => 'comment:node',
  85. // Node tokens
  86. 'nid' => 'node:nid',
  87. 'type' => 'node:type',
  88. 'type-name' => 'node:type-name',
  89. 'language' => 'node:language',
  90. 'title' => 'node:title',
  91. 'author-uid' => 'node:author:uid',
  92. 'author-name' => 'node:author:name',
  93. 'author-mail' => 'node:author:mail',
  94. 'node_comment_count' => 'node:comment-count',
  95. 'unread_comment_count' => 'node:comment-count-new',
  96. 'log' => 'node:log',
  97. //'' => '', // Date tokens expanded below
  98. //'mod-' => '', // Date tokens expanded below
  99. 'menupath' => 'node:menu-link:parent:path][node:menu-link',
  100. 'menu' => 'node:menu-link:menu-name',
  101. 'menu-link-title' => 'node:menu-link',
  102. 'menu-link-mlid' => 'node:menu-link:mlid',
  103. 'menu-link-plid' => 'node:menu-link:parent:mlid',
  104. //'term' => 'node:term',
  105. //'term-id' => 'node:term:tid',
  106. //'vocab' => 'node:term:vocabulary',
  107. //'vocab-id' => 'node:term:vocabulary:vid',
  108. // Book tokens
  109. //'book' => 'node:book',
  110. //'book_id' => 'node:book:bid',
  111. //'bookpath' => 'node:book:path',
  112. // Taxonomy tokens
  113. 'tid' => 'term:tid',
  114. 'cat' => 'term:name',
  115. 'cat-description' => 'term:description',
  116. 'vid' => 'term:vocabulary:vid',
  117. 'vocab' => 'term:vocabulary',
  118. 'vocab-description' => 'term:vocabulary:description',
  119. // User tokens
  120. 'user' => 'user:name',
  121. 'uid' => 'user:uid',
  122. 'mail' => 'user:mail',
  123. 'reg-date' => 'user:created',
  124. 'reg-since' => 'user:created:since',
  125. //'user-created' => '', // Date tokens expanded below
  126. 'log-date' => 'user:last-login',
  127. 'log-since' => 'user:last-login:since',
  128. //'user-last-login' => '', // Date tokens expanded below
  129. //'date-in-tz' => '',
  130. 'account-url' => 'user:url',
  131. 'account-edit' => 'user:edit-url',
  132. ];
  133. // Account for date tokens which need to be expanded.
  134. $tokens += _token_upgrade_token_date_list('site-', 'site:date');
  135. $tokens += _token_upgrade_token_date_list('', 'node:created');
  136. $tokens += _token_upgrade_token_date_list('mod-', 'node:changed');
  137. //$tokens += _token_upgrade_token_date_list('node-revision-', 'node:changed');
  138. $tokens += _token_upgrade_token_date_list('comment-', 'comment:created');
  139. $tokens += _token_upgrade_token_date_list('user-register-', 'user:created');
  140. $tokens += _token_upgrade_token_date_list('user-last-login-', 'user:last-login');
  141. return $tokens;
  142. }
  143. /**
  144. * Build a list of Drupal 6 date tokens and their Drupal 7 token names.
  145. */
  146. function _token_upgrade_token_date_list($old_token, $new_token) {
  147. $tokens = [];
  148. $formats = [
  149. 'yyyy' => 'Y',
  150. 'yy' => 'y',
  151. 'month' => 'F',
  152. 'mon' => 'M',
  153. 'mm' => 'm',
  154. 'm' => 'n',
  155. 'ww' => 'W',
  156. 'date' => 'N',
  157. 'day' => 'l',
  158. 'ddd' => 'D',
  159. 'dd' => 'd',
  160. 'd' => 'j',
  161. ];
  162. foreach ($formats as $token_format => $date_format) {
  163. $tokens[$old_token . $token_format] = "$new_token:custom:$date_format";
  164. }
  165. $tokens[$old_token . 'raw'] = "$new_token:raw";
  166. $tokens[$old_token . 'since'] = "$new_token:since";
  167. return $tokens;
  168. }
  169. /**
  170. * Update a string containing Drupal 6 style tokens to Drupal 7 style tokens.
  171. *
  172. * @param $text
  173. * A string containing tokens.
  174. * @param $updates
  175. * An optional array of Drupal 7 tokens keyed by their Drupal 6 token name.
  176. * The default tokens will be merged into this array. Note neither the old
  177. * or new token names should include the surrounding bracket ([ and ])
  178. * characters.
  179. * @return
  180. * A string with the tokens upgraded
  181. *
  182. * @see _token_upgrade_token_list()
  183. */
  184. function token_update_token_text($text, $updates = [], $leading = '[', $trailing = ']') {
  185. $updates += _token_upgrade_token_list();
  186. $regex = '/' . preg_quote($leading, '/') . '([^\s]*)' . preg_quote($trailing, '/') . '/';
  187. preg_match_all($regex, $text, $matches);
  188. foreach ($matches[1] as $index => $old_token) {
  189. if (isset($updates[$old_token])) {
  190. $new_token = $updates[$old_token];
  191. $text = str_replace("{$leading}{$old_token}{$trailing}", "[$new_token]", $text);
  192. // Also replace any tokens that have a -raw suffix.
  193. $text = str_replace("{$leading}{$old_token}-raw{$trailing}", "[$new_token]", $text);
  194. }
  195. }
  196. return $text;
  197. }
  198. /**
  199. * Get token problems.
  200. */
  201. function token_get_token_problems() {
  202. // @todo Improve the duplicate checking to report which modules are the offenders.
  203. //$token_info = [];
  204. //foreach (module_implements('token_info') as $module) {
  205. // $module_token_info = module_invoke($module, 'token_info');
  206. // if (in_array($module, _token_core_supported_modules())) {
  207. // $module .= '/token';
  208. // }
  209. // if (isset($module_token_info['types'])) {
  210. // if (is_array($module_token_info['types'])) {
  211. // foreach (array_keys($module_token_info['types']) as $type) {
  212. // if (is_array($module_token_info['types'][$type])) {
  213. // $module_token_info['types'][$type] += ['module' => $module];
  214. // }
  215. // }
  216. // }
  217. // }
  218. // if (isset($module_token_info['tokens'])) {
  219. // if (is_array($module_token_info['tokens'])) {
  220. //
  221. // }
  222. // }
  223. // if (is_array($module_token_info)) {
  224. // $token_info = array_merge_recursive($token_info, $module_token_info);
  225. // }
  226. //}
  227. $token_info = \Drupal::token()->getInfo();
  228. $token_problems = [
  229. 'not-array' => [
  230. 'label' => t('Tokens or token types not defined as arrays'),
  231. 'severity' => REQUIREMENT_ERROR,
  232. ],
  233. 'missing-info' => [
  234. 'label' => t('Tokens or token types missing name property'),
  235. 'severity' => REQUIREMENT_WARNING,
  236. ],
  237. 'type-no-tokens' => [
  238. 'label' => t('Token types do not have any tokens defined'),
  239. 'severity' => REQUIREMENT_INFO,
  240. ],
  241. 'tokens-no-type' => [
  242. 'label' => t('Token types are not defined but have tokens'),
  243. 'severity' => REQUIREMENT_INFO,
  244. ],
  245. 'duplicate' => [
  246. 'label' => t('Token or token types are defined by multiple modules'),
  247. 'severity' => REQUIREMENT_ERROR,
  248. ],
  249. ];
  250. // Check token types for problems.
  251. foreach ($token_info['types'] as $type => $type_info) {
  252. $real_type = !empty($type_info['type']) ? $type_info['type'] : $type;
  253. if (!is_array($type_info)) {
  254. $token_problems['not-array']['problems'][] = "\$info['types']['$type']";
  255. continue;
  256. }
  257. elseif (!isset($type_info['name'])) {
  258. $token_problems['missing-info']['problems'][] = "\$info['types']['$type']";
  259. }
  260. elseif (is_array($type_info['name'])) {
  261. $token_problems['duplicate']['problems'][] = "\$info['types']['$type']";
  262. }
  263. elseif (empty($token_info['tokens'][$real_type])) {
  264. $token_problems['type-no-tokens']['problems'][] = "\$info['types']['$real_type']";
  265. }
  266. }
  267. // Check tokens for problems.
  268. foreach ($token_info['tokens'] as $type => $tokens) {
  269. if (!is_array($tokens)) {
  270. $token_problems['not-array']['problems'][] = "\$info['tokens']['$type']";
  271. continue;
  272. }
  273. else {
  274. foreach (array_keys($tokens) as $token) {
  275. if (!is_array($tokens[$token])) {
  276. $token_problems['not-array']['problems'][] = "\$info['tokens']['$type']['$token']";
  277. continue;
  278. }
  279. elseif (!isset($tokens[$token]['name'])) {
  280. $token_problems['missing-info']['problems'][] = "\$info['tokens']['$type']['$token']";
  281. }
  282. elseif (is_array($tokens[$token]['name'])) {
  283. $token_problems['duplicate']['problems'][] = "\$info['tokens']['$type']['$token']";
  284. }
  285. }
  286. }
  287. if (!isset($token_info['types'][$type])) {
  288. $token_problems['tokens-no-type']['problems'][] = "\$info['types']['$type']";
  289. }
  290. }
  291. return $token_problems;
  292. }