Newer
Older
<?php
/**
* @file
* Token callbacks for the token module.
*/
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface;
Sascha Grossenbacher
committed
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Render\Element;
Lukas Schneider
committed
use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\Html;
use Drupal\Core\TypedData\DataReferenceDefinitionInterface;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\menu_link_content\MenuLinkContentInterface;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
András Czövek
committed
use Drupal\Core\TypedData\PrimitiveInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
git
committed
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\image\Entity\ImageStyle;
/**
* Implements hook_token_info_alter().
*/
Dave Reid
committed
function token_token_info_alter(&$info) {
// Force 'date' type tokens to require input and add a 'current-date' type.
// @todo Remove when http://drupal.org/node/943028 is fixed.
$info['types']['date']['needs-data'] = 'date';
$info['types']['current-date'] = array(
'name' => t('Current date'),
'description' => t('Tokens related to the current date and time.'),
'type' => 'date',
);
// Add a 'dynamic' key to any tokens that have chained but dynamic tokens.
Dave Reid
committed
$info['tokens']['date']['custom']['dynamic'] = TRUE;
// The [file:size] may not always return in kilobytes.
// @todo Remove when http://drupal.org/node/1193044 is fixed.
if (!empty($info['tokens']['file']['size'])) {
$info['tokens']['file']['size']['description'] = t('The size of the file.');
}
// Remove deprecated tokens from being listed.
unset($info['tokens']['node']['tnid']);
unset($info['tokens']['node']['type']);
unset($info['tokens']['node']['type-name']);
Dave Reid
committed
Dave Reid
committed
// Support 'url' type tokens for core tokens.
if (isset($info['tokens']['comment']['url']) && \Drupal::moduleHandler()->moduleExists('comment')) {
Dave Reid
committed
$info['tokens']['comment']['url']['type'] = 'url';
}
if (isset($info['tokens']['node']['url']) && \Drupal::moduleHandler()->moduleExists('node')) {
$info['tokens']['node']['url']['type'] = 'url';
}
if (isset($info['tokens']['term']['url']) && \Drupal::moduleHandler()->moduleExists('taxonomy')) {
Dave Reid
committed
$info['tokens']['term']['url']['type'] = 'url';
}
$info['tokens']['user']['url']['type'] = 'url';
// Add [token:url] tokens for any URI-able entities.
$entities = \Drupal::entityTypeManager()->getDefinitions();
foreach ($entities as $entity => $entity_info) {
git
committed
// Do not generate tokens if the entity doesn't define a token type or is
// not a content entity.
if (!$entity_info->get('token_type') || (!$entity_info instanceof ContentEntityTypeInterface)) {
Hussain Abbas
committed
$token_type = $entity_info->get('token_type');
if (!isset($info['types'][$token_type]) || !isset($info['tokens'][$token_type])) {
// Define tokens for entity type's without their own integration.
$info['types'][$entity_info->id()] = [
'name' => $entity_info->getLabel(),
'needs-data' => $entity_info->id(),
'module' => 'token',
];
// Add [entity:url] tokens if they do not already exist.
// @todo Support entity:label
if (!isset($info['tokens'][$token_type]['url'])) {
$info['tokens'][$token_type]['url'] = array(
'name' => t('URL'),
'description' => t('The URL of the @entity.', array('@entity' => Unicode::strtolower($entity_info->getLabel()))),
'module' => 'token',
// Add [entity:original] tokens if they do not already exist.
if (!isset($info['tokens'][$token_type]['original'])) {
$info['tokens'][$token_type]['original'] = array(
'name' => t('Original @entity', array('@entity' => Unicode::strtolower($entity_info->getLabel()))),
'description' => t('The original @entity data if the @entity is being updated or saved.', array('@entity' => Unicode::strtolower($entity_info->getLabel()))),
'module' => 'token',
'type' => $token_type,
);
}
// Add support for custom date formats.
// @todo Remove when http://drupal.org/node/1173706 is fixed.
$date_format_types = \Drupal::entityTypeManager()->getStorage('date_format')->loadMultiple();
foreach ($date_format_types as $date_format_type => $date_format_type_info) {
/* @var \Drupal\system\Entity\DateFormat $date_format_type_info */
if (!isset($info['tokens']['date'][$date_format_type])) {
$info['tokens']['date'][$date_format_type] = array(
Rajeshwari Variar
committed
'name' => Html::escape($date_format_type_info->label()),
'description' => t("A date in '@type' format. (%date)", array('@type' => $date_format_type, '%date' => format_date(REQUEST_TIME, $date_format_type))),
'module' => 'token',
);
}
}
Dave Reid
committed
}
/**
* Implements hook_token_info().
*/
function token_token_info() {
Dave Reid
committed
// Node tokens.
Dave Reid
committed
$info['tokens']['node']['source'] = array(
'name' => t('Translation source node'),
'description' => t("The source node for this current node's translation set."),
'type' => 'node',
);
$info['tokens']['node']['log'] = array(
'name' => t('Revision log message'),
'description' => t('The explanation of the most recent changes made to the node.'),
);
$info['tokens']['node']['content-type'] = array(
'name' => t('Content type'),
'description' => t('The content type of the node.'),
'type' => 'content-type',
);
// Content type tokens.
$info['types']['content-type'] = array(
'name' => t('Content types'),
'description' => t('Tokens related to content types.'),
Dave Reid
committed
'needs-data' => 'node_type',
);
$info['tokens']['content-type']['name'] = array(
'name' => t('Name'),
'description' => t('The name of the content type.'),
);
$info['tokens']['content-type']['machine-name'] = array(
'name' => t('Machine-readable name'),
'description' => t('The unique machine-readable name of the content type.'),
);
$info['tokens']['content-type']['description'] = array(
'name' => t('Description'),
'description' => t('The optional description of the content type.'),
);
$info['tokens']['content-type']['node-count'] = array(
'name' => t('Node count'),
'description' => t('The number of nodes belonging to the content type.'),
);
Dave Reid
committed
$info['tokens']['content-type']['edit-url'] = array(
'name' => t('Edit URL'),
'description' => t("The URL of the content type's edit page."),
Dave Reid
committed
);
Dave Reid
committed
Dave Reid
committed
// Taxonomy term and vocabulary tokens.
if (\Drupal::moduleHandler()->moduleExists('taxonomy')) {
Dave Reid
committed
$info['tokens']['term']['edit-url'] = array(
'name' => t('Edit URL'),
'description' => t("The URL of the taxonomy term's edit page."),
Dave Reid
committed
);
$info['tokens']['term']['parents'] = array(
'name' => t('Parents'),
'description' => t("An array of all the term's parents, starting with the root."),
'type' => 'array',
);
Dave Reid
committed
$info['tokens']['term']['root'] = array(
'name' => t('Root term'),
'description' => t("The root term of the taxonomy term."),
'type' => 'term',
);
Dave Reid
committed
$info['tokens']['vocabulary']['machine-name'] = array(
'name' => t('Machine-readable name'),
'description' => t('The unique machine-readable name of the vocabulary.'),
);
$info['tokens']['vocabulary']['edit-url'] = array(
'name' => t('Edit URL'),
'description' => t("The URL of the vocabulary's edit page."),
Dave Reid
committed
);
}
$info['tokens']['file']['basename'] = array(
'name' => t('Base name'),
'description' => t('The base name of the file.'),
);
$info['tokens']['file']['extension'] = array(
'name' => t('Extension'),
'description' => t('The extension of the file.'),
$info['tokens']['file']['size-raw'] = array(
'name' => t('File byte size'),
'description' => t('The size of the file, in bytes.'),
);
// User tokens.
Dave Reid
committed
// Add information on the restricted user tokens.
$info['tokens']['user']['cancel-url'] = array(
'name' => t('Account cancellation URL'),
'description' => t('The URL of the confirm delete page for the user account.'),
'restricted' => TRUE,
Dave Reid
committed
);
$info['tokens']['user']['one-time-login-url'] = array(
'name' => t('One-time login URL'),
'description' => t('The URL of the one-time login page for the user account.'),
'restricted' => TRUE,
Dave Reid
committed
);
Dave Reid
committed
$info['tokens']['user']['roles'] = array(
'name' => t('Roles'),
'description' => t('The user roles associated with the user account.'),
'type' => 'array',
);
Dave Reid
committed
// Current user tokens.
$info['tokens']['current-user']['ip-address'] = array(
'name' => t('IP address'),
'description' => 'The IP address of the current user.',
);
Dave Reid
committed
// Menu link tokens (work regardless if menu module is enabled or not).
Dave Reid
committed
$info['types']['menu-link'] = array(
'name' => t('Menu links'),
'description' => t('Tokens related to menu links.'),
'needs-data' => 'menu-link',
);
$info['tokens']['menu-link']['mlid'] = array(
'name' => t('Link ID'),
'description' => t('The unique ID of the menu link.'),
);
$info['tokens']['menu-link']['title'] = array(
'name' => t('Title'),
'description' => t('The title of the menu link.'),
);
$info['tokens']['menu-link']['url'] = array(
'name' => t('URL'),
'description' => t('The URL of the menu link.'),
Dave Reid
committed
);
$info['tokens']['menu-link']['parent'] = array(
'name' => t('Parent'),
'description' => t("The menu link's parent."),
'type' => 'menu-link',
);
$info['tokens']['menu-link']['parents'] = array(
'name' => t('Parents'),
'description' => t("An array of all the menu link's parents, starting with the root."),
'type' => 'array',
);
$info['tokens']['menu-link']['root'] = array(
'name' => t('Root'),
'description' => t("The menu link's root."),
'type' => 'menu-link',
);
// Current page tokens.
$info['types']['current-page'] = array(
'name' => t('Current page'),
'description' => t('Tokens related to the current page request.'),
);
$info['tokens']['current-page']['title'] = array(
'description' => t('The title of the current page.'),
);
$info['tokens']['current-page']['url'] = array(
'name' => t('URL'),
'description' => t('The URL of the current page.'),
);
$info['tokens']['current-page']['page-number'] = array(
'name' => t('Page number'),
'description' => t('The page number of the current page when viewing paged lists.'),
);
$info['tokens']['current-page']['query'] = array(
'name' => t('Query string value'),
'description' => t('The value of a specific query string field of the current page.'),
'dynamic' => TRUE,
);
Dave Reid
committed
// URL tokens.
$info['types']['url'] = array(
'name' => t('URL'),
'description' => t('Tokens related to URLs.'),
'needs-data' => 'path',
);
$info['tokens']['url']['path'] = array(
'name' => t('Path'),
'description' => t('The path component of the URL.'),
);
$info['tokens']['url']['relative'] = array(
'name' => t('Relative URL'),
'description' => t('The relative URL.'),
);
$info['tokens']['url']['absolute'] = array(
'name' => t('Absolute URL'),
'description' => t('The absolute URL.'),
);
$info['tokens']['url']['brief'] = array(
'name' => t('Brief URL'),
'description' => t('The URL without the protocol and trailing backslash.'),
);
$info['tokens']['url']['unaliased'] = array(
'name' => t('Unaliased URL'),
'description' => t('The unaliased URL.'),
'type' => 'url',
);
$info['tokens']['url']['args'] = array(
'name' => t('Arguments'),
'description' => t("The specific argument of the current page (e.g. 'arg:1' on the page 'node/1' returns '1')."),
'type' => 'array',
);
Dave Reid
committed
// Array tokens.
$info['types']['array'] = array(
'name' => t('Array'),
'description' => t('Tokens related to arrays of strings.'),
'needs-data' => 'array',
'nested' => TRUE,
Dave Reid
committed
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
);
$info['tokens']['array']['first'] = array(
'name' => t('First'),
'description' => t('The first element of the array.'),
);
$info['tokens']['array']['last'] = array(
'name' => t('Last'),
'description' => t('The last element of the array.'),
);
$info['tokens']['array']['count'] = array(
'name' => t('Count'),
'description' => t('The number of elements in the array.'),
);
$info['tokens']['array']['reversed'] = array(
'name' => t('Reversed'),
'description' => t('The array reversed.'),
'type' => 'array',
);
$info['tokens']['array']['keys'] = array(
'name' => t('Keys'),
'description' => t('The array of keys of the array.'),
'type' => 'array',
);
$info['tokens']['array']['join'] = array(
'name' => t('Imploded'),
'description' => t('The values of the array joined together with a custom string in-between each value.'),
'dynamic' => TRUE,
);
$info['tokens']['array']['value'] = array(
'name' => t('Value'),
'description' => t('The specific value of the array.'),
'dynamic' => TRUE,
);
Dave Reid
committed
Dave Reid
committed
// Random tokens.
$info['types']['random'] = array(
'name' => t('Random'),
'description' => ('Tokens related to random data.'),
);
$info['tokens']['random']['number'] = array(
'name' => t('Number'),
'description' => t('A random number from 0 to @max.', array('@max' => mt_getrandmax())),
);
$info['tokens']['random']['hash'] = array(
'name' => t('Hash'),
'description' => t('A random hash. The possible hashing algorithms are: @hash-algos.', array('@hash-algos' => implode(', ', hash_algos()))),
'dynamic' => TRUE,
);
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
// Define image_with_image_style token type.
if (\Drupal::moduleHandler()->moduleExists('image')) {
$info['types']['image_with_image_style'] = [
'name' => t('Image with image style'),
'needs-data' => 'image_with_image_style',
'module' => 'token',
'nested' => TRUE,
];
// Provide tokens for the ImageStyle attributes.
$info['tokens']['image_with_image_style']['mimetype'] = [
'name' => t('MIME type'),
'description' => t('The MIME type (image/png, image/bmp, etc.) of the image.'),
];
$info['tokens']['image_with_image_style']['filesize'] = [
'name' => t('File size'),
'description' => t('The file size of the image.'),
];
$info['tokens']['image_with_image_style']['height'] = [
'name' => t('Height'),
'description' => t('The height the image, in pixels.'),
];
$info['tokens']['image_with_image_style']['width'] = [
'name' => t('Width'),
'description' => t('The width of the image, in pixels.'),
];
$info['tokens']['image_with_image_style']['uri'] = [
'name' => t('URI'),
'description' => t('The URI to the image.'),
];
$info['tokens']['image_with_image_style']['url'] = [
'name' => t('URL'),
'description' => t('The URL to the image.'),
];
}
Dave Reid
committed
return $info;
}
/**
* Implements hook_tokens().
*/
Sascha Grossenbacher
committed
function token_tokens($type, array $tokens, array $data = array(), array $options = array(), BubbleableMetadata $bubbleable_metadata) {
Dave Reid
committed
$replacements = array();
$url_options = array('absolute' => TRUE);
Sascha Grossenbacher
committed
if (isset($options['langcode'])) {
$url_options['language'] = \Drupal::languageManager()->getLanguage($options['langcode']);
Sascha Grossenbacher
committed
$langcode = $options['langcode'];
}
else {
Sascha Grossenbacher
committed
$langcode = NULL;
}
// Date tokens.
if ($type == 'date') {
$date = !empty($data['date']) ? $data['date'] : REQUEST_TIME;
// @todo Remove when http://drupal.org/node/1173706 is fixed.
$date_format_types = \Drupal::entityTypeManager()->getStorage('date_format')->loadMultiple();
foreach ($tokens as $name => $original) {
if (isset($date_format_types[$name]) && _token_module('date', $name) == 'token') {
Sascha Grossenbacher
committed
$replacements[$original] = format_date($date, $name, '', NULL, $langcode);
// Current date tokens.
// @todo Remove when http://drupal.org/node/943028 is fixed.
if ($type == 'current-date') {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('date', $tokens, array('date' => REQUEST_TIME), $options, $bubbleable_metadata);
}
// Comment tokens.
if ($type == 'comment' && !empty($data['comment'])) {
/* @var \Drupal\comment\CommentInterface $comment */
$comment = $data['comment'];
// Chained token relationships.
Cameron Zemek
committed
if (($url_tokens = \Drupal::token()->findWithPrefix($tokens, 'url'))) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('url', $url_tokens, array('url' => $comment->urlInfo('canonical', ['fragment' => "comment-{$comment->id()}"])), $options, $bubbleable_metadata);
Dave Reid
committed
// Node tokens.
if ($type == 'node' && !empty($data['node'])) {
/* @var \Drupal\node\NodeInterface $node */
Dave Reid
committed
$node = $data['node'];
foreach ($tokens as $name => $original) {
switch ($name) {
Dave Reid
committed
case 'log':
$replacements[$original] = (string) $node->revision_log->value;
Dave Reid
committed
break;
case 'content-type':
$type_name = \Drupal::entityTypeManager()->getStorage('node_type')->load($node->getType())->label();
$replacements[$original] = $type_name;
break;
Dave Reid
committed
}
}
// Chained token relationships.
Hoi Sing Edison Wong
committed
if (($parent_tokens = \Drupal::token()->findWithPrefix($tokens, 'source')) && $source_node = $node->getUntranslated()) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('node', $parent_tokens, array('node' => $source_node), $options, $bubbleable_metadata);
Dave Reid
committed
}
if (($node_type_tokens = \Drupal::token()->findWithPrefix($tokens, 'content-type')) && $node_type = node_type_load($node->bundle())) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('content-type', $node_type_tokens, array('node_type' => $node_type), $options, $bubbleable_metadata);
}
Cameron Zemek
committed
if (($url_tokens = \Drupal::token()->findWithPrefix($tokens, 'url'))) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('url', $url_tokens, array('url' => $node->urlInfo()), $options, $bubbleable_metadata);
}
// Content type tokens.
if ($type == 'content-type' && !empty($data['node_type'])) {
/* @var \Drupal\node\NodeTypeInterface $node_type */
$node_type = $data['node_type'];
foreach ($tokens as $name => $original) {
switch ($name) {
case 'name':
$replacements[$original] = $node_type->label();
break;
case 'machine-name':
$replacements[$original] = $node_type->id();
break;
case 'description':
$replacements[$original] = $node_type->getDescription();
break;
case 'node-count':
$count = \Drupal::entityQueryAggregate('node')
->aggregate('nid', 'COUNT')
->condition('type', $node_type->id())
->execute();
$replacements[$original] = (int) $count;
break;
Dave Reid
committed
case 'edit-url':
$replacements[$original] = $node_type->url('edit-form', $url_options);
Dave Reid
committed
break;
}
}
Dave Reid
committed
}
// Taxonomy term tokens.
if ($type == 'term' && !empty($data['term'])) {
/* @var \Drupal\taxonomy\TermInterface $term */
Dave Reid
committed
$term = $data['term'];
/** @var \Drupal\taxonomy\TermStorageInterface $term_storage */
$term_storage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
Dave Reid
committed
foreach ($tokens as $name => $original) {
switch ($name) {
case 'edit-url':
Rajeshwari Variar
committed
$replacements[$original] = Url::fromRoute('entity.taxonomy_term.edit_form', ['taxonomy_term' => $term->id()], $url_options)->toString();
Dave Reid
committed
break;
Dave Reid
committed
case 'parents':
if ($parents = token_taxonomy_term_load_all_parents($term->id())) {
$replacements[$original] = token_render_array($parents, $options);
}
break;
Dave Reid
committed
case 'root':
$parents = $term_storage->loadAllParents($term->id());
Dave Reid
committed
$root_term = end($parents);
if ($root_term->id() != $term->id()) {
$replacements[$original] = $root_term->label();
Dave Reid
committed
}
break;
Dave Reid
committed
}
}
// Chained token relationships.
Cameron Zemek
committed
if (($url_tokens = \Drupal::token()->findWithPrefix($tokens, 'url'))) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('url', $url_tokens, array('url' => $term->urlInfo()), $options, $bubbleable_metadata);
// [term:parents:*] chained tokens.
Cameron Zemek
committed
if ($parents_tokens = \Drupal::token()->findWithPrefix($tokens, 'parents')) {
if ($parents = token_taxonomy_term_load_all_parents($term->id())) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('array', $parents_tokens, array('array' => $parents), $options, $bubbleable_metadata);
Cameron Zemek
committed
if ($root_tokens = \Drupal::token()->findWithPrefix($tokens, 'root')) {
$parents = $term_storage->loadAllParents($term->id());
Dave Reid
committed
$root_term = end($parents);
if ($root_term->tid != $term->id()) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('term', $root_tokens, array('term' => $root_term), $options, $bubbleable_metadata);
Dave Reid
committed
}
}
Dave Reid
committed
}
// Vocabulary tokens.
if ($type == 'vocabulary' && !empty($data['vocabulary'])) {
$vocabulary = $data['vocabulary'];
foreach ($tokens as $name => $original) {
switch ($name) {
case 'machine-name':
$replacements[$original] = $vocabulary->id();
Dave Reid
committed
break;
case 'edit-url':
Rajeshwari Variar
committed
$replacements[$original] = Url::fromRoute('entity.taxonomy_vocabulary.edit_form', ['taxonomy_vocabulary' => $vocabulary->id()], $url_options)->toString();
Dave Reid
committed
break;
}
}
Dave Reid
committed
}
// File tokens.
if ($type == 'file' && !empty($data['file'])) {
$file = $data['file'];
foreach ($tokens as $name => $original) {
switch ($name) {
$basename = pathinfo($file->uri->value, PATHINFO_BASENAME);
$replacements[$original] = $basename;
$extension = pathinfo($file->uri->value, PATHINFO_EXTENSION);
$replacements[$original] = $extension;
case 'size-raw':
$replacements[$original] = (int) $file->filesize->value;
// User tokens.
if ($type == 'user' && !empty($data['user'])) {
/* @var \Drupal\user\UserInterface $account */
$account = $data['user'];
foreach ($tokens as $name => $original) {
switch ($name) {
case 'picture':
if ($account instanceof UserInterface && $account->hasField('user_picture')) {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = \Drupal::service('renderer');
$output = [
'#theme' => 'user_picture',
'#account' => $account,
];
Sascha Grossenbacher
committed
$replacements[$original] = $renderer->renderPlain($output);
Dave Reid
committed
case 'roles':
Christian López Espínola
committed
$roles = $account->getRoles();
$roles_names = array_combine($roles, $roles);
$replacements[$original] = token_render_array($roles_names, $options);
Dave Reid
committed
break;
}
}
// Chained token relationships.
if ($account instanceof UserInterface && $account->hasField('user_picture') && ($picture_tokens = \Drupal::token()->findWithPrefix($tokens, 'picture'))) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('file', $picture_tokens, array('file' => $account->user_picture->entity), $options, $bubbleable_metadata);
Cameron Zemek
committed
if ($url_tokens = \Drupal::token()->findWithPrefix($tokens, 'url')) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('url', $url_tokens, array('url' => $account->urlInfo()), $options, $bubbleable_metadata);
Cameron Zemek
committed
if ($role_tokens = \Drupal::token()->findWithPrefix($tokens, 'roles')) {
Christian López Espínola
committed
$roles = $account->getRoles();
$roles_names = array_combine($roles, $roles);
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('array', $role_tokens, array('array' => $roles_names), $options, $bubbleable_metadata);
Dave Reid
committed
}
// Current user tokens.
if ($type == 'current-user') {
foreach ($tokens as $name => $original) {
switch ($name) {
case 'ip-address':
$ip = \Drupal::request()->getClientIp();
$replacements[$original] = $ip;
break;
}
}
}
Dave Reid
committed
// Menu link tokens.
if ($type == 'menu-link' && !empty($data['menu-link'])) {
/** @var \Drupal\Core\Menu\MenuLinkInterface $link */
$link = $data['menu-link'];
/** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
$menu_link_manager = \Drupal::service('plugin.manager.menu.link');
if ($link instanceof MenuLinkContentInterface) {
$link = $menu_link_manager->createInstance($link->getPluginId());
}
Dave Reid
committed
foreach ($tokens as $name => $original) {
switch ($name) {
$replacements[$original] = $link->getPluginId();
Dave Reid
committed
break;
case 'title':
$replacements[$original] = $link->getTitle();
Dave Reid
committed
break;
case 'url':
$replacements[$original] = $link->getUrlObject()->setAbsolute()->toString();
Dave Reid
committed
break;
case 'parent':
/** @var \Drupal\Core\Menu\MenuLinkInterface $parent */
if ($link->getParent() && $parent = $menu_link_manager->createInstance($link->getParent())) {
$replacements[$original] = $parent->getTitle();
Dave Reid
committed
}
break;
case 'parents':
if ($parents = token_menu_link_load_all_parents($link->getPluginId())) {
$replacements[$original] = token_render_array($parents, $options);
}
break;
if ($link->getParent() && $parent_ids = array_keys(token_menu_link_load_all_parents($link->getPluginId()))) {
$root = $menu_link_manager->createInstance(array_shift($parent_ids));
$replacements[$original] = $root->getTitle();
Dave Reid
committed
}
}
// Chained token relationships.
/** @var \Drupal\Core\Menu\MenuLinkInterface $parent */
if ($link->getParent() && ($parent_tokens = \Drupal::token()->findWithPrefix($tokens, 'parent')) && $parent = $menu_link_manager->createInstance($link->getParent())) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('menu-link', $parent_tokens, array('menu-link' => $parent), $options, $bubbleable_metadata);
Dave Reid
committed
}
// [menu-link:parents:*] chained tokens.
Cameron Zemek
committed
if ($parents_tokens = \Drupal::token()->findWithPrefix($tokens, 'parents')) {
if ($parents = token_menu_link_load_all_parents($link->getPluginId())) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('array', $parents_tokens, array('array' => $parents), $options, $bubbleable_metadata);
if (($root_tokens = \Drupal::token()->findWithPrefix($tokens, 'root')) && $link->getParent() && $parent_ids = array_keys(token_menu_link_load_all_parents($link->getPluginId()))) {
$root = $menu_link_manager->createInstance(array_shift($parent_ids));
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('menu-link', $root_tokens, array('menu-link' => $root), $options, $bubbleable_metadata);
Cameron Zemek
committed
if ($url_tokens = \Drupal::token()->findWithPrefix($tokens, 'url')) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('url', $url_tokens, array('url' => $link->getUrlObject()), $options, $bubbleable_metadata);
Dave Reid
committed
}
// Current page tokens.
if ($type == 'current-page') {
foreach ($tokens as $name => $original) {
switch ($name) {
$request = \Drupal::request();
$route = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT);
$title = \Drupal::service('title_resolver')->getTitle($request, $route);
$replacements[$original] = $title;
case 'url':
Sascha Grossenbacher
committed
$replacements[$original] = Url::fromRoute('<current>', [], $url_options)->toString();
break;
case 'page-number':
if ($page = \Drupal::request()->query->get('page')) {
// @see PagerDefault::execute()
$pager_page_array = explode(',', $page);
$page = $pager_page_array[0];
}
$replacements[$original] = (int) $page + 1;
break;
}
}
// @deprecated
// [current-page:arg] dynamic tokens.
if ($arg_tokens = \Drupal::token()->findWithPrefix($tokens, 'arg')) {
Sascha Grossenbacher
committed
$path = ltrim(\Drupal::service('path.current')->getPath(), '/');
// Make sure its a system path.
$path = \Drupal::service('path.alias_manager')->getPathByAlias($path);
foreach ($arg_tokens as $name => $original) {
$parts = explode('/', $path);
if (is_numeric($name) && isset($parts[$name])) {
$replacements[$original] = $parts[$name];
}
}
}
// [current-page:query] dynamic tokens.
Cameron Zemek
committed
if ($query_tokens = \Drupal::token()->findWithPrefix($tokens, 'query')) {
foreach ($query_tokens as $name => $original) {
if (\Drupal::request()->query->has($name)) {
$value = \Drupal::request()->query->get($name);
$replacements[$original] = $value;
// Chained token relationships.
Cameron Zemek
committed
if ($url_tokens = \Drupal::token()->findWithPrefix($tokens, 'url')) {
Sascha Grossenbacher
committed
$url = Url::fromRoute('<current>');
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('url', $url_tokens, array('url' => $url), $options, $bubbleable_metadata);
}
}
// URL tokens.
if ($type == 'url' && !empty($data['url'])) {
// To retrieve the correct path, modify a copy of the Url object.
Sascha Grossenbacher
committed
$path = '/' . $path_url->setAbsolute(FALSE)->setOption('fragment', NULL)->getInternalPath();
foreach ($tokens as $name => $original) {
switch ($name) {
case 'path':
Sascha Grossenbacher
committed
$value = !($url->getOption('alias')) ? \Drupal::service('path.alias_manager')->getAliasByPath($path, $langcode) : $path;
$replacements[$original] = $value;
break;
case 'alias':
// @deprecated
Sascha Grossenbacher
committed
$alias = \Drupal::service('path.alias_manager')->getAliasByPath($path, $langcode);
$replacements[$original] = $alias;
break;
case 'absolute':
$replacements[$original] = $url->setAbsolute()->toString();
break;
case 'relative':
$replacements[$original] = $url->setAbsolute(FALSE)->toString();
$replacements[$original] = preg_replace(array('!^https?://!', '!/$!'), '', $url->setAbsolute()->toString());
case 'unaliased':
$unaliased = clone $url;
$replacements[$original] = $unaliased->setAbsolute()->setOption('alias', TRUE)->toString();
case 'args':
Sascha Grossenbacher
committed
$value = !($url->getOption('alias')) ? \Drupal::service('path.alias_manager')->getAliasByPath($path, $langcode) : $path;
$replacements[$original] = token_render_array(explode('/', $value), $options);
// [url:args:*] chained tokens.
if ($arg_tokens = \Drupal::token()->findWithPrefix($tokens, 'args')) {
Sascha Grossenbacher
committed
$value = !($url->getOption('alias')) ? \Drupal::service('path.alias_manager')->getAliasByPath($path, $langcode) : $path;
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('array', $arg_tokens, array('array' => explode('/', ltrim($value, '/'))), $options, $bubbleable_metadata);
}
// [url:unaliased:*] chained tokens.
Cameron Zemek
committed
if ($unaliased_tokens = \Drupal::token()->findWithPrefix($tokens, 'unaliased')) {
$url->setOption('alias', TRUE);
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('url', $unaliased_tokens, array('url' => $url), $options, $bubbleable_metadata);
}
if (!empty($data[$type]) && $entity_type = \Drupal::service('token.entity_mapper')->getEntityTypeForTokenType($type)) {
/* @var \Drupal\Core\Entity\EntityInterface $entity */
foreach ($tokens as $name => $original) {
switch ($name) {
if (_token_module($type, 'url') == 'token' && $url = $entity->url()) {
$replacements[$original] = $url;
case 'original':
if (_token_module($type, 'original') == 'token' && !empty($entity->original)) {
$label = $entity->original->label();
$replacements[$original] = $label;
// [entity:url:*] chained tokens.
Cameron Zemek
committed
if (($url_tokens = \Drupal::token()->findWithPrefix($tokens, 'url')) && _token_module($type, 'url') == 'token') {
Ashwin Shaharkar
committed
$replacements += \Drupal::token()->generate('url', $url_tokens, array('url' => $entity->toUrl()), $options, $bubbleable_metadata);
Dave Reid
committed
// [entity:original:*] chained tokens.
Cameron Zemek
committed
if (($original_tokens = \Drupal::token()->findWithPrefix($tokens, 'original')) && _token_module($type, 'original') == 'token' && !empty($entity->original)) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate($type, $original_tokens, array($type => $entity->original), $options, $bubbleable_metadata);
// Pass through to an generic 'entity' token type generation.
$entity_data = array(
'entity_type' => $entity_type,
'entity' => $entity,
'token_type' => $type,
);
// @todo Investigate passing through more data like everything from entity_extract_ids().
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('entity', $tokens, $entity_data, $options, $bubbleable_metadata);
Dave Reid
committed
// Array tokens.
if ($type == 'array' && !empty($data['array']) && is_array($data['array'])) {
$array = $data['array'];
$sort = isset($options['array sort']) ? $options['array sort'] : TRUE;
$keys = token_element_children($array, $sort);
Sascha Grossenbacher
committed
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = \Drupal::service('renderer');
Dave Reid
committed
foreach ($tokens as $name => $original) {
switch ($name) {
case 'first':
$value = $array[$keys[0]];
Sascha Grossenbacher
committed
$value = is_array($value) ? $renderer->renderPlain($value) : (string) $value;
$replacements[$original] = $value;
Dave Reid
committed
break;
case 'last':
$value = $array[$keys[count($keys) - 1]];
Sascha Grossenbacher
committed
$value = is_array($value) ? $renderer->renderPlain($value) : (string) $value;
$replacements[$original] =$value;
Dave Reid
committed
break;
case 'count':
$replacements[$original] = count($keys);
Dave Reid
committed
break;
case 'keys':
$replacements[$original] = token_render_array($keys, $options);
break;
case 'reversed':
$reversed = array_reverse($array, TRUE);
$replacements[$original] = token_render_array($reversed, $options);
break;
case 'join':
$replacements[$original] = token_render_array($array, array('join' => '') + $options);
break;
}
}
// [array:value:*] dynamic tokens.
Cameron Zemek
committed
if ($value_tokens = \Drupal::token()->findWithPrefix($tokens, 'value')) {
Dave Reid
committed
foreach ($value_tokens as $key => $original) {
if ($key[0] !== '#' && isset($array[$key])) {
Dave Reid
committed
$replacements[$original] = token_render_array_value($array[$key], $options);
}
}
}
// [array:join:*] dynamic tokens.
Cameron Zemek
committed
if ($join_tokens = \Drupal::token()->findWithPrefix($tokens, 'join')) {
Dave Reid
committed
foreach ($join_tokens as $join => $original) {
$replacements[$original] = token_render_array($array, array('join' => $join) + $options);
}
}
// [array:keys:*] chained tokens.
Cameron Zemek
committed
if ($key_tokens = \Drupal::token()->findWithPrefix($tokens, 'keys')) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('array', $key_tokens, array('array' => $keys), $options, $bubbleable_metadata);
Dave Reid
committed
}
// [array:reversed:*] chained tokens.
Cameron Zemek
committed
if ($reversed_tokens = \Drupal::token()->findWithPrefix($tokens, 'reversed')) {
Sascha Grossenbacher
committed
$replacements += \Drupal::token()->generate('array', $reversed_tokens, array('array' => array_reverse($array, TRUE)), array('array sort' => FALSE) + $options, $bubbleable_metadata);
Dave Reid
committed
}
// @todo Handle if the array values are not strings and could be chained.
}
Dave Reid
committed
// Random tokens.
if ($type == 'random') {
foreach ($tokens as $name => $original) {
switch ($name) {
case 'number':
$replacements[$original] = mt_rand();
break;
}
}
// [custom:hash:*] dynamic token.
Cameron Zemek
committed
if ($hash_tokens = \Drupal::token()->findWithPrefix($tokens, 'hash')) {
Dave Reid
committed
$algos = hash_algos();
foreach ($hash_tokens as $name => $original) {
if (in_array($name, $algos)) {
Christian López Espínola
committed
$replacements[$original] = hash($name, Crypt::randomBytes(55));
Dave Reid
committed
}
}
}
}
// If $type is a token type, $data[$type] is empty but $data[$entity_type] is
// not, re-run token replacements.
if (empty($data[$type]) && ($entity_type = \Drupal::service('token.entity_mapper')->getEntityTypeForTokenType($type)) && $entity_type != $type && !empty($data[$entity_type]) && empty($options['recursive'])) {
Dave Reid
committed
$data[$type] = $data[$entity_type];
Dave Reid
committed
$options['recursive'] = TRUE;
Sascha Grossenbacher
committed
$replacements += \Drupal::moduleHandler()->invokeAll('tokens', array($type, $tokens, $data, $options, $bubbleable_metadata));
Dave Reid
committed
}
Dave Reid
committed
// If the token type specifics a 'needs-data' value, and the value is not
// present in $data, then throw an error.
if (!empty($GLOBALS['drupal_test_info']['test_run_id'])) {
// Only check when tests are running.
Hussain Abbas
committed
$type_info = \Drupal::token()->getTypeInfo($type);
if (!empty($type_info['needs-data']) && !isset($data[$type_info['needs-data']])) {
trigger_error(t('Attempting to perform token replacement for token type %type without required data', array('%type' => $type)), E_USER_WARNING);
}
Dave Reid
committed
}
Dave Reid
committed
return $replacements;
}
/**
Dave Reid
committed
* Implements hook_token_info() on behalf of book.module.
Dave Reid
committed
function book_token_info() {
$info['tokens']['node']['book'] = array(
'name' => t('Book'),
'description' => t('The book page associated with the node.'),
'type' => 'menu-link',
);